From 0d9eeed89b3f775a1204db947af43df3bb12401b Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Wed, 4 Feb 2026 12:59:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8D=95=E4=BD=8D=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E7=9A=84=E5=A4=84=E7=90=86=EF=BC=8C=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=8F=90=E9=AB=98=E6=80=A7=E8=83=BD=EF=BC=9B?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E7=B1=B3=E5=8D=95=E4=BD=8D=E7=9A=84=E4=BD=BF?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/design/2026/吊装路径通行空间设计.md | 29 ++++ src/Core/MainPlugin.cs | 3 + src/Core/PathPointRenderPlugin.cs | 204 ++++++++++++------------ src/PathPlanning/AutoPathFinder.cs | 22 ++- src/PathPlanning/GridMapGenerator.cs | 13 +- src/Utils/UnitsConverter.cs | 86 +++++++--- 6 files changed, 212 insertions(+), 145 deletions(-) diff --git a/doc/design/2026/吊装路径通行空间设计.md b/doc/design/2026/吊装路径通行空间设计.md index f304f50..ac5e419 100644 --- a/doc/design/2026/吊装路径通行空间设计.md +++ b/doc/design/2026/吊装路径通行空间设计.md @@ -128,6 +128,34 @@ if (horizontalDirection != null) } ``` +### 起点终点延伸 + +为了确保通行空间完全包裹物体,所有水平段的起点和终点都需要向路径方向延伸半个物体尺寸: + +```csharp +// 通行空间包裹调整:水平段起点向反方向、终点向正方向各延伸半个物体尺寸 +if (_visualizationMode == PathVisualizationMode.VehicleSpace && !isVerticalSegment) +{ + double offset = alongPathSize / 2.0; // 沿路径方向的物体尺寸的一半 + + // 起点向反方向延伸 + adjustedStartPoint = new Point3D( + adjustedStartPoint.X - dirX * offset, + adjustedStartPoint.Y - dirY * offset, + adjustedStartPoint.Z - dirZ * offset + ); + + // 终点向正方向延伸 + adjustedEndPoint = new Point3D( + adjustedEndPoint.X + dirX * offset, + adjustedEndPoint.Y + dirY * offset, + adjustedEndPoint.Z + dirZ * offset + ); +} +``` + +**原因**:路径点使用物体中心坐标,如果不延伸,起点和终点处只会包裹物体的一半。 + ### 渲染模式 使用 `VehicleSpace` 可视化模式显示吊装路径的通行空间: @@ -135,6 +163,7 @@ if (horizontalDirection != null) - 起吊/下降段:垂直长方体,截面为物体宽度 × 物体长度 - 平移段(初始方向):水平长方体,截面为物体宽度 × 物体高度 - 平移段(转折90度):水平长方体,截面为物体长度 × 物体高度 +- **所有水平段**:起点和终点向路径方向延伸半个物体尺寸,确保完全包裹 ## 参考 diff --git a/src/Core/MainPlugin.cs b/src/Core/MainPlugin.cs index d8e7714..4318729 100644 --- a/src/Core/MainPlugin.cs +++ b/src/Core/MainPlugin.cs @@ -473,6 +473,9 @@ namespace NavisworksTransport { LogManager.Info($"[文档管理] 文档已切换到: {NavisApplication.ActiveDocument?.FileName ?? "无活动文档"}"); + // 清除单位转换缓存(文档切换后单位可能不同) + Utils.UnitsConverter.ClearCache(); + GlobalExceptionHandler.SafeExecute(() => { var activeDoc = NavisApplication.ActiveDocument; diff --git a/src/Core/PathPointRenderPlugin.cs b/src/Core/PathPointRenderPlugin.cs index dbb2664..604e664 100644 --- a/src/Core/PathPointRenderPlugin.cs +++ b/src/Core/PathPointRenderPlugin.cs @@ -389,14 +389,14 @@ namespace NavisworksTransport // 网格点类型配置 private GridPointType _gridPointType = GridPointType.Rectangle; - // 通行空间参数(最终尺寸,已包括安全间隙) - private double _passageAlongPath; // 通行空间沿路径方向的尺寸 - private double _passageAcrossPath; // 通行空间垂直于路径方向的尺寸 - private double _passageNormalToPath; // 通行空间法线方向的尺寸(垂直于路径和垂直于路径方向) + // 通行空间参数(最终尺寸,已包括安全间隙)- 内部使用模型单位 + private double _passageAlongPath; // 通行空间沿路径方向的尺寸(模型单位) + private double _passageAcrossPath; // 通行空间垂直于路径方向的尺寸(模型单位) + private double _passageNormalToPath; // 通行空间法线方向的尺寸(模型单位) - // 物体尺寸(米) - private double _objectLength; // 物体长度(米) - private double _objectHeight; // 物体高度(米) + // 物体尺寸 - 内部使用模型单位 + private double _objectLength; // 物体长度(模型单位) + private double _objectHeight; // 物体高度(模型单位) // 静态实例,用于外部访问 private static PathPointRenderPlugin _instance; @@ -1367,39 +1367,39 @@ namespace NavisworksTransport /// 计算通行空间参数(高度、宽度、颜色、透明度、垂直偏移) /// /// 路径可视化对象 - /// 米到模型单位的转换系数 /// 是否是垂直段(仅用于吊装路径) /// 是否是与初始方向垂直的水平段(吊装路径转折90度) /// 通行空间参数元组 - private (double heightInModelUnits, double widthInModelUnits, Color lineColor, double lineOpacity, double verticalOffset) - CalculatePassageSpaceParameters(PathVisualization visualization, double metersToModelUnits, bool isVerticalSegment = false, bool isTurn90Horizontal = false) + private (double height, double width, Color lineColor, double lineOpacity, double verticalOffset) + CalculatePassageSpaceParameters(PathVisualization visualization, bool isVerticalSegment = false, bool isTurn90Horizontal = false) { - double heightInMeters; - double widthInMeters; + double height; + double width; Color lineColor; double lineOpacity; if (_visualizationMode == PathVisualizationMode.VehicleSpace) { // VehicleSpace 模式:根据路径类型和段类型计算通行空间尺寸 + // _passage* 和 _object* 字段已经是模型单位(由 SetPassageSpaceParameters 转换) if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting) { // 吊装路径:根据段类型和方向设置尺寸 // 默认:width=物体宽度(垂直于路径),height=物体高度/长度 - widthInMeters = _passageAcrossPath; - heightInMeters = isVerticalSegment ? _objectLength : _objectHeight; + width = _passageAcrossPath; + height = isVerticalSegment ? _objectLength : _objectHeight; // 🔥 水平段转折90度特殊处理:width改用物体长度 if (!isVerticalSegment && isTurn90Horizontal) { - widthInMeters = _objectLength; + width = _objectLength; } } else { // 其他路径类型 - widthInMeters = _passageAcrossPath; - heightInMeters = _passageNormalToPath; + width = _passageAcrossPath; + height = _passageNormalToPath; } var renderStyle = GetRenderStyle(RenderStyleName.VehicleSpace); @@ -1409,8 +1409,9 @@ namespace NavisworksTransport else if (_visualizationMode == PathVisualizationMode.RibbonLine) { // RibbonLine 模式:使用较低的带状高度 - heightInMeters = GetLineRadius() / metersToModelUnits * 0.1; - widthInMeters = _passageAcrossPath; // 使用通行空间垂直于路径方向的尺寸 + // GetLineRadius() 返回模型单位,直接乘以系数 + height = GetLineRadius() * 0.1; + width = _passageAcrossPath; // 已经是模型单位 var renderStyle = GetRenderStyle(RenderStyleName.Line); lineColor = renderStyle.Color; lineOpacity = renderStyle.Alpha; @@ -1418,17 +1419,13 @@ namespace NavisworksTransport else { // StandardLine 模式:不需要高度和宽度(圆柱体) - heightInMeters = 0; - widthInMeters = 0; + height = 0; + width = 0; var renderStyle = GetRenderStyle(RenderStyleName.Line); lineColor = renderStyle.Color; lineOpacity = renderStyle.Alpha; } - // 转换为模型单位 - double heightInModelUnits = heightInMeters * metersToModelUnits; - double widthInModelUnits = widthInMeters * metersToModelUnits; - // 计算通行空间的垂直偏移(根据路径类型) double verticalOffset = 0; if (_visualizationMode == PathVisualizationMode.VehicleSpace) @@ -1436,12 +1433,12 @@ namespace NavisworksTransport if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground) { // 地面路径:路径点是地面位置,通行空间底面在地面,中心需要向下偏移半个高度 - verticalOffset = -heightInModelUnits / 2.0; + verticalOffset = -height / 2.0; } else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail) { // 空轨路径:路径点是轨道中心线位置,通行空间顶面对齐轨道,中心需要向上偏移半个高度 - verticalOffset = heightInModelUnits / 2.0; + verticalOffset = height / 2.0; } else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting) { @@ -1453,12 +1450,12 @@ namespace NavisworksTransport else { // 吊装的水平段:路径点是悬挂点位置,通行空间顶面在悬挂点,中心需要向上偏移半个高度 - verticalOffset = heightInModelUnits / 2.0; + verticalOffset = height / 2.0; } } } - return (heightInModelUnits, widthInModelUnits, lineColor, lineOpacity, verticalOffset); + return (height, width, lineColor, lineOpacity, verticalOffset); } /// @@ -1502,8 +1499,8 @@ namespace NavisworksTransport double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(); // 计算通行空间参数 - var (heightInModelUnits, widthInModelUnits, lineColor, lineOpacity, verticalOffset) = - CalculatePassageSpaceParameters(visualization, metersToModelUnits); + var (height, width, lineColor, lineOpacity, verticalOffset) = + CalculatePassageSpaceParameters(visualization); // 3. 构建路径连线(Edges包含直线段和圆弧段) foreach (var edge in edges) @@ -1545,6 +1542,9 @@ namespace NavisworksTransport adjustedEndPoint = endPoint; } + // 🔥 地面/空轨路径水平段:起点和终点向路径方向延伸半个物体尺寸 + ExtendLineSegmentForVehicleSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath); + var lineMarker = new LineMarker { StartPoint = adjustedStartPoint, @@ -1553,8 +1553,8 @@ namespace NavisworksTransport Radius = GetLineRadius(), SegmentType = PathSegmentType.Straight, SampledPoints = edge.SampledPoints, - Height = heightInModelUnits, // 根据模式设置高度 - Width = widthInModelUnits, // 根据模式设置宽度 + Height = height, // 根据模式设置高度 + Width = width, // 根据模式设置宽度 Opacity = lineOpacity // 根据模式设置透明度 }; visualization.PathLineMarkers.Add(lineMarker); @@ -1625,6 +1625,9 @@ namespace NavisworksTransport adjustedSampledPoints = edge.SampledPoints; } + // 🔥 圆弧段:起点和终点向路径方向延伸半个物体尺寸 + ExtendLineSegmentForVehicleSpace(ref adjustedStartPoint, ref adjustedEndPoint, _passageAlongPath); + var arcMarker = new LineMarker { StartPoint = adjustedStartPoint, @@ -1634,8 +1637,8 @@ namespace NavisworksTransport SegmentType = PathSegmentType.Arc, Trajectory = edge.Trajectory, SampledPoints = adjustedSampledPoints, - Height = heightInModelUnits, // 根据模式设置高度 - Width = widthInModelUnits, // 根据模式设置宽度 + Height = height, // 根据模式设置高度 + Width = width, // 根据模式设置宽度 Opacity = arcLineOpacity // 根据模式设置透明度 }; visualization.PathLineMarkers.Add(arcMarker); @@ -1799,8 +1802,8 @@ namespace NavisworksTransport } } - var (heightInModelUnits, widthInModelUnits, lineColor, lineOpacity, verticalOffset) = - CalculatePassageSpaceParameters(visualization, metersToModelUnits, isVerticalSegment, isTurn90Horizontal); + var (height, width, lineColor, lineOpacity, verticalOffset) = + CalculatePassageSpaceParameters(visualization, isVerticalSegment, isTurn90Horizontal); // 计算长方体的轴向量(right和up向量) var (right, up) = CalculateCuboidAxes(startPoint.Position, endPoint.Position, horizontalDirection); @@ -1831,67 +1834,17 @@ namespace NavisworksTransport adjustedEndPoint = endPoint.Position; } - // 暂时注释掉起点终点调整,先观察原始通行空间的误差 - /* - // 通行空间模式下,调整起点和终点以包裹车辆 - if (_visualizationMode == PathVisualizationMode.VehicleSpace) + // 🔥 通行空间包裹调整:水平段起点和终点延伸以完全包裹物体 + if (!isVerticalSegment) { - bool needAdjust = false; - if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Ground) + // 沿路径方向的物体尺寸(吊装路径根据是否转折90度选择) + double alongPathSize = _passageAlongPath; + if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Hoisting) { - needAdjust = true; - } - else if (visualization.PathRoute.PathType == NavisworksTransport.PathType.Rail) - { - needAdjust = true; - } - - if (needAdjust) - { - // 调整起点:沿起点→第二个点的方向后退半个车辆长度 - if (i == 0 && sortedPoints.Count >= 2) - { - var nextPoint = sortedPoints[1]; - var dx = nextPoint.Position.X - startPoint.Position.X; - var dy = nextPoint.Position.Y - startPoint.Position.Y; - var dz = nextPoint.Position.Z - startPoint.Position.Z; - var length = Math.Sqrt(dx * dx + dy * dy + dz * dz); - LogManager.Info($"[通行空间调整] 起点: 原点=({startPoint.Position.X:F3},{startPoint.Position.Y:F3},{startPoint.Position.Z:F3}), 方向=({dx:F3},{dy:F3},{dz:F3}), 长度={length:F3}, _passageAlongPath={_passageAlongPath:F3}"); - if (length > 0.001) - { - var offset = _passageAlongPath / 2.0; - adjustedStartPoint = new Point3D( - startPoint.Position.X - dx / length * offset, - startPoint.Position.Y - dy / length * offset, - startPoint.Position.Z - dz / length * offset + verticalOffset - ); - LogManager.Info($"[通行空间调整] 调整后起点=({adjustedStartPoint.X:F3},{adjustedStartPoint.Y:F3},{adjustedStartPoint.Z:F3})"); - } - } - - // 调整终点:沿倒数第二个点→终点的方向前进半个车辆长度 - if (i == sortedPoints.Count - 2 && sortedPoints.Count >= 2) - { - var prevPoint = sortedPoints[i]; - var dx = endPoint.Position.X - prevPoint.Position.X; - var dy = endPoint.Position.Y - prevPoint.Position.Y; - var dz = endPoint.Position.Z - prevPoint.Position.Z; - var length = Math.Sqrt(dx * dx + dy * dy + dz * dz); - LogManager.Info($"[通行空间调整] 终点: 原点=({endPoint.Position.X:F3},{endPoint.Position.Y:F3},{endPoint.Position.Z:F3}), 方向=({dx:F3},{dy:F3},{dz:F3}), 长度={length:F3}, _passageAlongPath={_passageAlongPath:F3}"); - if (length > 0.001) - { - var offset = _passageAlongPath / 2.0; - adjustedEndPoint = new Point3D( - endPoint.Position.X + dx / length * offset, - endPoint.Position.Y + dy / length * offset, - endPoint.Position.Z + dz / length * offset + verticalOffset - ); - LogManager.Info($"[通行空间调整] 调整后终点=({adjustedEndPoint.X:F3},{adjustedEndPoint.Y:F3},{adjustedEndPoint.Z:F3})"); - } - } + alongPathSize = isTurn90Horizontal ? _passageAcrossPath : _objectLength; } + ExtendLineSegmentForVehicleSpace(ref adjustedStartPoint, ref adjustedEndPoint, alongPathSize); } - */ var lineMarker = new LineMarker { @@ -1902,8 +1855,8 @@ namespace NavisworksTransport SegmentType = PathSegmentType.Straight, FromIndex = startPoint.Index, ToIndex = endPoint.Index, - Height = heightInModelUnits, - Width = widthInModelUnits, + Height = height, + Width = width, Opacity = lineOpacity, HorizontalDirection = horizontalDirection // 设置水平段方向向量 }; @@ -2123,15 +2076,20 @@ namespace NavisworksTransport /// 安全间隙(米) /// 垂直段的高度(物体长度 + 2×安全间隙,模型单位) /// 水平段的高度(物体高度 + 2×安全间隙,模型单位) - public void SetPassageSpaceParameters(double passageAcrossPath, double passageNormalToPath, double passageAlongPath, double passageNormalToPathVertical = 0, double passageNormalToPathHorizontal = 0) + /// + /// 设置通行空间参数 - 外部传入米制单位,内部存储为模型单位 + /// + public void SetPassageSpaceParameters(double passageAcrossPathInMeters, double passageNormalToPathInMeters, double passageAlongPathInMeters, double passageNormalToPathVerticalInMeters = 0, double passageNormalToPathHorizontalInMeters = 0) { - _passageAlongPath = passageAlongPath; // 通行空间沿路径方向的尺寸(模型单位) - _passageAcrossPath = passageAcrossPath; // 通行空间垂直于路径方向的尺寸(模型单位) - _passageNormalToPath = passageNormalToPath; // 通行空间法线方向的尺寸(模型单位) + // 转换为模型单位存储 + double factor = UnitsConverter.GetMetersToUnitsConversionFactor(); + _passageAlongPath = passageAlongPathInMeters * factor; + _passageAcrossPath = passageAcrossPathInMeters * factor; + _passageNormalToPath = passageNormalToPathInMeters * factor; // 保存垂直段和水平段的高度(用于吊装路径分段渲染) - _objectLength = passageNormalToPathVertical; // 垂直段高度(模型单位) - _objectHeight = passageNormalToPathHorizontal; // 水平段高度(模型单位) + _objectLength = passageNormalToPathVerticalInMeters * factor; + _objectHeight = passageNormalToPathHorizontalInMeters * factor; // 参数改变时刷新所有普通路径(因为RibbonLine模式也使用车辆宽度) RefreshNormalPaths(); @@ -2534,9 +2492,9 @@ namespace NavisworksTransport double metersToModelUnits = UnitsConverter.GetMetersToUnitsConversionFactor(); // 转换为模型单位 - double radiusInModelUnits = baseRadiusInMeters * metersToModelUnits; + double radius = baseRadiusInMeters * metersToModelUnits; - return radiusInModelUnits; + return radius; } /// @@ -3030,6 +2988,44 @@ namespace NavisworksTransport } } + /// + /// 延伸线段起点和终点以完全包裹物体(VehicleSpace模式) + /// + /// 起点(会被修改) + /// 终点(会被修改) + private void ExtendLineSegmentForVehicleSpace(ref Point3D startPoint, ref Point3D endPoint, double alongPathSize) + { + if (_visualizationMode != PathVisualizationMode.VehicleSpace) + return; + + var segDx = endPoint.X - startPoint.X; + var segDy = endPoint.Y - startPoint.Y; + var segDz = endPoint.Z - startPoint.Z; + var segLength = Math.Sqrt(segDx * segDx + segDy * segDy + segDz * segDz); + + if (segLength > 0.001) + { + double offset = alongPathSize / 2.0; + var dirX = segDx / segLength; + var dirY = segDy / segLength; + var dirZ = segDz / segLength; + + // 起点向反方向延伸 + startPoint = new Point3D( + startPoint.X - dirX * offset, + startPoint.Y - dirY * offset, + startPoint.Z - dirZ * offset + ); + + // 终点向正方向延伸 + endPoint = new Point3D( + endPoint.X + dirX * offset, + endPoint.Y + dirY * offset, + endPoint.Z + dirZ * offset + ); + } + } + /// /// 请求视图刷新(带防抖机制) /// diff --git a/src/PathPlanning/AutoPathFinder.cs b/src/PathPlanning/AutoPathFinder.cs index e362eee..4f19ad1 100644 --- a/src/PathPlanning/AutoPathFinder.cs +++ b/src/PathPlanning/AutoPathFinder.cs @@ -153,7 +153,7 @@ namespace NavisworksTransport.PathPlanning private delegate float SpeedCalculator( int currentX, int currentY, int currentLayerIndex, double currentZ, int neighborX, int neighborY, int neighborLayerIndex, double neighborZ, - double heightDiff, double baseSpeed, double maxHeightDiffInModelUnits, + double heightDiff, double baseSpeed, double maxHeightDiff, Point3D startPos, Point3D endPos); /// @@ -170,10 +170,9 @@ namespace NavisworksTransport.PathPlanning double baseSpeed = 5.0; // km/h float maxSpeed = (float)baseSpeed; - // 将米转换为模型单位 - double maxHeightDiffMeters = GetMaxHeightDiffMeters(); - double maxHeightDiffInModelUnits = maxHeightDiffMeters * UnitsConverter.GetMetersToUnitsConversionFactor(); - LogManager.Info($"[3D图构建] 高度差阈值: {maxHeightDiffMeters}米 = {maxHeightDiffInModelUnits:F2}模型单位"); + // 使用配置的模型单位值 + double maxHeightDiff = ConfigManager.Instance.Current.PathEditing.MaxHeightDiff; + LogManager.Info($"[3D图构建] 高度差阈值: {ConfigManager.Instance.Current.PathEditing.MaxHeightDiffMeters}米 = {maxHeightDiff:F2}模型单位"); // === 阶段1:创建所有3D节点 === int totalNodesCreated = 0; @@ -268,7 +267,7 @@ namespace NavisworksTransport.PathPlanning continue; double heightDiff = Math.Abs(neighborLayer.Z - currentZ); - if (heightDiff > maxHeightDiffInModelUnits) + if (heightDiff > maxHeightDiff) continue; if (!nodes.TryGetValue((nx, ny, nli), out var neighborNode)) @@ -279,11 +278,11 @@ namespace NavisworksTransport.PathPlanning if (speedCalculator != null) { speed = speedCalculator(x, y, li, currentZ, nx, ny, nli, neighborLayer.Z, - heightDiff, baseSpeed, maxHeightDiffInModelUnits, startPos, endPos); + heightDiff, baseSpeed, maxHeightDiff, startPos, endPos); } else { - speed = CalculateSpeedByHeightDiff(heightDiff, baseSpeed, maxHeightDiffInModelUnits); + speed = CalculateSpeedByHeightDiff(heightDiff, baseSpeed, maxHeightDiff); } maxSpeed = Math.Max(maxSpeed, speed); @@ -337,7 +336,7 @@ namespace NavisworksTransport.PathPlanning continue; double heightDiff = Math.Abs(layer2.Z - layer1.Z); - if (heightDiff > maxHeightDiffInModelUnits) + if (heightDiff > maxHeightDiff) continue; if (!nodes.TryGetValue((x2, y2, li), out var node1) || @@ -1607,15 +1606,14 @@ namespace NavisworksTransport.PathPlanning // 1. 起终点高度差不能超过阈值(原有逻辑:防止跨越大高度差,例如楼梯) // 2. 中间点高度必须与起点和终点一致(新增逻辑:任何高度变化都不能优化掉) bool canSkip = false; - double maxAllowedHeightDiffMeters = GetMaxHeightDiffMeters(); // 从配置文件读取高度差阈值 - double maxAllowedHeightDiffInModelUnits = maxAllowedHeightDiffMeters * UnitsConverter.GetMetersToUnitsConversionFactor(); + double maxAllowedHeightDiff = ConfigManager.Instance.Current.PathEditing.MaxHeightDiff; // 从配置文件读取高度差阈值(模型单位) double startZ = startPoint.Z; double endZ = endPoint.Z; double totalHeightDiff = Math.Abs(endZ - startZ); // 检查1:起终点高度差必须在阈值内 - if (totalHeightDiff <= maxAllowedHeightDiffInModelUnits) + if (totalHeightDiff <= maxAllowedHeightDiff) { // 检查2:所有中间点的高度必须与起点和终点一致(不能有高度变化) bool hasMiddleHeightChange = false; diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index f7a7681..efb5edf 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -157,10 +157,9 @@ namespace NavisworksTransport.PathPlanning // 2.7. 标记边界层(用于膨胀计算) LogManager.Info("【生成网格地图】步骤2.7: 标记边界层"); - double maxHeightDiffMeters = GetMaxHeightDiffMeters(); - double maxHeightDiffInModelUnits = maxHeightDiffMeters * metersToModelUnitsConversionFactor; - LogManager.Info($"【生成网格地图】边界高度差阈值: {maxHeightDiffMeters}米 = {maxHeightDiffInModelUnits:F2}模型单位"); - MarkBoundaryLayers(channelCoverage.GridMap, maxHeightDiffInModelUnits); + double maxHeightDiff = ConfigManager.Instance.Current.PathEditing.MaxHeightDiff; + LogManager.Info($"【生成网格地图】边界高度差阈值: {ConfigManager.Instance.Current.PathEditing.MaxHeightDiffMeters}米 = {maxHeightDiff:F2}模型单位"); + MarkBoundaryLayers(channelCoverage.GridMap, maxHeightDiff); LogManager.Info($"【阶段2.7完成】边界层标记后网格统计: {channelCoverage.GridMap.GetStatistics()}"); // 3. 应用车辆尺寸膨胀 @@ -867,9 +866,7 @@ namespace NavisworksTransport.PathPlanning LogManager.Info($"【多层膨胀】开始按层处理膨胀,网格大小: {gridMap.Width}x{gridMap.Height}, 膨胀半径: {inflationRadius}"); // 计算高度差阈值(用于楼梯口保护) - double metersToModelUnitsConversionFactor = UnitsConverter.GetMetersToUnitsConversionFactor(Application.ActiveDocument.Units); - double maxHeightDiffMeters = GetMaxHeightDiffMeters(); - double maxHeightDiffInModelUnits = maxHeightDiffMeters * metersToModelUnitsConversionFactor; + double maxHeightDiff = ConfigManager.Instance.Current.PathEditing.MaxHeightDiff; // 统计每个层索引的处理情况 var layerStats = new Dictionary(); @@ -897,7 +894,7 @@ namespace NavisworksTransport.PathPlanning int obstacleInflated = InflateObstacles(gridMap, layerIndex, inflationRadius); // 步骤2:边界膨胀(包括边界本身) - var (boundaryCount, boundaryInflated) = InflateBoundaries(gridMap, layerIndex, inflationRadius, maxHeightDiffInModelUnits); + var (boundaryCount, boundaryInflated) = InflateBoundaries(gridMap, layerIndex, inflationRadius, maxHeightDiff); if (boundaryCount > 0 || obstacleInflated > 0) { diff --git a/src/Utils/UnitsConverter.cs b/src/Utils/UnitsConverter.cs index 44a4329..751600c 100644 --- a/src/Utils/UnitsConverter.cs +++ b/src/Utils/UnitsConverter.cs @@ -6,25 +6,77 @@ namespace NavisworksTransport.Utils /// /// Navisworks单位转换工具类 /// 提供统一的单位转换功能,避免代码重复 + /// + /// 性能优化:缓存转换系数,避免重复访问API /// public static class UnitsConverter { + // 缓存字段 - 使用 NaN 作为初始值,避免默认值掩盖错误 + private static double _cachedUnitsToMetersFactor = double.NaN; + private static double _cachedMetersToUnitsFactor = double.NaN; + private static Units _cachedUnits = Units.Meters; + + /// + /// 清除转换系数缓存(在单位变化时调用) + /// + public static void ClearCache() + { + _cachedUnitsToMetersFactor = double.NaN; + _cachedMetersToUnitsFactor = double.NaN; + } + + /// + /// 检查缓存是否有效(已设置且单位未变化) + /// + private static bool IsCacheValid() + { + // 从未设置过(NaN) + if (double.IsNaN(_cachedUnitsToMetersFactor) || double.IsNaN(_cachedMetersToUnitsFactor)) + return false; + + try + { + var currentUnits = Application.ActiveDocument?.Units ?? Units.Meters; + return currentUnits == _cachedUnits; + } + catch + { + return false; + } + } + + /// + /// 更新缓存 + /// + private static void UpdateCache() + { + try + { + var currentUnits = Application.ActiveDocument?.Units ?? Units.Meters; + + // 如果单位变化,更新缓存 + if (currentUnits != _cachedUnits) + { + _cachedUnits = currentUnits; + _cachedUnitsToMetersFactor = GetUnitsToMetersConversionFactor(currentUnits); + _cachedMetersToUnitsFactor = GetMetersToUnitsConversionFactor(currentUnits); + } + } + catch (Exception) + { + // 出错时保留上次的有效值(如果有),否则保持 NaN 以暴露错误 + // 不要设置默认值,避免掩盖问题 + } + } + /// /// 获取Navisworks文档单位转换为米的系数 /// /// 转换系数(文档单位转换为米) public static double GetUnitsToMetersConversionFactor() { - try - { - var units = Application.ActiveDocument.Units; - return GetUnitsToMetersConversionFactor(units); - } - catch (Exception) - { - // 默认为米 - return 1.0; - } + UpdateCache(); + return _cachedUnitsToMetersFactor; } /// @@ -69,16 +121,8 @@ namespace NavisworksTransport.Utils /// 转换系数(米转换为文档单位) public static double GetMetersToUnitsConversionFactor() { - try - { - var units = Application.ActiveDocument.Units; - return GetMetersToUnitsConversionFactor(units); - } - catch (Exception) - { - // 默认为米 - return 1.0; - } + UpdateCache(); + return _cachedMetersToUnitsFactor; } /// @@ -137,4 +181,4 @@ namespace NavisworksTransport.Utils return distanceInMeters * GetMetersToUnitsConversionFactor(); } } -} \ No newline at end of file +}