使用Python和Matplotlib模拟3D海浪动画

使用Python和Matplotlib模拟3D海浪动画

在计算机图形学和动画领域,模拟逼真的海洋表面一直是一个具有挑战性的问题。本文将介绍如何使用Python的Matplotlib库和Gerstner波浪模型,创建一个动态的3D海浪动画。通过叠加多个波浪,我们可以生成复杂而真实的海洋效果。

前言

Gerstner波浪模型是一种经典的海浪模拟方法,具有计算简单和效果逼真的特点。它通过对海面上的每个点施加正弦波的位移,来模拟波浪的起伏。本文将详细解释代码的实现过程,并提供可运行的示例代码。

环境准备

首先,确保您的环境中安装了以下库:

  • numpy
  • matplotlib

可以使用以下命令安装:

pip install numpy matplotlib

代码实现

1. 导入必要的库

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
  • numpy用于数值计算和数组操作。
  • matplotlib.pyplot用于绘制图形。
  • matplotlib.animation用于创建动画。

2. 设置海洋网格参数

nx, ny = 200, 200  # 网格大小
x = np.linspace(-10, 10, nx)
y = np.linspace(-10, 10, ny)
X, Y = np.meshgrid(x, y)
  • 创建一个二维网格,用于表示海洋表面的坐标点。
  • 网格越密集,生成的海浪细节越丰富。

3. 设置Gerstner波浪参数

wave_amplitude = 1.0     # 波浪振幅
wave_length = 5.0        # 波长
wave_speed = 1.0         # 波速
num_waves = 5            # 波浪数量
directions = np.linspace(0, 2 * np.pi, num_waves, endpoint=False)
phases = np.random.uniform(0, 2 * np.pi, num_waves)
  • num_waves决定了叠加多少个波浪,以增加海浪的复杂度。
  • directions定义了每个波浪的传播方向,均匀分布在0到2π之间。
  • phases为每个波浪生成一个随机的初始相位。

4. 创建图形和3D坐标轴

fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
  • 创建一个图形窗口,并添加一个3D坐标轴用于绘制海浪表面。

5. 设置绘图参数

ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_zlim(-3, 3)
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.view_init(elev=30, azim=225)
  • 设置坐标轴的范围和视角。
  • 隐藏坐标轴的刻度,使图形更加简洁。

6. 定义动画更新函数

def animate(frame):ax.clear()Z = np.zeros_like(X)t = frame / 20.0  # 时间参数for i in range(num_waves):direction = directions[i]phase = phases[i]k = 2 * np.pi / wave_lengthomega = k * wave_speeddir_x = np.cos(direction)dir_y = np.sin(direction)phi = k * (dir_x * X + dir_y * Y) - omega * t + phaseZ += wave_amplitude / num_waves * np.cos(phi)surf = ax.plot_surface(X, Y, Z, cmap='Blues', linewidth=0, antialiased=True)ax.set_xlim(-10, 10)ax.set_ylim(-10, 10)ax.set_zlim(-3, 3)ax.set_xticks([])ax.set_yticks([])ax.set_zticks([])ax.view_init(elev=30, azim=225)return surf,
  • animate函数用于更新每一帧的图像。
  • t是时间参数,控制波浪的动态变化。
  • 在循环中,叠加多个Gerstner波浪。
  • 使用ax.plot_surface绘制3D海浪表面。

7. 创建动画

ani = animation.FuncAnimation(fig, animate, frames=200, interval=30, blit=False)
  • 使用FuncAnimation创建动画。
  • frames=200表示总共生成200帧。
  • interval=30表示每帧之间的间隔为30毫秒。

8. 显示动画

plt.show()
  • 显示生成的海浪动画。

运行效果

运行上述代码后,将会出现一个窗口,展示动态的3D海浪动画。波浪在不断地起伏,模拟了真实的海洋表面。由于叠加了多个不同方向和相位的波浪,海浪看起来更加复杂和逼真。
在这里插入图片描述下面是-gif动图
在这里插入图片描述

深入理解Gerstner波浪模型

Gerstner波浪模型通过对海面上的每个点施加位移,来模拟波浪的传播。对于二维情况下,海面上某一点的位移可以表示为:

Z = A cos ⁡ ( k x − ω t + ϕ ) Z = A \cos(kx - \omega t + \phi) Z=Acos(kxωt+ϕ)

  • ( A ):振幅
  • ( k ):波数,( k = \frac{2\pi}{\lambda} ),其中( \lambda )为波长
  • ( \omega ):角频率,( \omega = k \cdot c ),其中( c )为波速
  • ( \phi ):初始相位

在代码中,我们对多个波浪进行叠加,每个波浪具有不同的传播方向和初始相位。这使得海浪的形状更加复杂多变。

参数调整

您可以通过修改以下参数来改变海浪的效果:

  • wave_amplitude:增大振幅会使波浪更高。
  • wave_length:改变波长会影响波浪的密集程度。
  • wave_speed:改变波速会影响波浪传播的速度。
  • num_waves:增加波浪数量会使海浪更复杂。

例如,将波浪数量增加到10:

num_waves = 10

运行后,您会发现海浪的细节更加丰富。
完整代码如下:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D# 设置海洋网格参数
nx, ny = 200, 200  # 网格大小,值越大,细节越丰富
x = np.linspace(-10, 10, nx)
y = np.linspace(-10, 10, ny)
X, Y = np.meshgrid(x, y)# Gerstner波浪参数
wave_amplitude = 1.0     # 波浪振幅
wave_length = 5.0        # 波长
wave_speed = 1.0         # 波速
num_waves = 5            # 波浪数量,叠加多个波浪以增加复杂度
directions = np.linspace(0, 2 * np.pi, num_waves, endpoint=False)  # 波浪传播方向
phases = np.random.uniform(0, 2 * np.pi, num_waves)                # 随机初始相位# 创建图形和3D坐标轴
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')# 设置绘图参数
ax.set_xlim(-10, 10)
ax.set_ylim(-10, 10)
ax.set_zlim(-3, 3)
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
ax.view_init(elev=30, azim=225)  # 视角角度,可根据需要调整# 初始化海浪高度
Z = np.zeros_like(X)# 动画更新函数
def animate(frame):ax.clear()Z = np.zeros_like(X)t = frame / 20.0  # 时间参数,控制动画速度# 叠加多个Gerstner波浪for i in range(num_waves):direction = directions[i]phase = phases[i]k = 2 * np.pi / wave_length  # 波数omega = k * wave_speed       # 角频率# 波浪传播方向的单位向量dir_x = np.cos(direction)dir_y = np.sin(direction)# 计算偏移phi = k * (dir_x * X + dir_y * Y) - omega * t + phaseZ += wave_amplitude / num_waves * np.cos(phi)# 绘制海浪表面surf = ax.plot_surface(X, Y, Z, cmap='Blues', linewidth=0, antialiased=True)# 设置绘图参数ax.set_xlim(-10, 10)ax.set_ylim(-10, 10)ax.set_zlim(-3, 3)ax.set_xticks([])ax.set_yticks([])ax.set_zticks([])ax.view_init(elev=30, azim=225)return surf,# 创建动画
ani = animation.FuncAnimation(fig, animate, frames=200, interval=30, blit=False)# 显示动画
plt.show()

结论

本文介绍了如何使用Python和Matplotlib库,基于Gerstner波浪模型,创建一个动态的3D海浪动画。通过对代码的逐步讲解,相信您已经理解了其中的原理和实现方法。您可以尝试调整参数,甚至扩展代码,实现更多有趣的效果。

参考资料

  • Gerstner Waves on Wikipedia
  • Matplotlib 3D Surface Plot Documentation
  • NumPy Meshgrid Function

希望本文对您有所帮助,祝您在数据可视化和动画制作的道路上取得更多成果!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/58211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Fargo】14: sockaddr_in 、 sockaddr 、sockaddr_storage 区别及转换

sockaddr_in 和 sockaddr struct recv_addr_; uv_ip4_addr(ip.c_str(), port, &recv_addr); 这里libuv用的是sockaddr_in ,mediasoup用的是sockaddr,二者有什么区别,可以直接转换么sockaddr 看起来更为通用 差异和特定的用途 在网络编程中,sockaddr_in 和 sockaddr 是…

HarmonyOS ArkTS与C++数据类型转换

1. HarmonyOS ArkTS与C数据类型转换 本文介绍了C与TS各自数据类型与互相之间的数据类型转换,在需要使用C模块时可以快速上手对各种数据类型进行转换。 1.1. 概述 HarmonyOS的主力开发语言是ArkTS,也提供了C语言的支持,对于一些能力&#xff…

react mackDowan 渲染文本,图片,视频

需要安装:react-markdown;remark-gfm "react-markdown": "^9.0.1", "remark-gfm": "^4.0.0", import { useEffect, useState } from react; import ReactMarkdown, { Components } from react-markdown;functio…

iOS_响应者链 Responder Chain

文章目录 简述Hit-Test 机制 (找到最佳响应者)响应者链 Responder chain应用获取当前View的控制器对象:手势穿透: 简述 传递链: 系统向离用户最近的view传递。 UIKit –> active app’s event queue –> window …

【设计模式系列】迭代器模式(七)

一、什么是迭代器模式 迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供一种方法来顺序访问一个聚合对象中的各个元素,而不暴露其内部的表示。迭代器模式将集合的遍历过程封装在一个独立的迭代器对象中,这样…

纯GO语言开发RTSP流媒体服务器-RTSP推流直播、本地保存录像、录像回放、http-flv及hls协议分发

温馨提示:我们分享的文章是给需要的人,不需要的人请绕过,文明浏览,误恶语伤人! 前言 在软件开发中遇到使用流媒体音视频的行业比较多,如安防监控系统、无人机巡逻视频上云处理、直播平台、教育与企业培训…

如何快速使用Cesium完成项目

要快速使用Cesium完成项目,可以按照以下步骤进行: 学习基础知识: 首先,了解Cesium的基本概念和功能。可以通过阅读Cesium的官方文档和一些入门教程来掌握基础知识。例如,可以参考“Cesium速成教程:一小时入…

代码随想录(十二)——图论

并查集 并查集主要有三个功能。 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上判断两个节点是否在…

阿里云物联网的通信方式

阿里云物联网通信的两种方式,一个是物模型(分为服务,事件,属性),一个是自定义topic(要另外设置数据流转) 1.使用产品内的功能定义,(其实也就是Topic中定义好的…

新手逆向实战三部曲之三——通过进入关键call追码注册软件(进阶)

教程开始: 通过前两次的学习,是不是感觉逆向也蛮有意思的呢,感兴趣的同学可以先看看前二次的内容再继续向下学习 新手逆向实战三部曲之一 新手逆向实战三部曲之二 有了上次爆破的基础,这次便省力了许多,这次从载入开始…

STM32第15章 RCC-使用HSE/HSI配置时钟

时间:2024.10.21-10.23 参考资料: 《零死角玩转STM32》“RCC-使用HSE/HIS配置时钟”章节 TIPS: 从前面的历程中我们知道,程序在启动的时候会执行汇编文件,汇编文件里会调用System_Init(固件库编程的函数),它里面会把时钟初始化成72M,因此前面我们在用固件库写程序的…

数据结构:“小猫钓鱼游戏”

一:题目 栈和队列的综合应用:“小猫钓鱼”的游戏规则是:将一副扑克牌平均分成两份,每人拿一份。玩家甲先拿出手中的第一张扑克牌放在桌上,然后玩家乙也拿出手中的第一张扑克牌,并放在玩家甲刚打出的扑克牌的…

采用Excel作为可视化设计器的开源规则引擎 NopRule

决策树和决策矩阵是业务人员可以直观理解的复杂IF-ELSE逻辑表达形式,也是规则引擎中最常用、最有用的部分。常见的规则引擎如Drools虽然提供了更加丰富的功能特性集, 特别是所谓的RETE算法可以用于高效复用多次重复出现的表达式片段,但在实际…

SpringSecurity + Jwt权限校验,接口调用403 Forbidden问题排查与解决

问题背景:部分接口调用正常,部分接口调用报403Forbidden,postman不显示具体报错信息。 问题描述: 接口调用报错,经排查,权限校验认证通过,可以进入接口,但是在执行过程中&#xff0…

深入了解 Android 中的命名空间:`xmlns:tools` 和其他常见命名空间

在 Android 开发中,xmlns (.xml的namespace)命名空间是一个非常重要的概念。通过引入不同的命名空间,可以使用不同的属性来设计布局、设置工具属性或者支持自定义视图等。除了 xmlns:tools 以外,还有很多常见的命名空间…

从0到1学习node.js(npm)

文章目录 一、NPM的生产环境与开发环境二、全局安装三、npm安装指定版本的包四、删除包 五、用npm发布一个包六、修改和删除npm包1、修改2、删除 一、NPM的生产环境与开发环境 类型命令补充生产依赖npm i -S uniq-S 等效于 --save -S是默认选项npm i -save uniq包的信息保存在…

webpack 老项目升级记录:从 node-sass 限制的的 node v8 提升至支持 ^node v22

老项目简介 技术框架 vue 2.5.17webpack 4.16.5"webpack-cli": "3.1.0""node-sass": "^4.7.2" 几个阶段 第一步:vue2 升级到最新 第一步:升级 vue2 至最新版本,截止到目前(2024-10-…

ATom:加州理工学院化学电离质谱仪(CIT-CIMS)的现场数据,V2版

目录 简介 摘要 代码 引用 网址推荐 知识星球 机器学习 ATom: In Situ Data from Caltech Chemical Ionization Mass Spectrometer (CIT-CIMS), V2 ATom:加州理工学院化学电离质谱仪(CIT-CIMS)的现场数据,V2版 简介 该数…

trueNas 24.10 docker配置文件daemon.json无法修改(重启被覆盖)解决方案

前言 最近听说truenas的24.10版本开放docker容器解决方案放弃了原来难用的k3s,感觉非常巴适,就研究了一下,首先遇到无法迁移老系统应用问题比较好解决,使用sudo登录ssh临时修改daemon.json重启docker后进行docker start 容器即可…

十一、数据库配置

一、Navicat配置 这个软件需要破解 密码是:123456; 新建连接》新建数据库 创建一个表 保存出现名字设置 双击打开 把id设置为自动递增 这里就相当于每一次向数据库添加一个语句,会自动增长id一次 二、数据库的增删改查 1、Vs 建一个控…