本来想生成一个闪电轨迹的图像,思路是取两点,坐标塞进列表,计算距离,如果大于指定值就计算这两点的中点并旦在一定范围内偏移(范国与两点距离有关),然后把中点坐标赛回列表。循环执行直到列表中所有相邻点的距离小于指定值,然后遍历列表生成粒子。
闪电轨迹本身就是有棱有角的,不能太平滑,也不能有奇怪的凸起。
写了个代码发现生成的不太像,倒像是一个国家的边境线了。
其中17 18行的代码是用来做随机偏移的,可以调整这4个参数以及35行的终止距离。
(代码陆续修补)
代码一
- import matplotlib.pyplot as plt
- import random
-
-
- def generate_lightning(start_point, end_point, max_distance):
- 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 / 12, distance / 4)
- offset_y = random.uniform(-distance / 6, distance / 6)
- 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
-
-
- # 设置起始点和终点坐标以及最大距离
- start_point = (0, 0)
- end_point = (100, 100)
- max_distance = 8
-
- # 生成闪电轨迹的点列表
- lightning_points = generate_lightning(start_point, end_point, max_distance)
-
- # 绘制闪电
- x_coords, y_coords = zip(*lightning_points)
- plt.plot(x_coords, y_coords, 'b-')
-
- # 设置图形的坐标轴范围等
- plt.xlim(min(x_coords) - 1, max(x_coords) + 1)
- plt.ylim(min(y_coords) - 1, max(y_coords) + 1)
-
- # 显示图形
- plt.show()
代码二
- import matplotlib.pyplot as plt
- import random
-
-
- def generate_lightning(start_point, end_point, max_distance):
- 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 / 5, distance / 5)
- offset_y = random.uniform(-distance / 5, distance / 5)
- 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):
- fork_list = []
- for _ in range(num_forks):
- # 随机选择一个主闪电上的点作为分叉的起点
- point_on_main = random.choice(main_points)
- # 随机生成一个偏移的分叉终点
- x_offset = random.uniform(-20, 20)
- y_offset = random.uniform(-20, 20)
- 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, 2), depth - 1)
- fork_list.extend(sub_forks)
- return fork_list
-
-
- # 设置起始点和终点坐标以及最大距离
- start_point = (50, 100)
- end_point = (50, 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=(8, 12))
- plt.style.use('dark_background') # 设置黑色背景
-
- # 绘制主闪电
- x_main, y_main = zip(*main_lightning)
- plt.plot(x_main, y_main, color='black', linewidth=1.5, alpha=0.9, label="Main Lightning")
-
- # 绘制分叉
- for fork in forks:
- x_fork, y_fork = zip(*fork)
- plt.plot(x_fork, y_fork, color='black', linewidth=1, alpha=0.6)
-
- # 动态调整坐标范围
- 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]
- plt.xlim(min(x_all) - 10, max(x_all) + 10)
- plt.ylim(min(y_all) - 10, max(y_all) + 10)
-
- # 设置图形
- plt.axis('off') # 关闭坐标轴显示
- plt.legend()
- plt.show(block=True) # 强制显示图形
代码三(用ai优化了一下)
- import matplotlib.pyplot as plt
- import random
- import numpy as np
-
-
- def generate_lightning(start_point, end_point, max_distance):
- 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 / 5, distance / 5)
- offset_y = random.uniform(-distance / 5, distance / 5)
- 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):
- fork_list = []
- for _ in range(num_forks):
- point_on_main = random.choice(main_points)
- x_offset = random.uniform(-20, 20)
- y_offset = random.uniform(-20, 20)
- 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, 2), depth - 1)
- fork_list.extend(sub_forks)
- return fork_list
-
-
- # 设置起始点和终点坐标以及最大距离
- start_point = (50, 100)
- end_point = (50, 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=(8, 12))
- plt.style.use('dark_background')
-
- # 计算主闪电的线宽变化
- n_points = len(main_lightning)
- linewidths_main = np.linspace(3, 0.5, 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]]
- plt.plot(x_main, y_main, color='blue', linewidth=linewidths_main[i], alpha=0.9)
-
- # 计算分叉的线宽变化
- for fork in forks:
- n_fork_points = len(fork)
- linewidths_fork = np.linspace(1.5, 0.3, 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]]
- plt.plot(x_fork, y_fork, color='blue', linewidth=linewidths_fork[i], alpha=0.6)
-
- # 动态调整坐标范围
- 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]
- plt.xlim(min(x_all) - 10, max(x_all) + 10)
- plt.ylim(min(y_all) - 10, max(y_all) + 10)
-
- plt.axis('off')
- plt.legend()
- plt.show(block=True)
代码四(让Cursor使用composer润色了下)
- 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()