[Python] 纯文本查看 复制代码
import matplotlib.pyplot as plt
import random
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
def generate_lightning(start_point, end_point, max_distance):
"""
生成闪电的主要路径
参数:
start_point: 起始点坐标 (x, y)
end_point: 终点坐标 (x, y)
max_distance: 两点之间的最大允许距离
返回:
points: 闪电路径的所有点坐标列表
"""
points = [start_point, end_point]
while True:
all_within_max_distance = True
new_points = []
for i in range(len(points) - 1):
p1 = points[i]
p2 = points[i + 1]
# 计算两点之间的距离
distance = ((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2) ** 0.5
if distance > max_distance:
all_within_max_distance = False
# 计算中点
midpoint = ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2)
# 添加随机偏移,使闪电更自然
offset_x = random.uniform(-distance / 4, distance / 4)
offset_y = random.uniform(-distance / 4, distance / 4)
new_midpoint = (midpoint[0] + offset_x, midpoint[1] + offset_y)
new_points.extend([p1, new_midpoint])
else:
new_points.append(p1)
new_points.append(points[-1])
points = new_points
if all_within_max_distance:
break
return points
def add_forks(main_points, max_distance, num_forks, depth=1):
"""
为主闪电添加分叉
参数:
main_points: 主闪电路径的点列表
max_distance: 两点之间的最大允许距离
num_forks: 分叉数量
depth: 递归深度,控制子分叉的生成
返回:
fork_list: 所有分叉的点坐标列表
"""
fork_list = []
for _ in range(num_forks):
# 选择主干上的点作为分叉起点(避开起始部分)
available_points = main_points[len(main_points)//4:]
point_on_main = random.choice(available_points)
# 生成分叉的终点
x_offset = random.uniform(-15, 15)
y_offset = random.uniform(-15, 0) # 只向下分叉
fork_end_point = (point_on_main[0] + x_offset, point_on_main[1] + y_offset)
# 生成分叉路径
fork_points = generate_lightning(point_on_main, fork_end_point, max_distance)
fork_list.append(fork_points)
# 递归生成子分叉
if depth > 1:
sub_forks = add_forks(fork_points, max_distance, random.randint(1, 1), depth - 1)
fork_list.extend(sub_forks)
return fork_list
# 定义闪电的颜色渐变
colors = [(0.1, 0.1, 0.3), (0.4, 0.4, 1), (0.7, 0.7, 1), (1, 1, 1)]
n_bins = 100
cmap = LinearSegmentedColormap.from_list('custom_lightning', colors, N=n_bins)
# 设置闪电的基本参数
start_point = (0, 150) # 起始点
end_point = (0, 0) # 终点
max_distance = 2 # 最大分段距离
# 生成主闪电路径
main_lightning = generate_lightning(start_point, end_point, max_distance)
# 设置分叉参数并生成分叉
num_forks = 4 # 分叉数量
fork_depth = 2 # 分叉深度
forks = add_forks(main_lightning, max_distance, num_forks, fork_depth)
# 创建图形
plt.figure(figsize=(10, 15))
plt.style.use('dark_background') # 使用深色背景
# 创建背景渐变效果
x = np.linspace(-50, 50, 100)
y = np.linspace(-10, 160, 170)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X**2 + (Y-80)**2)/3000) # 创建光晕效果
plt.imshow(Z, extent=[-50, 50, -10, 160], cmap='gray', alpha=0.3)
def plot_with_glow(x, y, color, linewidth, alpha):
"""
绘制带发光效果的线条
参数:
x, y: 线条的坐标
color: 线条颜色
linewidth: 线条宽度
alpha: 透明度
"""
for glow_width, glow_alpha in [(linewidth*3, 0.1), (linewidth*2, 0.2), (linewidth, alpha)]:
plt.plot(x, y, color=color, linewidth=glow_width, alpha=glow_alpha)
# 绘制主闪电
n_points = len(main_lightning)
linewidths_main = np.linspace(4, 1, n_points - 1) # 渐变的线条宽度
for i in range(n_points - 1):
x_main = [main_lightning[i][0], main_lightning[i + 1][0]]
y_main = [main_lightning[i][1], main_lightning[i + 1][1]]
color = cmap(random.uniform(0.7, 1.0)) # 随机选择颜色
plot_with_glow(x_main, y_main, color, linewidths_main[i], 0.9)
# 绘制分叉
for fork in forks:
n_fork_points = len(fork)
linewidths_fork = np.linspace(2, 0.5, n_fork_points - 1) # 分叉的线条宽度
for i in range(n_fork_points - 1):
x_fork = [fork[i][0], fork[i + 1][0]]
y_fork = [fork[i][1], fork[i + 1][1]]
color = cmap(random.uniform(0.5, 0.9)) # 随机选择颜色
plot_with_glow(x_fork, y_fork, color, linewidths_fork[i], 0.7)
# 调整显示范围
x_all = [p[0] for p in main_lightning] + [p[0] for fork in forks for p in fork]
y_all = [p[1] for p in main_lightning] + [p[1] for fork in forks for p in fork]
margin = 20
plt.xlim(min(x_all) - margin, max(x_all) + margin)
plt.ylim(min(y_all) - margin, max(y_all) + margin)
# 关闭坐标轴显示
plt.axis('off')
# 显示图形
plt.show()