From ccdada3aadbfebae7d725048b3fb21a1a5c3e838 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Fri, 19 Dec 2025 17:44:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86=E5=A2=99?= =?UTF-8?q?=E5=92=8C=E6=9F=B1=E5=AD=90=E6=A3=80=E6=B5=8B=E4=B8=8D=E5=88=B0?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NavisworksTransport.UnitTests.csproj | 9 ++++ src/Core/Animation/PathAnimationManager.cs | 3 +- src/Core/Spatial/SpatialHashGrid.cs | 60 +++++++++++++++++----- src/Core/Spatial/SpatialIndexManager.cs | 8 +-- 4 files changed, 62 insertions(+), 18 deletions(-) diff --git a/NavisworksTransport.UnitTests.csproj b/NavisworksTransport.UnitTests.csproj index 77f2cd6..219f778 100644 --- a/NavisworksTransport.UnitTests.csproj +++ b/NavisworksTransport.UnitTests.csproj @@ -79,6 +79,12 @@ packages\RoyT.AStar.3.0.2\lib\netstandard2.0\Roy-T.AStar.dll True + + + + packages\geometry4Sharp.1.0.0\lib\net462\geometry4Sharp.dll + True + @@ -88,6 +94,9 @@ + + + diff --git a/src/Core/Animation/PathAnimationManager.cs b/src/Core/Animation/PathAnimationManager.cs index 8de88ad..4b8bfa2 100644 --- a/src/Core/Animation/PathAnimationManager.cs +++ b/src/Core/Animation/PathAnimationManager.cs @@ -446,7 +446,8 @@ namespace NavisworksTransport.Core.Animation boundingBoxSize.Y * boundingBoxSize.Y + boundingBoxSize.Z * boundingBoxSize.Z ); - searchRadiusInModelUnits = objectDiagonal / 2 + _detectionGap; + //空间查询半径,不能设置太小,否则会漏掉周围的对象 + searchRadiusInModelUnits = objectDiagonal + _detectionGap; LogManager.Info($"空间查询半径: {searchRadiusInModelUnits:F2} 模型单位"); } diff --git a/src/Core/Spatial/SpatialHashGrid.cs b/src/Core/Spatial/SpatialHashGrid.cs index 007135d..e3090a7 100644 --- a/src/Core/Spatial/SpatialHashGrid.cs +++ b/src/Core/Spatial/SpatialHashGrid.cs @@ -60,32 +60,65 @@ namespace NavisworksTransport.Core.Spatial } /// - /// 插入对象到空间哈希网格 + /// 插入对象到空间哈希网格(边界框版本) + /// 对象将被插入到其边界框覆盖的所有格子中 /// /// 要插入的对象 - /// 对象的3D位置 - public void Insert(T item, Vector3d position) + /// 边界框最小点 + /// 边界框最大点 + public void Insert(T item, Vector3d boundsMin, Vector3d boundsMax) { - var gridCell = _indexer.ToGrid(position); + // 计算边界框覆盖的格子范围 + var minGridCell = _indexer.ToGrid(boundsMin); + var maxGridCell = _indexer.ToGrid(boundsMax); - if (!_grid.TryGetValue(gridCell, out var cellList)) + // 遍历边界框覆盖的所有格子 + for (int x = minGridCell.x; x <= maxGridCell.x; x++) { - cellList = new List(); - _grid[gridCell] = cellList; - } + for (int y = minGridCell.y; y <= maxGridCell.y; y++) + { + for (int z = minGridCell.z; z <= maxGridCell.z; z++) + { + var gridCell = new Vector3i(x, y, z); - cellList.Add(item); + if (!_grid.TryGetValue(gridCell, out var cellList)) + { + cellList = new List(); + _grid[gridCell] = cellList; + } + + cellList.Add(item); + } + } + } } + + + /// + /// 插入对象到空间哈希网格(使用 Navisworks BoundingBox3D) + /// 对象将被插入到其边界框覆盖的所有格子中 + /// + /// 要插入的对象 + /// Navisworks 边界框 + public void Insert(T item, Autodesk.Navisworks.Api.BoundingBox3D bounds) + { + var boundsMin = new Vector3d(bounds.Min.X, bounds.Min.Y, bounds.Min.Z); + var boundsMax = new Vector3d(bounds.Max.X, bounds.Max.Y, bounds.Max.Z); + Insert(item, boundsMin, boundsMax); + } + + + /// /// 批量插入对象 /// - /// 对象和位置的键值对 - public void InsertRange(IEnumerable> items) + /// 对象和边界框的键值对 + public void InsertRange(IEnumerable> items) { foreach (var kvp in items) { - Insert(kvp.Key, kvp.Value); + Insert(kvp.Key, kvp.Value.min, kvp.Value.max); } } @@ -105,11 +138,12 @@ namespace NavisworksTransport.Core.Spatial /// /// 范围查询:查找指定位置附近指定半径内的所有对象 + /// 注意:由于对象可能被插入到多个格子中,使用 HashSet 自动去重 /// /// 查询中心位置 /// 查询半径(模型单位) /// 可选的距离计算函数(用于精确过滤) - /// 范围内的对象列表(去重) + /// 范围内的对象列表(自动去重) public List FindInRadius( Vector3d center, double radius, diff --git a/src/Core/Spatial/SpatialIndexManager.cs b/src/Core/Spatial/SpatialIndexManager.cs index 55683a1..495f939 100644 --- a/src/Core/Spatial/SpatialIndexManager.cs +++ b/src/Core/Spatial/SpatialIndexManager.cs @@ -104,7 +104,7 @@ namespace NavisworksTransport.Core.Spatial { try { - // 获取包围盒中心作为对象位置 + // 获取包围盒 var bbox = item.BoundingBox(); var center = new Vector3d( (bbox.Min.X + bbox.Max.X) / 2.0, @@ -112,10 +112,10 @@ namespace NavisworksTransport.Core.Spatial (bbox.Min.Z + bbox.Max.Z) / 2.0 ); - // 插入到空间索引 - _globalSpatialIndex.Insert(item, center); + // 使用边界框插入到空间索引(支持大型对象覆盖多个格子) + _globalSpatialIndex.Insert(item, bbox); - // 缓存位置 + // 缓存位置(用于快速查询) _objectPositions[item] = center; indexedCount++;