合并obj算法更新
This commit is contained in:
parent
b3d7c37399
commit
c8eaf997a2
@ -2,7 +2,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict
|
from typing import Dict, Tuple
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -197,14 +197,14 @@ class ImagePreprocessor:
|
|||||||
|
|
||||||
return self.gps_points
|
return self.gps_points
|
||||||
|
|
||||||
def divide_grids(self) -> Dict[tuple, pd.DataFrame]:
|
def divide_grids(self) -> Tuple[Dict[tuple, pd.DataFrame], Dict[tuple, tuple]]:
|
||||||
"""划分网格"""
|
"""划分网格"""
|
||||||
self.logger.info(f"开始划分网格 (重叠率: {self.config.grid_overlap})")
|
self.logger.info(f"开始划分网格 (重叠率: {self.config.grid_overlap})")
|
||||||
grid_divider = GridDivider(
|
grid_divider = GridDivider(
|
||||||
overlap=self.config.grid_overlap,
|
overlap=self.config.grid_overlap,
|
||||||
output_dir=self.config.output_dir
|
output_dir=self.config.output_dir
|
||||||
)
|
)
|
||||||
grids = grid_divider.divide_grids(
|
grids, translations = grid_divider.divide_grids(
|
||||||
self.gps_points, grid_size=self.config.grid_size
|
self.gps_points, grid_size=self.config.grid_size
|
||||||
)
|
)
|
||||||
grid_points = grid_divider.assign_to_grids(self.gps_points, grids)
|
grid_points = grid_divider.assign_to_grids(self.gps_points, grids)
|
||||||
@ -212,7 +212,7 @@ class ImagePreprocessor:
|
|||||||
# -1是因为包含了grid_divider
|
# -1是因为包含了grid_divider
|
||||||
self.logger.info(f"成功划分为 {len(grid_points)} 个网格")
|
self.logger.info(f"成功划分为 {len(grid_points)} 个网格")
|
||||||
|
|
||||||
return grid_points
|
return grid_points, translations
|
||||||
|
|
||||||
def copy_images(self, grid_points: Dict[tuple, pd.DataFrame]):
|
def copy_images(self, grid_points: Dict[tuple, pd.DataFrame]):
|
||||||
"""复制图像到目标文件夹"""
|
"""复制图像到目标文件夹"""
|
||||||
@ -238,11 +238,11 @@ class ImagePreprocessor:
|
|||||||
merger = MergeTif(self.config.output_dir)
|
merger = MergeTif(self.config.output_dir)
|
||||||
merger.merge_all_tifs(grid_points)
|
merger.merge_all_tifs(grid_points)
|
||||||
|
|
||||||
def merge_obj(self, grid_points: Dict[int, pd.DataFrame]):
|
def merge_obj(self, grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):
|
||||||
"""合并所有网格的OBJ模型"""
|
"""合并所有网格的OBJ模型"""
|
||||||
self.logger.info("开始合并OBJ模型")
|
self.logger.info("开始合并OBJ模型")
|
||||||
merger = MergeObj(self.config.output_dir)
|
merger = MergeObj(self.config.output_dir)
|
||||||
merger.merge_grid_obj(grid_points)
|
merger.merge_grid_obj(grid_points, translations)
|
||||||
|
|
||||||
def merge_ply(self, grid_points: Dict[int, pd.DataFrame]):
|
def merge_ply(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
"""合并所有网格的PLY点云"""
|
"""合并所有网格的PLY点云"""
|
||||||
@ -257,13 +257,13 @@ class ImagePreprocessor:
|
|||||||
self.cluster()
|
self.cluster()
|
||||||
# self.filter_time_group_overlap()
|
# self.filter_time_group_overlap()
|
||||||
self.filter_points()
|
self.filter_points()
|
||||||
grid_points = self.divide_grids()
|
grid_points, translations = self.divide_grids()
|
||||||
self.copy_images(grid_points)
|
self.copy_images(grid_points)
|
||||||
self.logger.info("预处理任务完成")
|
self.logger.info("预处理任务完成")
|
||||||
|
|
||||||
self.odm_monitor.process_all_grids(grid_points)
|
# self.odm_monitor.process_all_grids(grid_points)
|
||||||
# self.merge_tif(grid_points)
|
# self.merge_tif(grid_points)
|
||||||
# self.merge_obj(grid_points)
|
# self.merge_obj(grid_points, translations)
|
||||||
# self.merge_ply(grid_points)
|
# self.merge_ply(grid_points)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"处理过程中发生错误: {str(e)}", exc_info=True)
|
self.logger.error(f"处理过程中发生错误: {str(e)}", exc_info=True)
|
||||||
|
@ -2,7 +2,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict
|
from typing import Dict, Tuple
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -197,20 +197,25 @@ class ImagePreprocessor:
|
|||||||
|
|
||||||
return self.gps_points
|
return self.gps_points
|
||||||
|
|
||||||
def divide_grids(self) -> Dict[tuple, pd.DataFrame]:
|
def divide_grids(self) -> Tuple[Dict[tuple, pd.DataFrame], Dict[tuple, tuple]]:
|
||||||
"""划分网格"""
|
"""划分网格
|
||||||
|
Returns:
|
||||||
|
tuple: (grid_points, translations)
|
||||||
|
- grid_points: 网格点数据字典
|
||||||
|
- translations: 网格平移量字典
|
||||||
|
"""
|
||||||
self.logger.info(f"开始划分网格 (重叠率: {self.config.grid_overlap})")
|
self.logger.info(f"开始划分网格 (重叠率: {self.config.grid_overlap})")
|
||||||
grid_divider = GridDivider(
|
grid_divider = GridDivider(
|
||||||
overlap=self.config.grid_overlap,
|
overlap=self.config.grid_overlap,
|
||||||
output_dir=self.config.output_dir
|
output_dir=self.config.output_dir
|
||||||
)
|
)
|
||||||
grids = grid_divider.divide_grids(
|
grids, translations = grid_divider.divide_grids(
|
||||||
self.gps_points, grid_size=self.config.grid_size
|
self.gps_points, grid_size=self.config.grid_size
|
||||||
)
|
)
|
||||||
grid_points = grid_divider.assign_to_grids(self.gps_points, grids)
|
grid_points = grid_divider.assign_to_grids(self.gps_points, grids)
|
||||||
self.logger.info(f"成功划分为 {len(grid_points)} 个网格")
|
self.logger.info(f"成功划分为 {len(grid_points)} 个网格")
|
||||||
|
|
||||||
return grid_points
|
return grid_points, translations
|
||||||
|
|
||||||
def copy_images(self, grid_points: Dict[tuple, pd.DataFrame]):
|
def copy_images(self, grid_points: Dict[tuple, pd.DataFrame]):
|
||||||
"""复制图像到目标文件夹"""
|
"""复制图像到目标文件夹"""
|
||||||
@ -235,11 +240,11 @@ class ImagePreprocessor:
|
|||||||
merger = MergeTif(self.config.output_dir)
|
merger = MergeTif(self.config.output_dir)
|
||||||
merger.merge_all_tifs(grid_points)
|
merger.merge_all_tifs(grid_points)
|
||||||
|
|
||||||
def merge_obj(self, grid_points: Dict[tuple, pd.DataFrame]):
|
def merge_obj(self, grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):
|
||||||
"""合并所有网格的OBJ模型"""
|
"""合并所有网格的OBJ模型"""
|
||||||
self.logger.info("开始合并OBJ模型")
|
self.logger.info("开始合并OBJ模型")
|
||||||
merger = MergeObj(self.config.output_dir)
|
merger = MergeObj(self.config.output_dir)
|
||||||
merger.merge_grid_obj(grid_points, self.config.grid_size)
|
merger.merge_grid_obj(grid_points, translations)
|
||||||
|
|
||||||
def merge_ply(self, grid_points: Dict[tuple, pd.DataFrame]):
|
def merge_ply(self, grid_points: Dict[tuple, pd.DataFrame]):
|
||||||
"""合并所有网格的PLY点云"""
|
"""合并所有网格的PLY点云"""
|
||||||
@ -254,14 +259,14 @@ class ImagePreprocessor:
|
|||||||
self.cluster()
|
self.cluster()
|
||||||
# self.filter_time_group_overlap()
|
# self.filter_time_group_overlap()
|
||||||
self.filter_points()
|
self.filter_points()
|
||||||
grid_points = self.divide_grids()
|
grid_points, translations = self.divide_grids()
|
||||||
# self.copy_images(grid_points)
|
# self.copy_images(grid_points)
|
||||||
self.logger.info("预处理任务完成")
|
self.logger.info("预处理任务完成")
|
||||||
|
|
||||||
# self.odm_monitor.process_all_grids(grid_points)
|
# self.odm_monitor.process_all_grids(grid_points)
|
||||||
# self.merge_tif(grid_points)
|
# self.merge_tif(grid_points)
|
||||||
# self.merge_ply(grid_points)
|
# self.merge_ply(grid_points)
|
||||||
self.merge_obj(grid_points)
|
self.merge_obj(grid_points, translations)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"处理过程中发生错误: {str(e)}", exc_info=True)
|
self.logger.error(f"处理过程中发生错误: {str(e)}", exc_info=True)
|
||||||
raise
|
raise
|
||||||
|
@ -3,6 +3,7 @@ import logging
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
class MergeObj:
|
class MergeObj:
|
||||||
@ -21,9 +22,11 @@ class MergeObj:
|
|||||||
if len(parts) == 0:
|
if len(parts) == 0:
|
||||||
continue
|
continue
|
||||||
if parts[0] == 'v': # 顶点
|
if parts[0] == 'v': # 顶点
|
||||||
vertices.append([float(parts[1]), float(parts[2]), float(parts[3])])
|
vertices.append(
|
||||||
|
[float(parts[1]), float(parts[2]), float(parts[3])])
|
||||||
elif parts[0] == 'f': # 面
|
elif parts[0] == 'f': # 面
|
||||||
faces.append([int(parts[1].split('/')[0]), int(parts[2].split('/')[0]), int(parts[3].split('/')[0])])
|
faces.append([int(parts[1].split(
|
||||||
|
'/')[0]), int(parts[2].split('/')[0]), int(parts[3].split('/')[0])])
|
||||||
|
|
||||||
return vertices, faces
|
return vertices, faces
|
||||||
|
|
||||||
@ -54,11 +57,14 @@ class MergeObj:
|
|||||||
vertices2, faces2 = self.read_obj(obj2_path)
|
vertices2, faces2 = self.read_obj(obj2_path)
|
||||||
|
|
||||||
# 平移第二个模型的顶点
|
# 平移第二个模型的顶点
|
||||||
vertices2_translated = self.translate_vertices(vertices2, translation)
|
vertices2_translated = self.translate_vertices(
|
||||||
|
vertices2, translation)
|
||||||
|
|
||||||
# 合并顶点和面
|
# 合并顶点和面
|
||||||
all_vertices = vertices1 + vertices2_translated
|
all_vertices = vertices1 + vertices2_translated
|
||||||
all_faces = faces1 + [[f[0] + len(vertices1), f[1] + len(vertices1), f[2] + len(vertices1)] for f in faces2]
|
all_faces = faces1 + \
|
||||||
|
[[f[0] + len(vertices1), f[1] + len(vertices1),
|
||||||
|
f[2] + len(vertices1)] for f in faces2]
|
||||||
|
|
||||||
# 写入合并后的obj文件
|
# 写入合并后的obj文件
|
||||||
self.write_obj(output_path, all_vertices, all_faces)
|
self.write_obj(output_path, all_vertices, all_faces)
|
||||||
@ -69,76 +75,161 @@ class MergeObj:
|
|||||||
self.logger.error(f"合并OBJ模型时发生错误: {str(e)}", exc_info=True)
|
self.logger.error(f"合并OBJ模型时发生错误: {str(e)}", exc_info=True)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def calculate_translation(self, grid_id: tuple, grid_size: float) -> tuple:
|
def read_mtl(self, file_path):
|
||||||
"""根据网格坐标和大小计算平移量"""
|
"""读取.mtl文件内容"""
|
||||||
# 直接使用网格的二维坐标计算平移量
|
with open(file_path, 'r') as file:
|
||||||
col, row = grid_id # grid_id是(width_idx, height_idx)格式
|
return file.read()
|
||||||
|
|
||||||
# 计算平移量,考虑到重叠
|
def copy_texture_files(self, src_dir: str, dst_dir: str, grid_id: tuple):
|
||||||
x_translation = col * grid_size
|
"""复制并重命名纹理文件
|
||||||
y_translation = row * grid_size
|
Args:
|
||||||
|
src_dir: 源纹理文件目录
|
||||||
|
dst_dir: 目标纹理文件目录
|
||||||
|
grid_id: 网格ID,用于重命名
|
||||||
|
"""
|
||||||
|
# 确保目标目录存在
|
||||||
|
os.makedirs(dst_dir, exist_ok=True)
|
||||||
|
|
||||||
self.logger.info(
|
# 复制所有png文件并重命名
|
||||||
f"网格 ({col},{row}) 的平移量: x={x_translation}, y={y_translation}"
|
for file in os.listdir(src_dir):
|
||||||
)
|
if file.endswith('.png'):
|
||||||
|
src_file = os.path.join(src_dir, file)
|
||||||
|
# 在文件名前添加网格ID前缀
|
||||||
|
new_name = f"grid_{grid_id[0]}_{grid_id[1]}_{file}"
|
||||||
|
dst_file = os.path.join(dst_dir, new_name)
|
||||||
|
shutil.copy2(src_file, dst_file)
|
||||||
|
self.logger.debug(f"复制纹理文件: {file} -> {new_name}")
|
||||||
|
|
||||||
return (x_translation, y_translation, 0) # z轴不需要平移
|
return dst_dir
|
||||||
|
|
||||||
def merge_grid_obj(self, grid_points: Dict[tuple, pd.DataFrame], grid_size: float = 500):
|
def update_mtl_content(self, mtl_content: str, grid_id: tuple) -> str:
|
||||||
"""合并所有网格的OBJ模型"""
|
"""更新MTL文件内容,修改纹理文件路径
|
||||||
|
Args:
|
||||||
|
mtl_content: 原MTL文件内容
|
||||||
|
grid_id: 网格ID,用于重命名纹理文件
|
||||||
|
Returns:
|
||||||
|
更新后的MTL文件内容
|
||||||
|
"""
|
||||||
|
updated_content = []
|
||||||
|
for line in mtl_content.split('\n'):
|
||||||
|
if line.startswith('map_Kd'): # 纹理文件路径行
|
||||||
|
# 获取原始文件名
|
||||||
|
original_file = line.split()[-1]
|
||||||
|
# 添加网格ID前缀
|
||||||
|
new_file = f"grid_{grid_id[0]}_{grid_id[1]}_{os.path.basename(original_file)}"
|
||||||
|
# 更新行内容
|
||||||
|
line = f"map_Kd {new_file}"
|
||||||
|
updated_content.append(line)
|
||||||
|
return '\n'.join(updated_content)
|
||||||
|
|
||||||
|
def merge_grid_obj(self, grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):
|
||||||
|
"""合并所有网格的OBJ模型和纹理"""
|
||||||
self.logger.info("开始合并所有网格的OBJ模型")
|
self.logger.info("开始合并所有网格的OBJ模型")
|
||||||
|
|
||||||
if len(grid_points) < 2:
|
if len(grid_points) < 2:
|
||||||
self.logger.info("只有一个网格,无需合并")
|
self.logger.info("只有一个网格,无需合并")
|
||||||
return
|
return
|
||||||
|
|
||||||
input_obj1, input_obj2 = None, None
|
|
||||||
merge_count = 0
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# 创建输出目录
|
||||||
|
output_model_dir = os.path.join(self.output_dir, "merged_model")
|
||||||
|
os.makedirs(output_model_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# 获取所有有效的网格OBJ文件
|
||||||
|
grid_objs = {}
|
||||||
for grid_id, points in grid_points.items():
|
for grid_id, points in grid_points.items():
|
||||||
grid_obj = os.path.join(
|
grid_base_dir = os.path.join(
|
||||||
self.output_dir,
|
self.output_dir,
|
||||||
f"grid_{grid_id[0]}_{grid_id[1]}",
|
f"grid_{grid_id[0]}_{grid_id[1]}",
|
||||||
"project",
|
"project",
|
||||||
"odm_texturing",
|
"odm_texturing"
|
||||||
"odm_textured_model_geo.obj"
|
|
||||||
)
|
)
|
||||||
|
grid_obj = os.path.join(grid_base_dir, "odm_textured_model_geo.obj")
|
||||||
|
grid_mtl = os.path.join(grid_base_dir, "odm_textured_model_geo.mtl")
|
||||||
|
|
||||||
if not os.path.exists(grid_obj):
|
if not os.path.exists(grid_obj) or not os.path.exists(grid_mtl):
|
||||||
self.logger.warning(f"网格 ({grid_id[0]},{grid_id[1]}) 的OBJ文件不存在: {grid_obj}")
|
self.logger.warning(
|
||||||
|
f"网格 ({grid_id[0]},{grid_id[1]}) 的OBJ或MTL文件不存在")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if input_obj1 is None:
|
grid_objs[grid_id] = {
|
||||||
input_obj1 = grid_obj
|
'obj': grid_obj,
|
||||||
self.logger.info(f"设置第一个输入OBJ: {input_obj1}")
|
'mtl': grid_mtl,
|
||||||
else:
|
'base_dir': grid_base_dir
|
||||||
input_obj2 = grid_obj
|
}
|
||||||
output_obj = os.path.join(self.output_dir, f"merged_model_{merge_count}.obj")
|
|
||||||
|
|
||||||
# 计算当前网格的平移量
|
if not grid_objs:
|
||||||
translation = self.calculate_translation(grid_id, grid_size)
|
self.logger.error("没有找到有效的OBJ文件")
|
||||||
|
return
|
||||||
|
|
||||||
self.logger.info(
|
# 使用第一个网格作为参考
|
||||||
f"开始合并第 {merge_count + 1} 次:\n"
|
reference_id = list(grid_objs.keys())[0]
|
||||||
f"平移量: {translation}\n"
|
merged_obj = grid_objs[reference_id]['obj']
|
||||||
f"输出: {output_obj}"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.merge_two_objs(input_obj1, input_obj2, output_obj, translation)
|
# 复制参考网格的纹理文件
|
||||||
merge_count += 1
|
self.copy_texture_files(
|
||||||
|
grid_objs[reference_id]['base_dir'],
|
||||||
|
output_model_dir,
|
||||||
|
reference_id
|
||||||
|
)
|
||||||
|
|
||||||
input_obj1 = output_obj
|
# 复制并更新参考网格的MTL文件
|
||||||
input_obj2 = None
|
ref_mtl_content = self.read_mtl(grid_objs[reference_id]['mtl'])
|
||||||
|
updated_mtl = self.update_mtl_content(ref_mtl_content, reference_id)
|
||||||
# 最后的结果重命名为merged_model.obj
|
|
||||||
final_output = os.path.join(self.output_dir, "merged_model.obj")
|
|
||||||
if os.path.exists(input_obj1) and input_obj1 != final_output:
|
|
||||||
os.rename(input_obj1, final_output)
|
|
||||||
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
f"OBJ模型合并完成,共执行 {merge_count} 次合并,"
|
f"使用网格 ({reference_id[0]},{reference_id[1]}) 作为参考网格")
|
||||||
f"最终输出文件: {final_output}"
|
|
||||||
|
# 依次合并其他网格
|
||||||
|
for grid_id, grid_files in list(grid_objs.items())[1:]:
|
||||||
|
# 复制当前网格的纹理文件
|
||||||
|
self.copy_texture_files(
|
||||||
|
grid_files['base_dir'],
|
||||||
|
output_model_dir,
|
||||||
|
grid_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# 更新当前网格的MTL内容
|
||||||
|
current_mtl = self.read_mtl(grid_files['mtl'])
|
||||||
|
updated_mtl += '\n' + self.update_mtl_content(current_mtl, grid_id)
|
||||||
|
|
||||||
|
# 获取平移量
|
||||||
|
translation = translations[grid_id]
|
||||||
|
translation = (translation[0], translation[1], 0) # 添加z轴的0平移
|
||||||
|
|
||||||
|
output_obj = os.path.join(
|
||||||
|
output_model_dir,
|
||||||
|
f"merged_model_{reference_id[0]}_{reference_id[1]}_{grid_id[0]}_{grid_id[1]}.obj"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"合并网格 ({grid_id[0]},{grid_id[1]}):\n"
|
||||||
|
f"平移量: x={translation[0]:.2f}m, y={translation[1]:.2f}m\n"
|
||||||
|
f"输出: {output_obj}"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.merge_two_objs(merged_obj, grid_files['obj'],
|
||||||
|
output_obj, translation)
|
||||||
|
merged_obj = output_obj
|
||||||
|
|
||||||
|
# 最后的结果
|
||||||
|
final_obj = os.path.join(output_model_dir, "merged_model.obj")
|
||||||
|
final_mtl = os.path.join(output_model_dir, "merged_model.mtl")
|
||||||
|
|
||||||
|
# 保存最终的OBJ和MTL文件
|
||||||
|
if os.path.exists(merged_obj) and merged_obj != final_obj:
|
||||||
|
shutil.copy2(merged_obj, final_obj)
|
||||||
|
os.remove(merged_obj)
|
||||||
|
|
||||||
|
# 保存合并后的MTL文件
|
||||||
|
with open(final_mtl, 'w') as f:
|
||||||
|
f.write(updated_mtl)
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"模型合并完成,输出目录: {output_model_dir}\n"
|
||||||
|
f"- OBJ文件: merged_model.obj\n"
|
||||||
|
f"- MTL文件: merged_model.mtl\n"
|
||||||
|
f"- 纹理文件: {len(os.listdir(output_model_dir)) - 2}个PNG文件"
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -16,7 +16,12 @@ class GridDivider:
|
|||||||
self.num_grids_height = 0
|
self.num_grids_height = 0
|
||||||
|
|
||||||
def divide_grids(self, points_df, grid_size=500):
|
def divide_grids(self, points_df, grid_size=500):
|
||||||
"""计算边界框并划分网格"""
|
"""计算边界框并划分网格
|
||||||
|
Returns:
|
||||||
|
tuple: (grids, translations)
|
||||||
|
- grids: 网格边界列表
|
||||||
|
- translations: 网格平移量字典
|
||||||
|
"""
|
||||||
self.logger.info("开始划分网格")
|
self.logger.info("开始划分网格")
|
||||||
|
|
||||||
min_lat, max_lat = points_df['lat'].min(), points_df['lat'].max()
|
min_lat, max_lat = points_df['lat'].min(), points_df['lat'].max()
|
||||||
@ -37,7 +42,9 @@ class GridDivider:
|
|||||||
lon_step = (max_lon - min_lon) / self.num_grids_width
|
lon_step = (max_lon - min_lon) / self.num_grids_width
|
||||||
|
|
||||||
grids = []
|
grids = []
|
||||||
|
grid_translations = {} # 存储每个网格相对于第一个网格的平移量
|
||||||
|
|
||||||
|
# 先创建所有网格
|
||||||
for i in range(self.num_grids_height):
|
for i in range(self.num_grids_height):
|
||||||
for j in range(self.num_grids_width):
|
for j in range(self.num_grids_width):
|
||||||
grid_min_lat = min_lat + i * lat_step - self.overlap * lat_step
|
grid_min_lat = min_lat + i * lat_step - self.overlap * lat_step
|
||||||
@ -46,21 +53,36 @@ class GridDivider:
|
|||||||
grid_max_lon = min_lon + (j + 1) * lon_step + self.overlap * lon_step
|
grid_max_lon = min_lon + (j + 1) * lon_step + self.overlap * lon_step
|
||||||
|
|
||||||
grid_id = (j, i) # 使用(width_idx, height_idx)元组作为网格标识
|
grid_id = (j, i) # 使用(width_idx, height_idx)元组作为网格标识
|
||||||
grids.append((grid_min_lat, grid_max_lat, grid_min_lon, grid_max_lon))
|
grid_bounds = (grid_min_lat, grid_max_lat, grid_min_lon, grid_max_lon)
|
||||||
|
grids.append(grid_bounds)
|
||||||
|
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
f"网格[{j},{i}]: 纬度[{grid_min_lat:.6f}, {grid_max_lat:.6f}], "
|
f"网格[{j},{i}]: 纬度[{grid_min_lat:.6f}, {grid_max_lat:.6f}], "
|
||||||
f"经度[{grid_min_lon:.6f}, {grid_max_lon:.6f}]"
|
f"经度[{grid_min_lon:.6f}, {grid_max_lon:.6f}]"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 计算每个网格相对于第一个网格的平移量
|
||||||
|
reference_grid = grids[0]
|
||||||
|
for i in range(self.num_grids_height):
|
||||||
|
for j in range(self.num_grids_width):
|
||||||
|
grid_id = (j, i)
|
||||||
|
grid_idx = i * self.num_grids_width + j
|
||||||
|
if grid_idx == 0: # 参考网格
|
||||||
|
grid_translations[grid_id] = (0, 0)
|
||||||
|
else:
|
||||||
|
translation = self.calculate_grid_translation(reference_grid, grids[grid_idx])
|
||||||
|
grid_translations[grid_id] = translation
|
||||||
|
self.logger.debug(
|
||||||
|
f"网格[{j},{i}]相对于参考网格的平移量: x={translation[0]:.2f}m, y={translation[1]:.2f}m"
|
||||||
|
)
|
||||||
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
f"成功划分为 {len(grids)} 个网格 ({self.num_grids_width}x{self.num_grids_height})")
|
f"成功划分为 {len(grids)} 个网格 ({self.num_grids_width}x{self.num_grids_height})")
|
||||||
|
|
||||||
|
|
||||||
# 添加可视化调用
|
# 添加可视化调用
|
||||||
self.visualize_grids(points_df, grids)
|
self.visualize_grids(points_df, grids)
|
||||||
|
|
||||||
return grids
|
return grids, grid_translations
|
||||||
|
|
||||||
|
|
||||||
def assign_to_grids(self, points_df, grids):
|
def assign_to_grids(self, points_df, grids):
|
||||||
@ -141,3 +163,44 @@ class GridDivider:
|
|||||||
self.logger.info(f"网格划分可视化图已保存至: {save_path}")
|
self.logger.info(f"网格划分可视化图已保存至: {save_path}")
|
||||||
|
|
||||||
plt.close()
|
plt.close()
|
||||||
|
|
||||||
|
def get_grid_center(self, grid_bounds) -> tuple:
|
||||||
|
"""计算网格中心点的经纬度
|
||||||
|
Args:
|
||||||
|
grid_bounds: (min_lat, max_lat, min_lon, max_lon)
|
||||||
|
Returns:
|
||||||
|
(center_lat, center_lon)
|
||||||
|
"""
|
||||||
|
min_lat, max_lat, min_lon, max_lon = grid_bounds
|
||||||
|
return ((min_lat + max_lat) / 2, (min_lon + max_lon) / 2)
|
||||||
|
|
||||||
|
def calculate_grid_translation(self, reference_grid: tuple, target_grid: tuple) -> tuple:
|
||||||
|
"""计算目标网格相对于参考网格的平移距离(米)
|
||||||
|
Args:
|
||||||
|
reference_grid: 参考网格的边界 (min_lat, max_lat, min_lon, max_lon)
|
||||||
|
target_grid: 目标网格的边界 (min_lat, max_lat, min_lon, max_lon)
|
||||||
|
Returns:
|
||||||
|
(x_translation, y_translation): 在米制单位下的平移量
|
||||||
|
"""
|
||||||
|
ref_center = self.get_grid_center(reference_grid)
|
||||||
|
target_center = self.get_grid_center(target_grid)
|
||||||
|
|
||||||
|
# 计算经度方向的距离(x轴)
|
||||||
|
x_distance = geodesic(
|
||||||
|
(ref_center[0], ref_center[1]),
|
||||||
|
(ref_center[0], target_center[1])
|
||||||
|
).meters
|
||||||
|
# 如果目标在参考点西边,距离为负
|
||||||
|
if target_center[1] < ref_center[1]:
|
||||||
|
x_distance = -x_distance
|
||||||
|
|
||||||
|
# 计算纬度方向的距离(y轴)
|
||||||
|
y_distance = geodesic(
|
||||||
|
(ref_center[0], ref_center[1]),
|
||||||
|
(target_center[0], ref_center[1])
|
||||||
|
).meters
|
||||||
|
# 如果目标在参考点南边,距离为负
|
||||||
|
if target_center[0] < ref_center[0]:
|
||||||
|
y_distance = -y_distance
|
||||||
|
|
||||||
|
return (x_distance, y_distance)
|
||||||
|
Loading…
Reference in New Issue
Block a user