refactor: 借鉴 PointHashGrid3d 优化空间哈希网格
改进内容: 1. 使用 ScaleGridIndexer3 实现更清晰的坐标转换(职责分离) 2. 优化 FindInRadius:提前判断 distanceFunc 是否为 null,避免循环中重复检查 3. 使用 TryGetValue 避免字典的两次查找 4. 增强代码注释,说明设计参考和增强点 参考 geometry3Sharp 的 PointHashGrid3d 设计,但保留了我们实现的优势: - 支持返回范围内所有对象(不仅是最近的一个) - 支持直接访问网格单元 - 提供详细的统计信息
This commit is contained in:
parent
d889635c1c
commit
8cec18a141
@ -7,12 +7,18 @@ namespace NavisworksTransport.Core.Spatial
|
||||
/// <summary>
|
||||
/// 自定义3D空间哈希网格
|
||||
/// 用于高效的空间范围查询,复杂度 O(1) 平均
|
||||
///
|
||||
/// 设计参考 geometry3Sharp 的 PointHashGrid3d,但提供了以下增强:
|
||||
/// 1. 支持返回范围内的所有对象(而不仅是最近的一个)
|
||||
/// 2. 支持直接访问网格单元(GetObjectsInCell)
|
||||
/// 3. 提供详细的统计信息用于性能分析
|
||||
/// 4. 使用 ScaleGridIndexer3 实现更清晰的坐标转换
|
||||
/// </summary>
|
||||
/// <typeparam name="T">存储的对象类型</typeparam>
|
||||
public class SpatialHashGrid<T>
|
||||
{
|
||||
private readonly Dictionary<Vector3i, List<T>> _grid;
|
||||
private readonly double _cellSize;
|
||||
private readonly ScaleGridIndexer3 _indexer;
|
||||
|
||||
/// <summary>
|
||||
/// 创建空间哈希网格
|
||||
@ -23,14 +29,14 @@ namespace NavisworksTransport.Core.Spatial
|
||||
if (cellSize <= 0)
|
||||
throw new ArgumentException("格子大小必须大于0", nameof(cellSize));
|
||||
|
||||
_cellSize = cellSize;
|
||||
_indexer = new ScaleGridIndexer3() { CellSize = cellSize };
|
||||
_grid = new Dictionary<Vector3i, List<T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格子大小(模型单位)
|
||||
/// </summary>
|
||||
public double CellSize => _cellSize;
|
||||
public double CellSize => _indexer.CellSize;
|
||||
|
||||
/// <summary>
|
||||
/// 格子总数
|
||||
@ -60,14 +66,15 @@ namespace NavisworksTransport.Core.Spatial
|
||||
/// <param name="position">对象的3D位置</param>
|
||||
public void Insert(T item, Vector3d position)
|
||||
{
|
||||
var gridCell = ToGridCoordinates(position);
|
||||
var gridCell = _indexer.ToGrid(position);
|
||||
|
||||
if (!_grid.ContainsKey(gridCell))
|
||||
if (!_grid.TryGetValue(gridCell, out var cellList))
|
||||
{
|
||||
_grid[gridCell] = new List<T>();
|
||||
cellList = new List<T>();
|
||||
_grid[gridCell] = cellList;
|
||||
}
|
||||
|
||||
_grid[gridCell].Add(item);
|
||||
cellList.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -111,8 +118,11 @@ namespace NavisworksTransport.Core.Spatial
|
||||
var results = new HashSet<T>();
|
||||
|
||||
// 计算需要检查的格子范围
|
||||
int gridRadius = (int)Math.Ceiling(radius / _cellSize);
|
||||
var centerGrid = ToGridCoordinates(center);
|
||||
int gridRadius = (int)Math.Ceiling(radius / _indexer.CellSize);
|
||||
var centerGrid = _indexer.ToGrid(center);
|
||||
|
||||
// 优化:提前创建忽略函数,避免在循环中检查 null(借鉴 PointHashGrid3d)
|
||||
bool hasDistanceCheck = (distanceFunc != null);
|
||||
|
||||
// 遍历查询范围内的所有格子
|
||||
for (int dx = -gridRadius; dx <= gridRadius; dx++)
|
||||
@ -127,12 +137,13 @@ namespace NavisworksTransport.Core.Spatial
|
||||
centerGrid.z + dz
|
||||
);
|
||||
|
||||
// 使用 TryGetValue 避免两次字典查找(借鉴 PointHashGrid3d)
|
||||
if (_grid.TryGetValue(gridCell, out var cellObjects))
|
||||
{
|
||||
foreach (var obj in cellObjects)
|
||||
{
|
||||
// 如果提供了距离函数,进行精确距离检查
|
||||
if (distanceFunc != null)
|
||||
if (hasDistanceCheck)
|
||||
{
|
||||
double distance = distanceFunc(obj);
|
||||
if (distance <= radius)
|
||||
@ -185,21 +196,7 @@ namespace NavisworksTransport.Core.Spatial
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将世界坐标转换为网格坐标
|
||||
/// </summary>
|
||||
/// <param name="position">世界坐标</param>
|
||||
/// <returns>网格坐标</returns>
|
||||
private Vector3i ToGridCoordinates(Vector3d position)
|
||||
{
|
||||
return new Vector3i(
|
||||
(int)Math.Floor(position.x / _cellSize),
|
||||
(int)Math.Floor(position.y / _cellSize),
|
||||
(int)Math.Floor(position.z / _cellSize)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网格统计信息(用于调试)
|
||||
/// 获取网格统计信息(用于调试和性能分析)
|
||||
/// </summary>
|
||||
/// <returns>统计信息字符串</returns>
|
||||
public string GetStatistics()
|
||||
@ -230,7 +227,7 @@ namespace NavisworksTransport.Core.Spatial
|
||||
minObjectsPerCell = 0;
|
||||
|
||||
return $"空间哈希网格统计:\n" +
|
||||
$" 格子大小: {_cellSize:F2} 模型单位\n" +
|
||||
$" 格子大小: {_indexer.CellSize:F2} 模型单位\n" +
|
||||
$" 总格子数: {_grid.Count}\n" +
|
||||
$" 总对象数: {totalObjects}\n" +
|
||||
$" 平均每格对象数: {avgObjectsPerCell:F2}\n" +
|
||||
|
||||
Loading…
Reference in New Issue
Block a user