Files
xian_algorithm_new/app/script/calculate_hazard_zones.py
T

116 lines
3.7 KiB
Python
Raw Normal View History

2026-06-29 11:37:04 +08:00
"""
计算所有隐患点的灾害影响范围并填充 xian_hazard_zones 表
仅计算隐患点 (xian_hidden_danger_spots),不计算风险点。
灾害类型包括: 滑坡、泥石流、山洪、内涝、崩塌
"""
import sys
import os
from datetime import datetime
# 确保项目根目录在 sys.path 中
_project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if _project_root not in sys.path:
sys.path.insert(0, _project_root)
from app.utils.logger import LoggerManager
from app.repositories.hazard_repository import hazard_repository
from app.models.hazard.hazard_zone_calculator import hazard_zone_calculator
_BATCH_SIZE = 200 # 每处理200条输出一次进度
logger = LoggerManager.get_logger("hazard_zones",
os.path.join(_project_root, "logs"))
def main():
logger.info("=" * 60)
logger.info("开始计算隐患点灾害影响范围")
logger.info(f"启动时间: {datetime.now().isoformat()}")
logger.info("=" * 60)
# 1. 获取所有隐患点
spots = hazard_repository.get_all_hidden_danger_spots()
total = len(spots)
logger.info(f"查询到 {total} 个隐患点")
if total == 0:
logger.warning("没有隐患点数据,退出")
return
# 按灾害类型统计
type_counts = {}
for s in spots:
dt = s['disaster_type']
type_counts[dt] = type_counts.get(dt, 0) + 1
logger.info(f"灾害类型分布: {type_counts}")
# 2. 逐点计算
records = []
success_count = 0
skip_count = 0
error_count = 0
for i, spot in enumerate(spots):
sid = spot['source_id']
dtype = spot['disaster_type']
dname = spot['disaster_name']
scale = spot.get('scale_grade')
try:
zone_wkt, path_wkt = hazard_zone_calculator.calculate(
source_id=sid,
disaster_type=dtype,
scale_grade=scale,
lon=spot['lon'],
lat=spot['lat'],
static_factors=spot['static_factors']
)
if zone_wkt:
records.append({
'source_id': sid,
'disaster_type': dtype,
'zone_wkt': zone_wkt,
'path_wkt': path_wkt
})
success_count += 1
else:
skip_count += 1
logger.debug(f"跳过 [{sid}] {dname}({dtype}): 无法计算影响范围")
except Exception as e:
error_count += 1
logger.error(f"计算失败 [{sid}] {dname}({dtype}): {e}")
# 进度输出
if (i + 1) % _BATCH_SIZE == 0 or (i + 1) == total:
logger.info(f"进度: {i + 1}/{total} "
f"(成功:{success_count} 跳过:{skip_count} 失败:{error_count})")
# 3. 写入数据库
logger.info(f"计算完成。开始写入数据库,共 {len(records)} 条记录")
# 先逻辑删除旧数据
deleted = hazard_repository.delete_existing_zones()
logger.info(f"已标记 {deleted} 条旧记录为删除")
# 批量写入新数据
inserted = hazard_repository.batch_insert_zones(records)
logger.info(f"成功写入 {inserted} 条新记录")
# 4. 汇总
logger.info("=" * 60)
logger.info("执行完成")
logger.info(f" 隐患点总数: {total}")
logger.info(f" 计算成功: {success_count}")
logger.info(f" 跳过: {skip_count}")
logger.info(f" 计算失败: {error_count}")
logger.info(f" 写入记录: {inserted}")
logger.info(f"完成时间: {datetime.now().isoformat()}")
logger.info("=" * 60)
if __name__ == '__main__':
main()