优化单位转换的处理,使用缓存提高性能;控制米单位的使用

This commit is contained in:
tian 2026-02-04 12:59:02 +08:00
parent eeeaceacc4
commit 0d9eeed89b
6 changed files with 212 additions and 145 deletions

View File

@ -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度水平长方体截面为物体长度 × 物体高度
- **所有水平段**:起点和终点向路径方向延伸半个物体尺寸,确保完全包裹
## 参考

View File

@ -473,6 +473,9 @@ namespace NavisworksTransport
{
LogManager.Info($"[文档管理] 文档已切换到: {NavisApplication.ActiveDocument?.FileName ?? ""}");
// 清除单位转换缓存(文档切换后单位可能不同)
Utils.UnitsConverter.ClearCache();
GlobalExceptionHandler.SafeExecute(() =>
{
var activeDoc = NavisApplication.ActiveDocument;

View File

@ -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
/// 计算通行空间参数(高度、宽度、颜色、透明度、垂直偏移)
/// </summary>
/// <param name="visualization">路径可视化对象</param>
/// <param name="metersToModelUnits">米到模型单位的转换系数</param>
/// <param name="isVerticalSegment">是否是垂直段(仅用于吊装路径)</param>
/// <param name="isTurn90Horizontal">是否是与初始方向垂直的水平段吊装路径转折90度</param>
/// <returns>通行空间参数元组</returns>
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);
}
/// <summary>
@ -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
/// <param name="safetyMargin">安全间隙(米)</param>
/// <param name="passageNormalToPathVertical">垂直段的高度(物体长度 + 2×安全间隙模型单位</param>
/// <param name="passageNormalToPathHorizontal">水平段的高度(物体高度 + 2×安全间隙模型单位</param>
public void SetPassageSpaceParameters(double passageAcrossPath, double passageNormalToPath, double passageAlongPath, double passageNormalToPathVertical = 0, double passageNormalToPathHorizontal = 0)
/// <summary>
/// 设置通行空间参数 - 外部传入米制单位,内部存储为模型单位
/// </summary>
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;
}
/// <summary>
@ -3030,6 +2988,44 @@ namespace NavisworksTransport
}
}
/// <summary>
/// 延伸线段起点和终点以完全包裹物体VehicleSpace模式
/// </summary>
/// <param name="startPoint">起点(会被修改)</param>
/// <param name="endPoint">终点(会被修改)</param>
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
);
}
}
/// <summary>
/// 请求视图刷新(带防抖机制)
/// </summary>

View File

@ -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);
/// <summary>
@ -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;

View File

@ -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<int, (int obstacleInflated, int boundaryCount, int boundaryInflated)>();
@ -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)
{

View File

@ -6,25 +6,77 @@ namespace NavisworksTransport.Utils
/// <summary>
/// Navisworks单位转换工具类
/// 提供统一的单位转换功能,避免代码重复
///
/// 性能优化缓存转换系数避免重复访问API
/// </summary>
public static class UnitsConverter
{
// 缓存字段 - 使用 NaN 作为初始值,避免默认值掩盖错误
private static double _cachedUnitsToMetersFactor = double.NaN;
private static double _cachedMetersToUnitsFactor = double.NaN;
private static Units _cachedUnits = Units.Meters;
/// <summary>
/// 清除转换系数缓存(在单位变化时调用)
/// </summary>
public static void ClearCache()
{
_cachedUnitsToMetersFactor = double.NaN;
_cachedMetersToUnitsFactor = double.NaN;
}
/// <summary>
/// 检查缓存是否有效(已设置且单位未变化)
/// </summary>
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;
}
}
/// <summary>
/// 更新缓存
/// </summary>
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 以暴露错误
// 不要设置默认值,避免掩盖问题
}
}
/// <summary>
/// 获取Navisworks文档单位转换为米的系数
/// </summary>
/// <returns>转换系数(文档单位转换为米)</returns>
public static double GetUnitsToMetersConversionFactor()
{
try
{
var units = Application.ActiveDocument.Units;
return GetUnitsToMetersConversionFactor(units);
}
catch (Exception)
{
// 默认为米
return 1.0;
}
UpdateCache();
return _cachedUnitsToMetersFactor;
}
/// <summary>
@ -69,16 +121,8 @@ namespace NavisworksTransport.Utils
/// <returns>转换系数(米转换为文档单位)</returns>
public static double GetMetersToUnitsConversionFactor()
{
try
{
var units = Application.ActiveDocument.Units;
return GetMetersToUnitsConversionFactor(units);
}
catch (Exception)
{
// 默认为米
return 1.0;
}
UpdateCache();
return _cachedMetersToUnitsFactor;
}
/// <summary>
@ -137,4 +181,4 @@ namespace NavisworksTransport.Utils
return distanceInMeters * GetMetersToUnitsConversionFactor();
}
}
}
}