664 lines
23 KiB
Python
664 lines
23 KiB
Python
"""
|
|
地形影响系统
|
|
负责模拟地形特征对植被分布和生态系统的影响
|
|
"""
|
|
|
|
import time
|
|
from typing import Dict, Any, List, Optional, Tuple
|
|
import math
|
|
import random
|
|
|
|
class TerrainInfluence:
|
|
"""
|
|
地形影响系统
|
|
负责模拟地形特征(坡度、海拔、朝向等)对植被分布和生态系统的影响
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化地形影响系统
|
|
|
|
Args:
|
|
plugin: 植被和生态系统插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
# 地形因子定义
|
|
self.terrain_factors = {
|
|
'elevation': {
|
|
'name': '海拔',
|
|
'description': '海拔高度对植被的影响',
|
|
'optimal_range': (0, 2000), # 最佳海拔范围(米)
|
|
'stress_threshold': 3000, # 压力阈值(米)
|
|
'impact_weight': 0.3 # 影响权重
|
|
},
|
|
'slope': {
|
|
'name': '坡度',
|
|
'description': '坡度对植被的影响',
|
|
'optimal_range': (0, 30), # 最佳坡度范围(度)
|
|
'stress_threshold': 60, # 压力阈值(度)
|
|
'impact_weight': 0.2
|
|
},
|
|
'aspect': {
|
|
'name': '朝向',
|
|
'description': '坡面朝向对植被的影响',
|
|
'optimal_range': (135, 225), # 最佳朝向(东南-西南)
|
|
'stress_direction': (0, 180), # 不利朝向(北向)
|
|
'impact_weight': 0.15
|
|
},
|
|
'soil_depth': {
|
|
'name': '土壤深度',
|
|
'description': '土壤深度对植被根系的影响',
|
|
'optimal_range': (0.5, 2.0), # 最佳土壤深度(米)
|
|
'stress_threshold': 0.2, # 压力阈值(米)
|
|
'impact_weight': 0.25
|
|
},
|
|
'water_accumulation': {
|
|
'name': '积水',
|
|
'description': '地表积水对植被的影响',
|
|
'optimal_range': (0, 0.3), # 最佳积水深度(米)
|
|
'stress_threshold': 0.5, # 压力阈值(米)
|
|
'impact_weight': 0.1
|
|
}
|
|
}
|
|
|
|
# 地形影响模型
|
|
self.influence_models = {
|
|
'linear': {
|
|
'name': '线性模型',
|
|
'description': '线性影响关系'
|
|
},
|
|
'exponential': {
|
|
'name': '指数模型',
|
|
'description': '指数影响关系'
|
|
},
|
|
'threshold': {
|
|
'name': '阈值模型',
|
|
'description': '基于阈值的影响'
|
|
},
|
|
'combined': {
|
|
'name': '组合模型',
|
|
'description': '综合多种因子的影响'
|
|
}
|
|
}
|
|
|
|
# 地形数据缓存
|
|
self.terrain_cache = {}
|
|
self.cache_config = {
|
|
'max_size': 1000, # 最大缓存大小
|
|
'expiration_time': 300, # 过期时间(秒)
|
|
'update_interval': 60 # 更新间隔(秒)
|
|
}
|
|
|
|
# 地形微气候效应
|
|
self.microclimate_effects = {
|
|
'temperature_variation': 0.0, # 温度变化
|
|
'humidity_variation': 0.0, # 湿度变化
|
|
'wind_shelter': 0.0, # 风力遮蔽
|
|
'radiation_exposure': 0.0 # 辐射暴露
|
|
}
|
|
|
|
# 地形适应性参数
|
|
self.adaptation_params = {
|
|
'adaptation_rate': 0.01, # 适应速率
|
|
'genetic_diversity': 0.7, # 遗传多样性
|
|
'migration_capability': 0.3, # 迁移能力
|
|
'stress_tolerance': 0.5 # 压力耐受性
|
|
}
|
|
|
|
# 统计信息
|
|
self.terrain_stats = {
|
|
'influence_calculations': 0,
|
|
'cache_hits': 0,
|
|
'cache_misses': 0,
|
|
'microclimate_updates': 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.terrain_cache.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._update_terrain_cache()
|
|
|
|
# 更新微气候效应
|
|
self._update_microclimate_effects()
|
|
|
|
except Exception as e:
|
|
print(f"✗ 地形影响系统更新失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def _update_terrain_cache(self):
|
|
"""更新地形数据缓存"""
|
|
try:
|
|
current_time = time.time()
|
|
|
|
# 清理过期缓存
|
|
expired_keys = []
|
|
for key, (timestamp, _) in self.terrain_cache.items():
|
|
if current_time - timestamp > self.cache_config['expiration_time']:
|
|
expired_keys.append(key)
|
|
|
|
for key in expired_keys:
|
|
del self.terrain_cache[key]
|
|
|
|
except Exception as e:
|
|
print(f"✗ 地形缓存更新失败: {e}")
|
|
|
|
def _update_microclimate_effects(self):
|
|
"""更新微气候效应"""
|
|
try:
|
|
# 在实际实现中,这里会根据地形特征更新微气候效应
|
|
self.terrain_stats['microclimate_updates'] += 1
|
|
except Exception as e:
|
|
print(f"✗ 微气候效应更新失败: {e}")
|
|
|
|
def calculate_terrain_influence(self, position: Tuple[float, float, float],
|
|
vegetation_type: str = None) -> Dict[str, float]:
|
|
"""
|
|
计算地形对植被的影响
|
|
|
|
Args:
|
|
position: 位置坐标 (x, y, z)
|
|
vegetation_type: 植被类型(可选)
|
|
|
|
Returns:
|
|
地形影响因子字典
|
|
"""
|
|
try:
|
|
# 检查缓存
|
|
cache_key = f"{position}_{vegetation_type or 'general'}"
|
|
current_time = time.time()
|
|
|
|
if cache_key in self.terrain_cache:
|
|
timestamp, cached_result = self.terrain_cache[cache_key]
|
|
if current_time - timestamp < self.cache_config['expiration_time']:
|
|
self.terrain_stats['cache_hits'] += 1
|
|
return cached_result
|
|
|
|
self.terrain_stats['cache_misses'] += 1
|
|
|
|
# 获取地形数据
|
|
terrain_data = self._get_terrain_data(position)
|
|
|
|
# 计算各因子影响
|
|
influence_factors = {}
|
|
total_weight = 0.0
|
|
weighted_sum = 0.0
|
|
|
|
for factor_name, factor_info in self.terrain_factors.items():
|
|
if factor_name in terrain_data:
|
|
factor_value = terrain_data[factor_name]
|
|
factor_influence = self._calculate_factor_influence(
|
|
factor_name, factor_value, factor_info
|
|
)
|
|
|
|
influence_factors[factor_name] = factor_influence
|
|
weight = factor_info['impact_weight']
|
|
weighted_sum += factor_influence * weight
|
|
total_weight += weight
|
|
|
|
# 计算综合影响
|
|
if total_weight > 0:
|
|
overall_influence = weighted_sum / total_weight
|
|
else:
|
|
overall_influence = 1.0
|
|
|
|
influence_factors['overall'] = overall_influence
|
|
|
|
# 缓存结果
|
|
self.terrain_cache[cache_key] = (current_time, influence_factors)
|
|
|
|
# 限制缓存大小
|
|
if len(self.terrain_cache) > self.cache_config['max_size']:
|
|
# 移除最旧的条目
|
|
oldest_key = min(self.terrain_cache.keys(),
|
|
key=lambda k: self.terrain_cache[k][0])
|
|
del self.terrain_cache[oldest_key]
|
|
|
|
self.terrain_stats['influence_calculations'] += 1
|
|
|
|
return influence_factors
|
|
|
|
except Exception as e:
|
|
print(f"✗ 地形影响计算失败: {e}")
|
|
return {'overall': 1.0}
|
|
|
|
def _get_terrain_data(self, position: Tuple[float, float, float]) -> Dict[str, float]:
|
|
"""
|
|
获取指定位置的地形数据
|
|
|
|
Args:
|
|
position: 位置坐标 (x, y, z)
|
|
|
|
Returns:
|
|
地形数据字典
|
|
"""
|
|
try:
|
|
x, y, z = position
|
|
|
|
# 简化的地形数据生成
|
|
# 在实际实现中,这里会从真实的地形数据源获取信息
|
|
terrain_data = {
|
|
'elevation': y, # 假设y坐标为海拔
|
|
'slope': random.uniform(0, 45), # 随机坡度
|
|
'aspect': random.uniform(0, 360), # 随机朝向
|
|
'soil_depth': random.uniform(0.1, 3.0), # 随机土壤深度
|
|
'water_accumulation': random.uniform(0, 0.8) # 随机积水深度
|
|
}
|
|
|
|
return terrain_data
|
|
|
|
except Exception as e:
|
|
print(f"✗ 地形数据获取失败: {e}")
|
|
return {}
|
|
|
|
def _calculate_factor_influence(self, factor_name: str, factor_value: float,
|
|
factor_info: Dict[str, Any]) -> float:
|
|
"""
|
|
计算单个地形因子的影响
|
|
|
|
Args:
|
|
factor_name: 因子名称
|
|
factor_value: 因子值
|
|
factor_info: 因子信息
|
|
|
|
Returns:
|
|
影响因子 (0.0-2.0)
|
|
"""
|
|
try:
|
|
optimal_range = factor_info['optimal_range']
|
|
impact_weight = factor_info['impact_weight']
|
|
|
|
min_optimal, max_optimal = optimal_range
|
|
|
|
# 计算在最优范围内的适宜性
|
|
if min_optimal <= factor_value <= max_optimal:
|
|
suitability = 1.0
|
|
else:
|
|
# 计算距离最优范围的距离
|
|
if factor_value < min_optimal:
|
|
distance = min_optimal - factor_value
|
|
else:
|
|
distance = factor_value - max_optimal
|
|
|
|
# 指数衰减函数
|
|
suitability = max(0.0, math.exp(-distance / (max_optimal - min_optimal)))
|
|
|
|
# 应用压力阈值
|
|
if 'stress_threshold' in factor_info:
|
|
stress_threshold = factor_info['stress_threshold']
|
|
if factor_name in ['elevation', 'slope', 'water_accumulation']:
|
|
if factor_value > stress_threshold:
|
|
# 超过压力阈值时进一步降低适宜性
|
|
excess = factor_value - stress_threshold
|
|
stress_factor = max(0.0, 1.0 - (excess / stress_threshold))
|
|
suitability *= stress_factor
|
|
|
|
return max(0.0, min(2.0, suitability))
|
|
|
|
except Exception as e:
|
|
print(f"✗ 因子影响计算失败: {e}")
|
|
return 1.0
|
|
|
|
def get_terrain_factors(self) -> Dict[str, Dict[str, Any]]:
|
|
"""
|
|
获取地形因子定义
|
|
|
|
Returns:
|
|
地形因子字典
|
|
"""
|
|
return self.terrain_factors.copy()
|
|
|
|
def get_terrain_factor_info(self, factor_name: str) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
获取特定地形因子的信息
|
|
|
|
Args:
|
|
factor_name: 因子名称
|
|
|
|
Returns:
|
|
因子信息字典或None
|
|
"""
|
|
return self.terrain_factors.get(factor_name)
|
|
|
|
def set_terrain_factor_parameter(self, factor_name: str, parameter: str, value: Any):
|
|
"""
|
|
设置地形因子参数
|
|
|
|
Args:
|
|
factor_name: 因子名称
|
|
parameter: 参数名称
|
|
value: 参数值
|
|
"""
|
|
try:
|
|
if factor_name in self.terrain_factors and parameter in self.terrain_factors[factor_name]:
|
|
self.terrain_factors[factor_name][parameter] = value
|
|
print(f"✓ 地形因子参数已设置: {factor_name}.{parameter} = {value}")
|
|
else:
|
|
print(f"✗ 无效的地形因子参数: {factor_name}.{parameter}")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 地形因子参数设置失败: {e}")
|
|
|
|
def get_influence_models(self) -> Dict[str, Dict[str, str]]:
|
|
"""
|
|
获取影响模型
|
|
|
|
Returns:
|
|
影响模型字典
|
|
"""
|
|
return self.influence_models.copy()
|
|
|
|
def set_influence_model(self, model_name: str):
|
|
"""
|
|
设置影响模型
|
|
|
|
Args:
|
|
model_name: 模型名称
|
|
"""
|
|
try:
|
|
if model_name in self.influence_models:
|
|
# 在实际实现中,这里会设置当前使用的模型
|
|
print(f"✓ 影响模型设置为: {self.influence_models[model_name]['name']}")
|
|
else:
|
|
print(f"✗ 无效的影响模型: {model_name}")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 影响模型设置失败: {e}")
|
|
|
|
def set_cache_config(self, config: Dict[str, Any]):
|
|
"""
|
|
设置缓存配置
|
|
|
|
Args:
|
|
config: 缓存配置字典
|
|
"""
|
|
try:
|
|
self.cache_config.update(config)
|
|
print(f"✓ 缓存配置已更新: {self.cache_config}")
|
|
except Exception as e:
|
|
print(f"✗ 缓存配置更新失败: {e}")
|
|
|
|
def get_cache_config(self) -> Dict[str, Any]:
|
|
"""
|
|
获取缓存配置
|
|
|
|
Returns:
|
|
缓存配置字典
|
|
"""
|
|
return self.cache_config.copy()
|
|
|
|
def clear_terrain_cache(self):
|
|
"""清空地形缓存"""
|
|
try:
|
|
self.terrain_cache.clear()
|
|
print("✓ 地形缓存已清空")
|
|
except Exception as e:
|
|
print(f"✗ 地形缓存清空失败: {e}")
|
|
|
|
def get_terrain_cache_info(self) -> Dict[str, Any]:
|
|
"""
|
|
获取地形缓存信息
|
|
|
|
Returns:
|
|
缓存信息字典
|
|
"""
|
|
try:
|
|
return {
|
|
'cache_size': len(self.terrain_cache),
|
|
'max_size': self.cache_config['max_size'],
|
|
'hit_rate': (self.terrain_stats['cache_hits'] /
|
|
max(1, self.terrain_stats['cache_hits'] + self.terrain_stats['cache_misses']))
|
|
}
|
|
except Exception as e:
|
|
print(f"✗ 缓存信息获取失败: {e}")
|
|
return {}
|
|
|
|
def update_microclimate_effect(self, effect_name: str, value: float):
|
|
"""
|
|
更新微气候效应
|
|
|
|
Args:
|
|
effect_name: 效应名称
|
|
value: 效应值
|
|
"""
|
|
try:
|
|
if effect_name in self.microclimate_effects:
|
|
self.microclimate_effects[effect_name] = value
|
|
print(f"✓ 微气候效应已更新: {effect_name} = {value}")
|
|
else:
|
|
print(f"✗ 无效的微气候效应: {effect_name}")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 微气候效应更新失败: {e}")
|
|
|
|
def get_microclimate_effects(self) -> Dict[str, float]:
|
|
"""
|
|
获取微气候效应
|
|
|
|
Returns:
|
|
微气候效应字典
|
|
"""
|
|
return self.microclimate_effects.copy()
|
|
|
|
def set_adaptation_parameter(self, parameter: str, value: float):
|
|
"""
|
|
设置适应性参数
|
|
|
|
Args:
|
|
parameter: 参数名称
|
|
value: 参数值
|
|
"""
|
|
try:
|
|
if parameter in self.adaptation_params:
|
|
self.adaptation_params[parameter] = max(0.0, min(1.0, value))
|
|
print(f"✓ 适应性参数已设置: {parameter} = {value}")
|
|
else:
|
|
print(f"✗ 无效的适应性参数: {parameter}")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 适应性参数设置失败: {e}")
|
|
|
|
def get_adaptation_parameters(self) -> Dict[str, float]:
|
|
"""
|
|
获取适应性参数
|
|
|
|
Returns:
|
|
适应性参数字典
|
|
"""
|
|
return self.adaptation_params.copy()
|
|
|
|
def simulate_terrain_adaptation(self, vegetation_type: str,
|
|
terrain_conditions: Dict[str, float]) -> float:
|
|
"""
|
|
模拟植被对地形的适应过程
|
|
|
|
Args:
|
|
vegetation_type: 植被类型
|
|
terrain_conditions: 地形条件
|
|
|
|
Returns:
|
|
适应性评分 (0.0-1.0)
|
|
"""
|
|
try:
|
|
# 获取植被的地形偏好
|
|
if self.plugin.vegetation_manager:
|
|
veg_info = self.plugin.vegetation_manager.get_vegetation_info(vegetation_type)
|
|
if veg_info:
|
|
# 基于植被类型和地形条件计算适应性
|
|
adaptation_score = self._calculate_adaptation_score(vegetation_type, terrain_conditions)
|
|
return adaptation_score
|
|
|
|
# 默认适应性评分
|
|
return 0.5
|
|
|
|
except Exception as e:
|
|
print(f"✗ 地形适应模拟失败: {e}")
|
|
return 0.5
|
|
|
|
def _calculate_adaptation_score(self, vegetation_type: str,
|
|
terrain_conditions: Dict[str, float]) -> float:
|
|
"""
|
|
计算植被对地形的适应性评分
|
|
|
|
Args:
|
|
vegetation_type: 植被类型
|
|
terrain_conditions: 地形条件
|
|
|
|
Returns:
|
|
适应性评分 (0.0-1.0)
|
|
"""
|
|
try:
|
|
# 简化的适应性计算
|
|
scores = []
|
|
|
|
for factor_name, factor_value in terrain_conditions.items():
|
|
if factor_name in self.terrain_factors:
|
|
factor_info = self.terrain_factors[factor_name]
|
|
factor_influence = self._calculate_factor_influence(
|
|
factor_name, factor_value, factor_info
|
|
)
|
|
scores.append(factor_influence)
|
|
|
|
if scores:
|
|
return sum(scores) / len(scores)
|
|
return 0.5
|
|
|
|
except Exception as e:
|
|
print(f"✗ 适应性评分计算失败: {e}")
|
|
return 0.5
|
|
|
|
def get_terrain_stats(self) -> Dict[str, int]:
|
|
"""
|
|
获取地形统计信息
|
|
|
|
Returns:
|
|
统计信息字典
|
|
"""
|
|
return self.terrain_stats.copy()
|
|
|
|
def reset_terrain_stats(self):
|
|
"""重置地形统计信息"""
|
|
try:
|
|
self.terrain_stats = {
|
|
'influence_calculations': 0,
|
|
'cache_hits': 0,
|
|
'cache_misses': 0,
|
|
'microclimate_updates': 0
|
|
}
|
|
print("✓ 地形统计信息已重置")
|
|
except Exception as e:
|
|
print(f"✗ 地形统计信息重置失败: {e}")
|
|
|
|
def get_terrain_suitability_map(self, area: Tuple[Tuple[float, float], Tuple[float, float]],
|
|
resolution: float = 1.0) -> Dict[Tuple[float, float], float]:
|
|
"""
|
|
获取区域内地形适宜性地图
|
|
|
|
Args:
|
|
area: 区域范围 ((min_x, min_z), (max_x, max_z))
|
|
resolution: 分辨率
|
|
|
|
Returns:
|
|
适宜性地图字典 {(x, z): suitability}
|
|
"""
|
|
try:
|
|
(min_x, min_z), (max_x, max_z) = area
|
|
suitability_map = {}
|
|
|
|
x = min_x
|
|
while x <= max_x:
|
|
z = min_z
|
|
while z <= max_z:
|
|
# 计算位置的适宜性
|
|
position = (x, 0, z) # 假设y坐标为0
|
|
influence = self.calculate_terrain_influence(position)
|
|
suitability = influence.get('overall', 1.0)
|
|
|
|
suitability_map[(x, z)] = suitability
|
|
|
|
z += resolution
|
|
x += resolution
|
|
|
|
return suitability_map
|
|
|
|
except Exception as e:
|
|
print(f"✗ 适宜性地图生成失败: {e}")
|
|
return {} |