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
+}