VWED_server/services/smap_to_scene_converter.py

179 lines
7.1 KiB
Python
Raw Permalink 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.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
交互式场景转换器 v2.0
用于指导用户填写必填参数并执行转换流程
支持Scene转换和华睿地图转换
"""
import os
import sys
import json
import logging
from pathlib import Path
from services.map_tools.convert_basic import SceneBasicConverter
# 设置logger
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
def save_uploaded_file(file_obj, filename):
"""
保存上传的文件到指定目录
file_obj: 文件对象或内容
filename: 保存的文件名
返回保存后的绝对路径
"""
upload_dir = os.path.join(os.path.dirname(__file__), 'map_converter', 'uploads')
if not os.path.exists(upload_dir):
os.makedirs(upload_dir)
save_path = os.path.join(upload_dir, filename)
# file_obj 可能是文件对象或字节内容
if hasattr(file_obj, 'read'):
content = file_obj.read()
else:
content = file_obj
# 如果是bytes则直接写否则以文本写
mode = 'wb' if isinstance(content, bytes) else 'w'
with open(save_path, mode, encoding=None if mode=='wb' else 'utf-8') as f:
f.write(content)
return save_path
def convert_smap_to_scene(smap_file, scene_file=None):
"""
smap_file/scene_file: 可以是文件路径、文件对象或内容
自动完成scene转换若scene_file不为空则自动丰富场景
"""
import time
from services.map_tools.convert_basic import SceneBasicConverter
# 如果传入的是文件对象或内容,则先保存
if not isinstance(smap_file, str) or not os.path.exists(smap_file):
smap_path = save_uploaded_file(smap_file, f'smap_{int(time.time())}.smap')
else:
smap_path = smap_file
scene_path = ''
if scene_file:
if not isinstance(scene_file, str) or not os.path.exists(scene_file):
scene_path = save_uploaded_file(scene_file, f'scene_{int(time.time())}.scene')
else:
scene_path = scene_file
params = {}
params['smap_file'] = smap_path
params['scene_file'] = scene_path
params['scene_id'] = int(time.time())
# 第一阶段转换固定使用 converter.scene
intermediate_output_file = 'converter.scene'
# 最终输出文件名为smap文件同名的scene文件
final_output_file = str(Path(smap_path).with_suffix('.scene').name)
params['output_file'] = intermediate_output_file
params['final_output_file'] = final_output_file
params['scene_name'] = Path(final_output_file).stem
params['scale'] = 0.66
params['origin'] = {'x': 0, 'y': 0}
params['setting'] = ''
params['ratio'] = 100
logger.info("==== 开始Scene转换 ====")
logger.info(f"SMAP文件: {params['smap_file']}")
logger.info(f"中间输出文件: {params['output_file']}")
logger.info(f"最终输出文件: {params['final_output_file']}")
logger.info(f"场景ID: {params['scene_id']}")
logger.info(f"场景名称: {params['scene_name']}")
logger.info(f"比例: {params['scale']}, 原点: {params['origin']}, 设置: {params['setting']}, 比率: {params['ratio']}")
try:
converter = SceneBasicConverter(
scene_id=params['scene_id'],
setting=params['setting'],
ratio=params['ratio']
)
result = converter.convert_basic(
smap_file=params['smap_file'],
scene_file=params['scene_file'],
output_file=params['output_file']
)
# 更新自定义参数
result['name'] = params['scene_name']
result['scale'] = params['scale']
result['origin'] = params['origin']
with open(params['output_file'], 'w', encoding='utf-8') as f:
json.dump(result, f, indent=2, ensure_ascii=False)
# coordinate_system.json
coordinate_data = {
'scale': result['scale'],
'origin': result['origin']
}
converted_dir = "converted"
if not os.path.exists(converted_dir):
os.makedirs(converted_dir)
with open(f"{converted_dir}/coordinate_system.json", 'w', encoding='utf-8') as f:
json.dump(coordinate_data, f, indent=2, ensure_ascii=False)
logger.info(f"✓ Scene转换完成中间文件已保存到: {params['output_file']}")
except Exception as e:
logger.error(f"✗ Scene转换过程中出现错误: {str(e)}")
return
# 自动丰富场景
if scene_path:
try:
from services.map_tools.enrich_scene import SceneEnricher
logger.info("==== 自动执行场景丰富化 ====")
enricher = SceneEnricher(params['output_file'], params['scene_file'])
enricher.enrich(params['output_file'])
logger.info("✓ 场景丰富化完成!")
# 重新读取场景丰富化后的文件内容,更新返回结果
try:
with open(params['output_file'], 'r', encoding='utf-8') as f:
result = json.load(f)
logger.info("✓ 已重新加载场景丰富化后的数据")
except Exception as e:
logger.error(f"✗ 重新加载场景丰富化后数据失败: {str(e)}")
except Exception as e:
logger.error(f"✗ 场景丰富化过程中出现错误: {str(e)}")
# 最终重命名输出文件
try:
import shutil
if os.path.exists(params['output_file']):
shutil.move(params['output_file'], params['final_output_file'])
logger.info(f"✓ 输出文件已重命名为: {params['final_output_file']}")
# 如果没有进行场景丰富化,但进行了文件重命名,需要确保返回的数据是最新的
# 因为result在场景丰富化时已经更新过所以这里只处理未进行丰富化的情况
if not scene_path:
try:
with open(params['final_output_file'], 'r', encoding='utf-8') as f:
result = json.load(f)
logger.info("✓ 已重新加载最终文件数据")
except Exception as e:
logger.error(f"✗ 重新加载最终文件数据失败: {str(e)}")
else:
logger.warning(f"中间文件 {params['output_file']} 不存在,无法重命名")
except Exception as e:
logger.error(f"✗ 文件重命名过程中出现错误: {str(e)}")
logger.info("==== 所有操作已完成 ====")
# 在返回结果中添加输出文件名信息
if isinstance(result, dict):
result['output_filename'] = params['final_output_file']
return result
# import argparse
# def main():
# parser = argparse.ArgumentParser(description='SMAP到Scene自动转换工具')
# parser.add_argument('--smap', required=True, help='输入的smap地图文件路径')
# parser.add_argument('--scene', required=False, help='可选参考scene文件路径')
# args = parser.parse_args()
# convert_smap_to_scene(args.smap, args.scene)
# if __name__ == "__main__":
# main()