2025年3月15日 星期六 甲辰(龙)年 月十四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

Python绘制闪电轨迹

时间:12-29来源:作者:点击数:33
城东书院 www.cdsy.xyz

本来想生成一个闪电轨迹的图像,思路是取两点,坐标塞进列表,计算距离,如果大于指定值就计算这两点的中点并旦在一定范围内偏移(范国与两点距离有关),然后把中点坐标赛回列表。循环执行直到列表中所有相邻点的距离小于指定值,然后遍历列表生成粒子。

闪电轨迹本身就是有棱有角的,不能太平滑,也不能有奇怪的凸起。

写了个代码发现生成的不太像,倒像是一个国家的边境线了。

其中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()

 

城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐