吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 744|回复: 40
上一主题 下一主题
收起左侧

[Python 原创] Python绘制闪电轨迹

  [复制链接]
跳转到指定楼层
楼主
icer233 发表于 2024-11-16 15:45 回帖奖励
本来想生成一个闪电轨迹的图像,思路是取两点,坐标塞进列表,计算距离,如果大于指定值就计算这两点的中点并旦在一定范围内偏移(范国与两点距离有关),然后把中点坐标赛回列表。循环执行直到列表中所有相邻点的距离小于指定值,然后遍历列表生成粒子。


闪电轨迹本身就是有棱有角的,不能太平滑,也不能有奇怪的凸起。
写了个代码发现生成的不太像,倒像是一个国家的边境线了。


其中17 18行的代码是用来做随机偏移的,可以调整这4个参数以及35行的终止距离。


[Python] 纯文本查看 复制代码
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()

免费评分

参与人数 7吾爱币 +9 热心值 +7 收起 理由
xinchi875 + 1 热心回复!
wangxb2555 + 1 热心回复!
jjxuanyuan + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
LanJetmew + 1 + 1 用心讨论,共获提升!
hjxhjxjx + 1 + 1 用心讨论,共获提升!
WD9521 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

来自 25#
lyzxx 发表于 2024-11-16 23:34
[Python] 纯文本查看 复制代码
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)  # 强制显示图形

myplot.png (46.43 KB, 下载次数: 0)

myplot.png

免费评分

参与人数 2吾爱币 +4 热心值 +2 收起 理由
go4399 + 1 + 1 用心讨论,共获提升!
苏紫方璇 + 3 + 1 用心讨论,共获提升!

查看全部评分

来自 35#
vincent327 发表于 2024-11-19 15:01
本帖最后由 vincent327 于 2024-11-19 15:04 编辑

哈哈哈 挺好玩的 用你的代码 然后让Cursor使用composer润色了下 成这样了!
[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()

Figure_1.png (59.22 KB, 下载次数: 2)

Figure_1.png
沙发
Wisdom_xiaogui 发表于 2024-11-16 16:38
3#
go4399 发表于 2024-11-16 16:43
上传个图,看看效果
4#
hjxhjxjx 发表于 2024-11-16 17:58
go4399 发表于 2024-11-16 16:43
上传个图,看看效果

试试效果
没安装库的先安装:
[Bash shell] 纯文本查看 复制代码
python -m pip install matplotlib  -i https://mirrors.aliyun.com/pypi/simple/

5#
Open74 发表于 2024-11-16 18:01
运行效果大概就是这样,实际原理就是简单的生成一段随机路径模仿闪电轨迹;楼主可以精进一点,比如闪电加上分支,颜色等

4cb1d065b9d2c2b5accbe8682144f45.png (29.86 KB, 下载次数: 0)

4cb1d065b9d2c2b5accbe8682144f45.png
6#
mebyan 发表于 2024-11-16 18:27
Open74 发表于 2024-11-16 18:01
运行效果大概就是这样,实际原理就是简单的生成一段随机路径模仿闪电轨迹;楼主可以精进一点,比如闪电加上 ...

要做成一个动态图,让轨迹从上往下快速形成才能模拟出闪电。最好再加上雨天背景图和雷声音频。
7#
 楼主| icer233 发表于 2024-11-16 18:32 |楼主
hjxhjxjx 发表于 2024-11-16 17:58
试试效果
没安装库的先安装:
[mw_shl_code=bash,true]python -m pip install matplotlib  -i https:// ...

我觉得这个轨迹还是有点奇怪,要再调参数
8#
 楼主| icer233 发表于 2024-11-16 18:38 |楼主
Open74 发表于 2024-11-16 18:01
运行效果大概就是这样,实际原理就是简单的生成一段随机路径模仿闪电轨迹;楼主可以精进一点,比如闪电加上 ...

分支的话在生成的轨迹上取一点,在空白的地方取一点再用一下写好的函数生成一条轨迹就行了
9#
 楼主| icer233 发表于 2024-11-16 18:39 |楼主
mebyan 发表于 2024-11-16 18:27
要做成一个动态图,让轨迹从上往下快速形成才能模拟出闪电。最好再加上雨天背景图和雷声音频。

我只是在研究模拟出合理的轨迹图不是闪电的过程
10#
ruanxiaoqi 发表于 2024-11-16 19:34
向你学习!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 16:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表