EG/plugins/user/fluid_simulation/water/wave_system.py
2025-12-12 16:16:15 +08:00

808 lines
28 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
波浪系统模块
负责生成和管理各种类型的波浪效果
"""
import time
from typing import Dict, Any, List, Optional
import math
import numpy as np
class WaveSystem:
"""
波浪系统
负责生成和管理各种类型的波浪效果,包括风浪、涌浪、涟漪等
"""
def __init__(self, plugin):
"""
初始化波浪系统
Args:
plugin: 水体和流体模拟插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 波浪类型定义
self.wave_types = {
'wind_wave': {
'name': '风浪',
'description': '由风力产生的波浪',
'frequency_range': (0.1, 1.0), # Hz
'amplitude_range': (0.01, 2.0), # 米
'speed_range': (1.0, 10.0), # m/s
'typical_wavelength': 10.0 # 米
},
'swell_wave': {
'name': '涌浪',
'description': '远处风暴产生的长周期波浪',
'frequency_range': (0.05, 0.2),
'amplitude_range': (0.5, 5.0),
'speed_range': (5.0, 20.0),
'typical_wavelength': 100.0
},
'ripple': {
'name': '涟漪',
'description': '小尺度的表面波纹',
'frequency_range': (1.0, 10.0),
'amplitude_range': (0.001, 0.05),
'speed_range': (0.1, 1.0),
'typical_wavelength': 0.1
},
'tsunami': {
'name': '海啸',
'description': '由地震或海底滑坡产生的巨大波浪',
'frequency_range': (0.001, 0.01),
'amplitude_range': (1.0, 50.0),
'speed_range': (50.0, 200.0),
'typical_wavelength': 100000.0
},
'ship_wave': {
'name': '船行波',
'description': '船舶运动产生的波浪',
'frequency_range': (0.1, 2.0),
'amplitude_range': (0.1, 1.0),
'speed_range': (0.5, 5.0),
'typical_wavelength': 5.0
}
}
# 活跃波浪列表
self.active_waves = []
self.wave_counter = 0
# 波浪谱配置
self.wave_spectrum = {
'type': 'pierson_moskowitz', # 'pierson_moskowitz', 'jonswap', 'custom'
'wind_speed': 10.0, # m/s
'fetch': 10000.0, # 风区长度(米)
'duration': 3600.0, # 风持续时间(秒)
'peak_frequency': 0.2, # Hz
'significant_wave_height': 1.0 # 有效波高(米)
}
# 动态波浪配置
self.dynamic_config = {
'max_waves': 32,
'update_frequency': 60.0, # Hz
'last_update_time': 0.0,
'time_scale': 1.0
}
# 环境影响因子
self.environment_factors = {
'wind_speed': 5.0, # m/s
'wind_direction': 0.0, # 弧度
'water_depth': 10.0, # 米
'current_velocity': (0.0, 0.0), # (vx, vz) m/s
'temperature': 20.0, # °C
'salinity': 35.0 # ppt
}
# 波浪统计
self.wave_stats = {
'total_waves': 0,
'active_waves': 0,
'total_energy': 0.0,
'peak_wave_height': 0.0,
'average_wave_period': 0.0
}
# 交互效果
self.interaction_effects = {
'splash_damping': 0.9, # 溅起波浪的阻尼系数
'wave_interference': True, # 是否启用波浪干涉
'nonlinear_effects': True, # 是否启用非线性效应
'breaking_waves': True # 是否启用碎浪效果
}
print("✓ 波浪系统已创建")
def initialize(self) -> bool:
"""
初始化波浪系统
Returns:
是否初始化成功
"""
try:
# 创建一些初始波浪
self._create_initial_waves()
self.initialized = True
print("✓ 波浪系统初始化完成")
return True
except Exception as e:
print(f"✗ 波浪系统初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用波浪系统
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("✗ 波浪系统未初始化")
return False
self.enabled = True
print("✓ 波浪系统已启用")
return True
except Exception as e:
print(f"✗ 波浪系统启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self):
"""禁用波浪系统"""
try:
self.enabled = False
print("✓ 波浪系统已禁用")
except Exception as e:
print(f"✗ 波浪系统禁用失败: {e}")
import traceback
traceback.print_exc()
def finalize(self):
"""清理波浪系统资源"""
try:
self.disable()
self.active_waves.clear()
self.initialized = False
print("✓ 波浪系统资源已清理")
except Exception as e:
print(f"✗ 波浪系统资源清理失败: {e}")
import traceback
traceback.print_exc()
def update(self, dt: float):
"""
更新波浪系统状态
Args:
dt: 时间增量
"""
try:
if not self.enabled:
return
# 更新时间
self.dynamic_config['last_update_time'] += dt * self.dynamic_config['time_scale']
# 更新活跃波浪
self._update_active_waves(dt)
# 根据环境条件生成新波浪
self._generate_environment_waves(dt)
# 更新统计信息
self._update_wave_statistics()
except Exception as e:
print(f"✗ 波浪系统更新失败: {e}")
import traceback
traceback.print_exc()
def _create_initial_waves(self):
"""创建初始波浪"""
try:
# 创建几个默认波浪
for i in range(3):
wave_params = {
'type': 'wind_wave',
'amplitude': 0.5 + i * 0.2,
'wavelength': 10.0 + i * 5.0,
'speed': 2.0 + i * 0.5,
'direction': i * math.pi / 3,
'frequency': 0.3 + i * 0.1,
'phase': 0.0,
'damping': 0.01,
'lifetime': float('inf'),
'position': (0.0, 0.0)
}
self._add_wave(wave_params)
print("✓ 初始波浪创建完成")
except Exception as e:
print(f"✗ 初始波浪创建失败: {e}")
def _update_active_waves(self, dt: float):
"""
更新活跃波浪
Args:
dt: 时间增量
"""
try:
time_value = self.dynamic_config['last_update_time']
# 更新每个波浪
waves_to_remove = []
for wave in self.active_waves:
# 更新相位
wave['phase'] += wave['frequency'] * 2 * math.pi * dt
# 应用阻尼
wave['amplitude'] *= (1.0 - wave['damping'] * dt)
# 检查生命周期
if wave['lifetime'] != float('inf'):
wave['lifetime'] -= dt
if wave['lifetime'] <= 0:
waves_to_remove.append(wave)
# 更新位置(考虑水流速度)
current_vx, current_vz = self.environment_factors['current_velocity']
wave['position'] = (
wave['position'][0] + current_vx * dt,
wave['position'][1] + current_vz * dt
)
# 移除过期波浪
for wave in waves_to_remove:
self.active_waves.remove(wave)
except Exception as e:
print(f"✗ 活跃波浪更新失败: {e}")
def _generate_environment_waves(self, dt: float):
"""
根据环境条件生成波浪
Args:
dt: 时间增量
"""
try:
# 基于风速生成波浪
wind_speed = self.environment_factors['wind_speed']
wind_direction = self.environment_factors['wind_direction']
# 简化的波浪生成逻辑
# 实际实现中会使用更复杂的波浪谱模型
wave_generation_probability = min(1.0, wind_speed / 20.0) * dt
if np.random.random() < wave_generation_probability and len(self.active_waves) < self.dynamic_config['max_waves']:
# 生成新波浪
wave_type = 'wind_wave'
wave_info = self.wave_types[wave_type]
# 根据风速确定波浪参数
amplitude = np.random.uniform(0.1, wind_speed / 5.0)
wavelength = np.random.uniform(5.0, max(5.0, wind_speed * 2.0))
speed = min(wind_speed, math.sqrt(9.81 * wavelength / (2 * math.pi))) # 深水波速
direction = wind_direction + np.random.uniform(-0.2, 0.2) # 小角度偏移
wave_params = {
'type': wave_type,
'amplitude': amplitude,
'wavelength': wavelength,
'speed': speed,
'direction': direction,
'frequency': speed / wavelength,
'phase': np.random.uniform(0, 2 * math.pi),
'damping': np.random.uniform(0.001, 0.01),
'lifetime': np.random.uniform(10.0, 60.0),
'position': (0.0, 0.0)
}
self._add_wave(wave_params)
except Exception as e:
print(f"✗ 环境波浪生成失败: {e}")
def _add_wave(self, wave_params: Dict[str, Any]) -> int:
"""
添加波浪
Args:
wave_params: 波浪参数
Returns:
波浪ID
"""
try:
wave_id = self.wave_counter
self.wave_counter += 1
wave_params['id'] = wave_id
wave_params['creation_time'] = self.dynamic_config['last_update_time']
self.active_waves.append(wave_params)
return wave_id
except Exception as e:
print(f"✗ 波浪添加失败: {e}")
return -1
def _update_wave_statistics(self):
"""更新波浪统计信息"""
try:
total_energy = 0.0
peak_height = 0.0
total_period = 0.0
for wave in self.active_waves:
# 波浪能量 (简化的计算)
energy = 0.5 * 1000.0 * 9.81 * wave['amplitude'] ** 2
total_energy += energy
# 峰值波高
peak_height = max(peak_height, wave['amplitude'] * 2) # 波峰到波谷
# 平均周期
if wave['frequency'] > 0:
total_period += 1.0 / wave['frequency']
self.wave_stats['total_waves'] = self.wave_counter
self.wave_stats['active_waves'] = len(self.active_waves)
self.wave_stats['total_energy'] = total_energy
self.wave_stats['peak_wave_height'] = peak_height
if len(self.active_waves) > 0:
self.wave_stats['average_wave_period'] = total_period / len(self.active_waves)
else:
self.wave_stats['average_wave_period'] = 0.0
except Exception as e:
print(f"✗ 波浪统计更新失败: {e}")
def create_wave(self, wave_type: str, parameters: Dict[str, Any]) -> int:
"""
创建指定类型的波浪
Args:
wave_type: 波浪类型
parameters: 波浪参数
Returns:
波浪ID
"""
try:
if wave_type not in self.wave_types:
print(f"✗ 无效的波浪类型: {wave_type}")
return -1
# 获取波浪类型信息
wave_info = self.wave_types[wave_type]
# 默认参数
default_params = {
'type': wave_type,
'amplitude': np.random.uniform(*wave_info['amplitude_range']),
'wavelength': wave_info['typical_wavelength'],
'speed': np.random.uniform(*wave_info['speed_range']),
'direction': np.random.uniform(0, 2 * math.pi),
'frequency': 0.0,
'phase': 0.0,
'damping': 0.01,
'lifetime': float('inf'),
'position': (0.0, 0.0)
}
# 更新默认参数
default_params.update(parameters)
# 计算频率(如果未提供)
if default_params['frequency'] <= 0:
if default_params['wavelength'] > 0:
default_params['frequency'] = default_params['speed'] / default_params['wavelength']
else:
default_params['frequency'] = 0.1
# 添加波浪
wave_id = self._add_wave(default_params)
if wave_id >= 0:
print(f"{wave_info['name']} 已创建 (ID: {wave_id})")
return wave_id
except Exception as e:
print(f"✗ 波浪创建失败: {e}")
return -1
def remove_wave(self, wave_id: int) -> bool:
"""
移除波浪
Args:
wave_id: 波浪ID
Returns:
是否移除成功
"""
try:
for wave in self.active_waves:
if wave['id'] == wave_id:
self.active_waves.remove(wave)
print(f"✓ 波浪已移除 (ID: {wave_id})")
return True
print(f"✗ 波浪不存在 (ID: {wave_id})")
return False
except Exception as e:
print(f"✗ 波浪移除失败: {e}")
return False
def get_wave(self, wave_id: int) -> Optional[Dict[str, Any]]:
"""
获取波浪信息
Args:
wave_id: 波浪ID
Returns:
波浪信息或None
"""
try:
for wave in self.active_waves:
if wave['id'] == wave_id:
return wave.copy()
return None
except Exception as e:
print(f"✗ 波浪信息获取失败: {e}")
return None
def get_all_waves(self) -> List[Dict[str, Any]]:
"""
获取所有活跃波浪
Returns:
波浪列表
"""
return [wave.copy() for wave in self.active_waves]
def calculate_wave_height_at(self, x: float, z: float, time_value: float = None) -> float:
"""
计算指定位置和时间的波浪高度
Args:
x, z: 位置坐标
time_value: 时间值如果为None则使用当前时间
Returns:
波浪高度
"""
try:
if time_value is None:
time_value = self.dynamic_config['last_update_time']
total_height = 0.0
# 计算每个波浪在该点的贡献
for wave in self.active_waves:
# 计算相对于波浪位置的距离
dx = x - wave['position'][0]
dz = z - wave['position'][1]
# 计算在波浪传播方向上的投影距离
direction = wave['direction']
projection = dx * math.cos(direction) + dz * math.sin(direction)
# 计算相位
phase = wave['phase'] + 2 * math.pi * projection / wave['wavelength']
# 计算波浪高度(正弦波)
height = wave['amplitude'] * math.sin(phase)
# 如果启用波浪干涉,直接叠加
if self.interaction_effects['wave_interference']:
total_height += height
else:
# 否则取最大值
total_height = max(total_height, height)
return total_height
except Exception as e:
print(f"✗ 波浪高度计算失败: {e}")
return 0.0
def calculate_wave_velocity_at(self, x: float, z: float, time_value: float = None) -> tuple:
"""
计算指定位置和时间的波浪速度
Args:
x, z: 位置坐标
time_value: 时间值如果为None则使用当前时间
Returns:
波浪速度 (vx, vz)
"""
try:
if time_value is None:
time_value = self.dynamic_config['last_update_time']
total_vx = 0.0
total_vz = 0.0
# 计算每个波浪在该点的速度贡献
for wave in self.active_waves:
# 计算相对于波浪位置的距离
dx = x - wave['position'][0]
dz = z - wave['position'][1]
# 计算在波浪传播方向上的投影距离
direction = wave['direction']
projection = dx * math.cos(direction) + dz * math.sin(direction)
# 计算相位
phase = wave['phase'] + 2 * math.pi * projection / wave['wavelength']
# 计算速度分量
speed = wave['speed']
vx = speed * math.cos(direction)
vz = speed * math.sin(direction)
# 考虑波浪振幅的影响
velocity_factor = wave['amplitude'] * math.cos(phase)
total_vx += vx * velocity_factor
total_vz += vz * velocity_factor
return (total_vx, total_vz)
except Exception as e:
print(f"✗ 波浪速度计算失败: {e}")
return (0.0, 0.0)
def generate_wave_spectrum(self) -> Dict[str, List[float]]:
"""
生成波浪谱
Returns:
包含频率和能量密度的字典
"""
try:
spectrum_type = self.wave_spectrum['type']
wind_speed = self.wave_spectrum['wind_speed']
# 频率范围
freq_min, freq_max = 0.01, 2.0
num_points = 100
frequencies = np.linspace(freq_min, freq_max, num_points)
energy_densities = np.zeros(num_points)
if spectrum_type == 'pierson_moskowitz':
# Pierson-Moskowitz谱
alpha = 8.1e-3
beta = 0.74
g = 9.81
for i, f in enumerate(frequencies):
if f > 0:
omega = 2 * math.pi * f
energy_densities[i] = alpha * g**2 / omega**5 * math.exp(-beta * (g / (omega * wind_speed))**4)
elif spectrum_type == 'jonswap':
# JONSWAP谱
alpha = 0.076 * (wind_speed**2 / (g * 100))**0.22 # 简化计算
beta = 0.74
gamma = 3.3 # 峰值增强因子
sigma = 0.07 # 谱宽参数
fp = self.wave_spectrum['peak_frequency']
omega_p = 2 * math.pi * fp
for i, f in enumerate(frequencies):
if f > 0:
omega = 2 * math.pi * f
ratio = omega / omega_p
# 谱宽参数
if ratio <= 1:
sigma_val = 0.07
else:
sigma_val = 0.09
# 峰值增强函数
gamma_val = gamma ** math.exp(-0.5 * ((ratio - 1) / sigma_val)**2)
energy_densities[i] = alpha * g**2 / omega**5 * math.exp(-beta * (g / (omega * wind_speed))**4) * gamma_val
return {
'frequencies': frequencies.tolist(),
'energy_densities': energy_densities.tolist()
}
except Exception as e:
print(f"✗ 波浪谱生成失败: {e}")
return {
'frequencies': [],
'energy_densities': []
}
def create_splash_wave(self, position: tuple, energy: float) -> List[int]:
"""
创建溅起波浪效果
Args:
position: 溅起位置 (x, z)
energy: 溅起能量
Returns:
创建的波浪ID列表
"""
try:
created_waves = []
# 创建多个同心圆波浪来模拟溅起效果
num_ripples = min(5, int(energy / 0.1))
for i in range(num_ripples):
amplitude = energy * 0.1 * (1.0 - i * 0.15)
wavelength = 0.5 + i * 0.3
speed = 1.0 + i * 0.5
lifetime = 2.0 + i * 0.5
wave_params = {
'type': 'ripple',
'amplitude': amplitude,
'wavelength': wavelength,
'speed': speed,
'direction': 0.0, # 径向波
'frequency': speed / wavelength,
'phase': 0.0,
'damping': 0.5,
'lifetime': lifetime,
'position': position
}
wave_id = self._add_wave(wave_params)
if wave_id >= 0:
created_waves.append(wave_id)
if created_waves:
print(f"✓ 溅起波浪已创建 ({len(created_waves)} 个波浪)")
return created_waves
except Exception as e:
print(f"✗ 溅起波浪创建失败: {e}")
return []
def update_environment_factors(self, factors: Dict[str, Any]):
"""
更新环境因子
Args:
factors: 环境因子字典
"""
try:
self.environment_factors.update(factors)
print(f"✓ 环境因子已更新: {factors}")
except Exception as e:
print(f"✗ 环境因子更新失败: {e}")
def get_environment_factors(self) -> Dict[str, Any]:
"""
获取环境因子
Returns:
环境因子字典
"""
return self.environment_factors.copy()
def set_wave_spectrum(self, spectrum: Dict[str, Any]):
"""
设置波浪谱参数
Args:
spectrum: 波浪谱参数字典
"""
try:
self.wave_spectrum.update(spectrum)
print(f"✓ 波浪谱参数已更新: {self.wave_spectrum}")
except Exception as e:
print(f"✗ 波浪谱参数设置失败: {e}")
def get_wave_spectrum(self) -> Dict[str, Any]:
"""
获取波浪谱参数
Returns:
波浪谱参数字典
"""
return self.wave_spectrum.copy()
def set_dynamic_config(self, config: Dict[str, Any]):
"""
设置动态配置
Args:
config: 动态配置字典
"""
try:
self.dynamic_config.update(config)
print(f"✓ 动态配置已更新: {self.dynamic_config}")
except Exception as e:
print(f"✗ 动态配置设置失败: {e}")
def get_dynamic_config(self) -> Dict[str, Any]:
"""
获取动态配置
Returns:
动态配置字典
"""
return self.dynamic_config.copy()
def get_wave_statistics(self) -> Dict[str, Any]:
"""
获取波浪统计信息
Returns:
波浪统计字典
"""
return self.wave_stats.copy()
def reset_wave_statistics(self):
"""重置波浪统计信息"""
try:
self.wave_stats = {
'total_waves': self.wave_counter,
'active_waves': len(self.active_waves),
'total_energy': 0.0,
'peak_wave_height': 0.0,
'average_wave_period': 0.0
}
print("✓ 波浪统计信息已重置")
except Exception as e:
print(f"✗ 波浪统计信息重置失败: {e}")
def get_wave_types(self) -> List[str]:
"""
获取所有波浪类型
Returns:
波浪类型列表
"""
return list(self.wave_types.keys())
def get_wave_type_info(self, wave_type: str) -> Optional[Dict[str, Any]]:
"""
获取波浪类型信息
Args:
wave_type: 波浪类型
Returns:
波浪类型信息或None
"""
return self.wave_types.get(wave_type)