EG/plugins/user/vegetation_ecosystem/visualization/advanced_visuals.py
2025-12-12 16:16:15 +08:00

792 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 random
class AdvancedVisuals:
"""
高级可视化系统
负责处理更复杂的生态系统可视化效果
"""
def __init__(self, plugin):
"""
初始化高级可视化系统
Args:
plugin: 植被和生态系统插件实例
"""
self.plugin = plugin
self.enabled = False
self.initialized = False
# 可视化效果类型
self.visualization_types = {
'ecosystem_health': {
'name': '生态系统健康度可视化',
'description': '可视化显示生态系统的整体健康状况',
'enabled': True
},
'interaction_trails': {
'name': '交互轨迹可视化',
'description': '可视化显示动物与植被的交互轨迹',
'enabled': True
},
'biodiversity_map': {
'name': '生物多样性地图',
'description': '生成并显示生物多样性热力图',
'enabled': True
},
'resource_distribution': {
'name': '资源分布可视化',
'description': '可视化显示环境资源分布',
'enabled': True
},
'population_density': {
'name': '种群密度可视化',
'description': '可视化显示动物种群密度',
'enabled': True
},
'growth_patterns': {
'name': '生长模式可视化',
'description': '可视化显示植被生长模式',
'enabled': True
}
}
# 可视化配置
self.visualization_config = {
'update_interval': 5.0, # 更新间隔(秒)
'render_distance': 150.0, # 渲染距离
'effect_intensity': 1.0, # 效果强度
'show_labels': True, # 显示标签
'transparency': 0.7, # 透明度
'color_scheme': 'default' # 颜色方案
}
# 可视化数据缓存
self.visualization_cache = {}
self.cache_config = {
'max_size': 200,
'expiration_time': 300 # 5分钟
}
# 特效参数
self.effect_params = {
'health_visualization': {
'color_gradient': [(1.0, 0.0, 0.0), (1.0, 1.0, 0.0), (0.0, 1.0, 0.0)], # 红-黄-绿
'pulse_rate': 0.5, # 脉冲频率
'size_variation': 0.2 # 大小变化
},
'trail_effects': {
'trail_lifetime': 10.0, # 轨迹生命周期
'trail_segments': 20, # 轨迹分段数
'trail_width': 0.5 # 轨迹宽度
},
'heatmap_settings': {
'gradient_colors': [(0.0, 0.0, 1.0), (0.0, 1.0, 0.0), (1.0, 1.0, 0.0), (1.0, 0.0, 0.0)],
'opacity_range': (0.3, 0.8),
'resolution': 50 # 热力图分辨率
}
}
# 可视化对象
self.visualization_objects = {}
self.object_counter = 0
# 时间配置
self.time_config = {
'last_update': 0.0,
'effect_time': 0.0
}
# 统计信息
self.visual_stats = {
'visualizations_created': 0,
'visualizations_updated': 0,
'cache_hits': 0,
'cache_misses': 0
}
print("✓ 高级可视化系统已创建")
def initialize(self) -> bool:
"""
初始化高级可视化系统
Returns:
是否初始化成功
"""
try:
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.visualization_cache.clear()
self.visualization_objects.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.time_config['last_update'] += dt
self.time_config['effect_time'] += dt
# 检查是否需要更新
if self.time_config['last_update'] >= self.visualization_config['update_interval']:
# 更新可视化效果
self._update_visualizations()
# 重置更新计时器
self.time_config['last_update'] = 0.0
# 更新特效时间
self._update_visual_effects(dt)
except Exception as e:
print(f"✗ 高级可视化系统更新失败: {e}")
import traceback
traceback.print_exc()
def _update_visualizations(self):
"""更新可视化效果"""
try:
# 更新生态系统健康度可视化
if self.visualization_types['ecosystem_health']['enabled']:
self._update_ecosystem_health_visualization()
# 更新交互轨迹可视化
if self.visualization_types['interaction_trails']['enabled']:
self._update_interaction_trails_visualization()
# 更新生物多样性地图
if self.visualization_types['biodiversity_map']['enabled']:
self._update_biodiversity_map_visualization()
# 更新统计信息
self.visual_stats['visualizations_updated'] += 1
except Exception as e:
print(f"✗ 可视化效果更新失败: {e}")
def _update_visual_effects(self, dt: float):
"""更新视觉特效"""
try:
# 在实际实现中,这里会更新各种视觉特效
# 如脉冲效果、颜色变化等
pass
except Exception as e:
print(f"✗ 视觉特效更新失败: {e}")
def _update_ecosystem_health_visualization(self):
"""更新生态系统健康度可视化"""
try:
if not self.plugin.ecosystem_manager:
return
# 获取生态系统状态
system_state = self.plugin.ecosystem_manager.get_system_state()
health_index = system_state.get('health_index', 0.5)
# 在实际实现中,这里会创建或更新表示生态系统健康度的可视化对象
# 比如在场景中显示一个颜色编码的球体或平面
# 缓存结果
self._cache_visualization_data('ecosystem_health', health_index)
except Exception as e:
print(f"✗ 生态系统健康度可视化更新失败: {e}")
def _update_interaction_trails_visualization(self):
"""更新交互轨迹可视化"""
try:
if not self.plugin.ecosystem_interactions:
return
# 获取交互历史
interaction_history = self.plugin.ecosystem_interactions.get_interaction_history(20)
# 在实际实现中,这里会根据交互历史创建轨迹可视化
# 比如显示动物移动路径、觅食路径等
# 缓存结果
self._cache_visualization_data('interaction_trails', len(interaction_history))
except Exception as e:
print(f"✗ 交互轨迹可视化更新失败: {e}")
def _update_biodiversity_map_visualization(self):
"""更新生物多样性地图可视化"""
try:
# 在实际实现中,这里会生成生物多样性热力图
# 基于植被和动物的分布密度计算多样性指数
biodiversity_index = 0.5 # 简化的默认值
if self.plugin.vegetation_manager and self.plugin.animal_simulator:
# 计算更准确的生物多样性指数
veg_stats = self.plugin.vegetation_manager.get_stats()
animal_stats = self.plugin.animal_simulator.get_stats()
veg_count = veg_stats.get('total_vegetation', 0)
animal_count = animal_stats.get('total_animals', 0)
# 简单的多样性计算
biodiversity_index = min(1.0, (veg_count + animal_count) / 1000.0)
# 缓存结果
self._cache_visualization_data('biodiversity_map', biodiversity_index)
except Exception as e:
print(f"✗ 生物多样性地图可视化更新失败: {e}")
def _cache_visualization_data(self, key: str, data: Any):
"""
缓存可视化数据
Args:
key: 缓存键
data: 要缓存的数据
"""
try:
# 检查缓存大小
if len(self.visualization_cache) >= self.cache_config['max_size']:
# 移除最旧的条目
oldest_key = min(self.visualization_cache.keys(),
key=lambda k: self.visualization_cache[k][0])
del self.visualization_cache[oldest_key]
# 缓存数据
self.visualization_cache[key] = (time.time(), data)
except Exception as e:
print(f"✗ 可视化数据缓存失败: {e}")
def get_cached_visualization_data(self, key: str) -> Optional[Any]:
"""
获取缓存的可视化数据
Args:
key: 缓存键
Returns:
缓存的数据或None
"""
try:
if key in self.visualization_cache:
timestamp, data = self.visualization_cache[key]
if time.time() - timestamp < self.cache_config['expiration_time']:
self.visual_stats['cache_hits'] += 1
return data
else:
# 缓存过期,删除条目
del self.visualization_cache[key]
self.visual_stats['cache_misses'] += 1
return None
except Exception as e:
print(f"✗ 缓存可视化数据获取失败: {e}")
return None
def create_visualization_object(self, object_type: str, properties: Dict[str, Any]) -> int:
"""
创建可视化对象
Args:
object_type: 对象类型
properties: 对象属性
Returns:
对象ID
"""
try:
object_id = self.object_counter
self.object_counter += 1
visualization_object = {
'id': object_id,
'type': object_type,
'properties': properties,
'created_time': time.time(),
'last_updated': time.time()
}
self.visualization_objects[object_id] = visualization_object
# 更新统计信息
self.visual_stats['visualizations_created'] += 1
print(f"✓ 可视化对象已创建: {object_type} (ID: {object_id})")
return object_id
except Exception as e:
print(f"✗ 可视化对象创建失败: {e}")
return -1
def update_visualization_object(self, object_id: int, properties: Dict[str, Any]) -> bool:
"""
更新可视化对象
Args:
object_id: 对象ID
properties: 对象属性
Returns:
是否更新成功
"""
try:
if object_id not in self.visualization_objects:
print(f"✗ 可视化对象不存在: {object_id}")
return False
# 更新属性
self.visualization_objects[object_id]['properties'].update(properties)
self.visualization_objects[object_id]['last_updated'] = time.time()
print(f"✓ 可视化对象已更新: ID {object_id}")
return True
except Exception as e:
print(f"✗ 可视化对象更新失败: {e}")
return False
def remove_visualization_object(self, object_id: int) -> bool:
"""
移除可视化对象
Args:
object_id: 对象ID
Returns:
是否移除成功
"""
try:
if object_id not in self.visualization_objects:
print(f"✗ 可视化对象不存在: {object_id}")
return False
del self.visualization_objects[object_id]
print(f"✓ 可视化对象已移除: ID {object_id}")
return True
except Exception as e:
print(f"✗ 可视化对象移除失败: {e}")
return False
def get_visualization_object(self, object_id: int) -> Optional[Dict[str, Any]]:
"""
获取可视化对象
Args:
object_id: 对象ID
Returns:
可视化对象或None
"""
return self.visualization_objects.get(object_id)
def get_all_visualization_objects(self) -> Dict[int, Dict[str, Any]]:
"""
获取所有可视化对象
Returns:
所有可视化对象字典
"""
return self.visualization_objects.copy()
def set_visualization_type_enabled(self, visualization_type: str, enabled: bool):
"""
设置可视化类型启用状态
Args:
visualization_type: 可视化类型
enabled: 是否启用
"""
try:
if visualization_type in self.visualization_types:
self.visualization_types[visualization_type]['enabled'] = enabled
print(f"✓ 可视化类型 '{visualization_type}'{'启用' if enabled else '禁用'}")
else:
print(f"✗ 无效的可视化类型: {visualization_type}")
except Exception as e:
print(f"✗ 可视化类型设置失败: {e}")
def get_visualization_types(self) -> Dict[str, Dict[str, Any]]:
"""
获取可视化类型
Returns:
可视化类型字典
"""
return self.visualization_types.copy()
def set_visualization_config(self, config: Dict[str, Any]):
"""
设置可视化配置
Args:
config: 配置字典
"""
try:
self.visualization_config.update(config)
print(f"✓ 可视化配置已更新: {self.visualization_config}")
except Exception as e:
print(f"✗ 可视化配置更新失败: {e}")
def get_visualization_config(self) -> Dict[str, Any]:
"""
获取可视化配置
Returns:
可视化配置字典
"""
return self.visualization_config.copy()
def set_effect_parameter(self, effect: str, parameter: str, value: Any):
"""
设置特效参数
Args:
effect: 特效名称
parameter: 参数名称
value: 参数值
"""
try:
if effect in self.effect_params and parameter in self.effect_params[effect]:
self.effect_params[effect][parameter] = value
print(f"✓ 特效参数已设置: {effect}.{parameter} = {value}")
else:
print(f"✗ 无效的特效参数: {effect}.{parameter}")
except Exception as e:
print(f"✗ 特效参数设置失败: {e}")
def get_effect_parameters(self) -> Dict[str, Dict[str, Any]]:
"""
获取特效参数
Returns:
特效参数字典
"""
return self.effect_params.copy()
def render_ecosystem_health(self):
"""渲染生态系统健康度可视化"""
try:
if not self.enabled or not self.visualization_types['ecosystem_health']['enabled']:
return
# 获取健康度数据
health_data = self.get_cached_visualization_data('ecosystem_health')
if health_data is None:
# 如果没有缓存数据,计算新的数据
if self.plugin.ecosystem_manager:
system_state = self.plugin.ecosystem_manager.get_system_state()
health_data = system_state.get('health_index', 0.5)
if health_data is not None:
# 在实际实现中,这里会渲染健康度可视化效果
# 比如根据健康度值改变颜色、大小等
# 根据健康度值选择颜色
color = self._get_health_color(health_data)
# 应用可视化效果
print(f"✓ 渲染生态系统健康度可视化: 健康度={health_data:.2f}, 颜色={color}")
except Exception as e:
print(f"✗ 生态系统健康度可视化渲染失败: {e}")
def _get_health_color(self, health: float) -> tuple:
"""
根据健康度获取颜色
Args:
health: 健康度值 (0.0-1.0)
Returns:
RGB颜色元组
"""
try:
# 使用预定义的颜色渐变
gradient = self.effect_params['health_visualization']['color_gradient']
# 确保健康度在有效范围内
health = max(0.0, min(1.0, health))
# 简单的三色插值
if health < 0.5:
# 红色到黄色
t = health * 2.0
r = gradient[0][0] + (gradient[1][0] - gradient[0][0]) * t
g = gradient[0][1] + (gradient[1][1] - gradient[0][1]) * t
b = gradient[0][2] + (gradient[1][2] - gradient[0][2]) * t
else:
# 黄色到绿色
t = (health - 0.5) * 2.0
r = gradient[1][0] + (gradient[2][0] - gradient[1][0]) * t
g = gradient[1][1] + (gradient[2][1] - gradient[1][1]) * t
b = gradient[1][2] + (gradient[2][2] - gradient[1][2]) * t
return (r, g, b)
except Exception as e:
print(f"✗ 健康度颜色计算失败: {e}")
return (0.5, 0.5, 0.5)
def render_biodiversity_map(self):
"""渲染生物多样性地图"""
try:
if not self.enabled or not self.visualization_types['biodiversity_map']['enabled']:
return
# 获取多样性数据
biodiversity_data = self.get_cached_visualization_data('biodiversity_map')
if biodiversity_data is None:
# 计算多样性数据
biodiversity_data = 0.5 # 默认值
if self.plugin.vegetation_manager and self.plugin.animal_simulator:
veg_stats = self.plugin.vegetation_manager.get_stats()
animal_stats = self.plugin.animal_simulator.get_stats()
veg_count = veg_stats.get('total_vegetation', 0)
animal_count = animal_stats.get('total_animals', 0)
biodiversity_data = min(1.0, (veg_count + animal_count) / 1000.0)
# 在实际实现中,这里会渲染多样性热力图
print(f"✓ 渲染生物多样性地图: 多样性指数={biodiversity_data:.2f}")
except Exception as e:
print(f"✗ 生物多样性地图渲染失败: {e}")
def render_interaction_trails(self):
"""渲染交互轨迹"""
try:
if not self.enabled or not self.visualization_types['interaction_trails']['enabled']:
return
# 在实际实现中,这里会渲染交互轨迹效果
print("✓ 渲染交互轨迹可视化")
except Exception as e:
print(f"✗ 交互轨迹渲染失败: {e}")
def get_visualization_stats(self) -> Dict[str, Any]:
"""
获取可视化统计信息
Returns:
统计信息字典
"""
# 计算缓存命中率
total_cache_accesses = self.visual_stats['cache_hits'] + self.visual_stats['cache_misses']
cache_hit_rate = 0.0
if total_cache_accesses > 0:
cache_hit_rate = self.visual_stats['cache_hits'] / total_cache_accesses
stats = self.visual_stats.copy()
stats['cache_hit_rate'] = cache_hit_rate
stats['active_objects'] = len(self.visualization_objects)
return stats
def reset_visualization_stats(self):
"""重置可视化统计信息"""
try:
self.visual_stats = {
'visualizations_created': 0,
'visualizations_updated': 0,
'cache_hits': 0,
'cache_misses': 0
}
print("✓ 可视化统计信息已重置")
except Exception as e:
print(f"✗ 可视化统计信息重置失败: {e}")
def clear_visualization_cache(self):
"""清空可视化缓存"""
try:
self.visualization_cache.clear()
print("✓ 可视化缓存已清空")
except Exception as e:
print(f"✗ 可视化缓存清空失败: {e}")
def cleanup_expired_cache(self):
"""清理过期缓存"""
try:
current_time = time.time()
expired_keys = []
for key, (timestamp, _) in self.visualization_cache.items():
if current_time - timestamp > self.cache_config['expiration_time']:
expired_keys.append(key)
for key in expired_keys:
del self.visualization_cache[key]
if expired_keys:
print(f"✓ 已清理 {len(expired_keys)} 个过期缓存项")
except Exception as e:
print(f"✗ 过期缓存清理失败: {e}")
def set_color_scheme(self, scheme: str):
"""
设置颜色方案
Args:
scheme: 颜色方案名称
"""
try:
self.visualization_config['color_scheme'] = scheme
print(f"✓ 颜色方案已设置为: {scheme}")
except Exception as e:
print(f"✗ 颜色方案设置失败: {e}")
def get_available_color_schemes(self) -> List[str]:
"""
获取可用的颜色方案
Returns:
颜色方案列表
"""
# 在实际实现中,这里会返回支持的颜色方案列表
return ['default', 'warm', 'cool', 'contrast']
def capture_visualization_screenshot(self, filename: str = None) -> str:
"""
捕获可视化截图
Args:
filename: 文件名
Returns:
截图文件路径
"""
try:
if filename is None:
timestamp = int(time.time())
filename = f"ecovisual_{timestamp}.png"
# 在实际实现中这里会调用渲染API捕获屏幕
print(f"✓ 可视化截图已保存: {filename}")
return filename
except Exception as e:
print(f"✗ 可视化截图捕获失败: {e}")
return ""
def export_visualization_data(self, filename: str) -> bool:
"""
导出可视化数据
Args:
filename: 文件名
Returns:
是否导出成功
"""
try:
# 创建导出数据
export_data = {
'visualization_config': self.visualization_config,
'effect_params': self.effect_params,
'visualization_types': self.visualization_types,
'stats': self.get_visualization_stats(),
'timestamp': time.time()
}
# 在实际实现中,这里会将数据保存到文件
print(f"✓ 可视化数据已导出到: {filename}")
return True
except Exception as e:
print(f"✗ 可视化数据导出失败: {e}")
return False
def import_visualization_data(self, filename: str) -> bool:
"""
导入可视化数据
Args:
filename: 文件名
Returns:
是否导入成功
"""
try:
# 在实际实现中,这里会从文件加载数据
print(f"✓ 可视化数据已从 {filename} 导入")
return True
except Exception as e:
print(f"✗ 可视化数据导入失败: {e}")
return False