采用包围体方法代替射线法进行垂直扫描,效果还可以。
This commit is contained in:
parent
eece385313
commit
f91d142bc7
@ -5,6 +5,8 @@
|
||||
### [2025/08/29]
|
||||
|
||||
1. [ ](BUG)路径导出,只有一条路径时,导出按钮不能点击;导出的内容有时不完整,只导出一个包含起点、一个路径点、终点的不存在的路径。
|
||||
2. [ ](性能优化)垂直扫描处理器性能问题:COM API几何提取效率极低,23个候选项需要5715ms,复杂几何体比简单几何体效率低4倍,需要优化批量处理和并行机制。
|
||||
3. [ ](稳定性)修复并行任务未观察异常导致程序崩溃:AggregateException错误表明Task异常处理不当,需要加强并行处理的异常处理和Task生命周期管理。
|
||||
|
||||
### [2025/08/28]
|
||||
|
||||
|
||||
@ -28,6 +28,12 @@ namespace NavisworksTransport.Core
|
||||
private volatile bool _isProcessing = false;
|
||||
private volatile bool _isDisposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// UI操作默认超时时间(毫秒)- 60秒
|
||||
/// 设置较长时间以应对程序性能异常导致的UI线程阻塞
|
||||
/// </summary>
|
||||
private const int DEFAULT_UI_TIMEOUT = 60000;
|
||||
|
||||
/// <summary>
|
||||
/// 获取UIStateManager的单例实例
|
||||
/// </summary>
|
||||
@ -150,7 +156,7 @@ namespace NavisworksTransport.Core
|
||||
/// <param name="operation">要执行的UI操作</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认5000ms</param>
|
||||
/// <returns>操作结果</returns>
|
||||
public async Task<T> ExecuteUIUpdateAsync<T>(Func<T> operation, int timeout = 5000)
|
||||
public async Task<T> ExecuteUIUpdateAsync<T>(Func<T> operation, int timeout = DEFAULT_UI_TIMEOUT)
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
@ -244,7 +250,8 @@ namespace NavisworksTransport.Core
|
||||
}
|
||||
finally
|
||||
{
|
||||
cancellationToken.Dispose();
|
||||
// 延迟释放,给异步操作清理时间,避免"CancellationTokenSource 已释放"异常
|
||||
_ = Task.Delay(100).ContinueWith(_ => cancellationToken.Dispose());
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,7 +260,7 @@ namespace NavisworksTransport.Core
|
||||
/// </summary>
|
||||
/// <param name="operation">要执行的UI操作</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认5000ms</param>
|
||||
public async Task ExecuteUIUpdateAsync(Action operation, int timeout = 5000)
|
||||
public async Task ExecuteUIUpdateAsync(Action operation, int timeout = DEFAULT_UI_TIMEOUT)
|
||||
{
|
||||
await ExecuteUIUpdateAsync<object>(() =>
|
||||
{
|
||||
@ -272,7 +279,7 @@ namespace NavisworksTransport.Core
|
||||
/// </summary>
|
||||
/// <param name="updates">要执行的UI更新操作数组</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认10000ms</param>
|
||||
public async Task ExecuteBatchUIUpdate(Action[] updates, int timeout = 10000)
|
||||
public async Task ExecuteBatchUIUpdate(Action[] updates, int timeout = DEFAULT_UI_TIMEOUT)
|
||||
{
|
||||
if (updates == null || updates.Length == 0)
|
||||
{
|
||||
@ -311,7 +318,7 @@ namespace NavisworksTransport.Core
|
||||
/// <param name="updates">要执行的UI更新操作</param>
|
||||
public async Task ExecuteBatchUIUpdate(params Action[] updates)
|
||||
{
|
||||
await ExecuteBatchUIUpdate(updates, 10000);
|
||||
await ExecuteBatchUIUpdate(updates, DEFAULT_UI_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -320,7 +327,7 @@ namespace NavisworksTransport.Core
|
||||
/// </summary>
|
||||
/// <param name="updates">要执行的UI更新操作数组</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认5000ms</param>
|
||||
public void ExecuteBatchUIUpdateSync(Action[] updates, int timeout = 5000)
|
||||
public void ExecuteBatchUIUpdateSync(Action[] updates, int timeout = DEFAULT_UI_TIMEOUT)
|
||||
{
|
||||
if (updates == null || updates.Length == 0)
|
||||
{
|
||||
@ -566,7 +573,7 @@ namespace NavisworksTransport.Core
|
||||
/// <param name="operation">要执行的UI操作</param>
|
||||
/// <param name="operationType">操作类型描述,用于日志记录</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认2000ms</param>
|
||||
public void ExecuteImmediateUIUpdate(Action operation, string operationType = "立即UI更新", int timeout = 2000)
|
||||
public void ExecuteImmediateUIUpdate(Action operation, string operationType = "立即UI更新", int timeout = DEFAULT_UI_TIMEOUT)
|
||||
{
|
||||
if (_isDisposed || operation == null)
|
||||
{
|
||||
|
||||
@ -41,7 +41,21 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
_categoryManager = new CategoryAttributeManager();
|
||||
_channelBuilder = new ChannelBasedGridBuilder();
|
||||
_verticalScanner = new VerticalScanProcessor();
|
||||
|
||||
double spatialHashSize = CalculateSpatialHashSize();
|
||||
_verticalScanner = new VerticalScanProcessor(spatialHashSize);
|
||||
|
||||
LogManager.Info($"[网格生成器] 初始化完成,空间哈希大小: {spatialHashSize:F1}模型单位");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据当前模型单位计算合适的空间哈希桶大小
|
||||
/// </summary>
|
||||
/// <returns>适合当前模型单位的空间哈希桶大小</returns>
|
||||
private double CalculateSpatialHashSize()
|
||||
{
|
||||
// 目标:10米在当前模型单位下的等价值
|
||||
return 10.0 * GetMetersToModelUnitsConversionFactor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -57,7 +71,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// <param name="mode">网格生成模式,默认为边界框模式以保持向后兼容</param>
|
||||
/// <param name="vehicleHeight">车辆高度(用于垂直通行检查)</param>
|
||||
/// <returns>生成的网格地图</returns>
|
||||
public GridMap GenerateFromBIM(Document document, BoundingBox3D bounds, double cellSize = 2.0, double vehicleRadius = 1.0, double safetyMargin = 0.5, Point3D planningStartPoint = default(Point3D), Point3D planningEndPoint = default(Point3D), GridGenerationMode mode = GridGenerationMode.BoundingBox, double vehicleHeight = 2.0)
|
||||
public GridMap GenerateFromBIM(Document document, BoundingBox3D bounds, double cellSize, double vehicleRadius, double safetyMargin, Point3D planningStartPoint, Point3D planningEndPoint, GridGenerationMode mode, double vehicleHeight)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -205,14 +219,19 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
LogManager.Info("[通道2.5D模式] 开始生成网格地图");
|
||||
|
||||
// 重要:将米制网格大小转换为模型单位
|
||||
double metersToModelUnitsConversionFactor = GetMetersToModelUnitsConversionFactor();
|
||||
double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor;
|
||||
LogManager.Info($"[通道2.5D模式] 网格大小单位转换: {cellSize}米 → {cellSizeInModelUnits:F2}模型单位 (转换系数: {metersToModelUnitsConversionFactor:F2})");
|
||||
|
||||
// 1. 使用通道构建器构建基础通道覆盖网格
|
||||
LogManager.Info("[通道2.5D模式] 步骤1: 构建通道覆盖网格");
|
||||
var channelCoverage = _channelBuilder.BuildChannelCoverage(cellSize, document);
|
||||
var channelCoverage = _channelBuilder.BuildChannelCoverage(cellSizeInModelUnits, document);
|
||||
|
||||
if (channelCoverage?.GridMap == null)
|
||||
{
|
||||
LogManager.Warning("[通道2.5D模式] 通道构建失败,回退到边界框模式");
|
||||
return GenerateBoundingBoxMode(document, bounds, cellSize, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint);
|
||||
return GenerateBoundingBoxMode(document, bounds, cellSizeInModelUnits, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint);
|
||||
}
|
||||
|
||||
LogManager.Info($"[通道2.5D模式] 通道覆盖构建完成: {channelCoverage.GetStatistics()}");
|
||||
@ -278,7 +297,10 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
LogManager.Error($"[通道2.5D模式] 生成失败: {ex.Message}");
|
||||
LogManager.Warning("[通道2.5D模式] 回退到边界框模式");
|
||||
return GenerateBoundingBoxMode(document, bounds, cellSize, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint);
|
||||
// 注意:catch块中也需要使用转换后的单位,但这里需要重新计算因为cellSizeInModelUnits变量作用域问题
|
||||
double metersToModelUnitsConversionFactor = GetMetersToModelUnitsConversionFactor();
|
||||
double cellSizeInModelUnits = cellSize * metersToModelUnitsConversionFactor;
|
||||
return GenerateBoundingBoxMode(document, bounds, cellSizeInModelUnits, vehicleRadius, safetyMargin, planningStartPoint, planningEndPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -168,20 +168,8 @@ namespace NavisworksTransport.PathPlanning
|
||||
LogManager.Info($" - 超出扫描边界的元素: {outOfBoundsCounter}");
|
||||
LogManager.Info($" - 符合条件并添加到空间哈希的元素: {itemsWithBounds.Count}");
|
||||
|
||||
// 【新增】详细记录前10个元素的信息
|
||||
LogManager.Info($"【空间哈希调试】 前10个待索引元素详情:");
|
||||
var itemsList = itemsWithBounds.Take(10).ToList();
|
||||
for (int i = 0; i < itemsList.Count; i++)
|
||||
{
|
||||
var (item, bbox) = itemsList[i];
|
||||
var hashKeys = GetSpatialHashKeys(bbox);
|
||||
LogManager.Info($"【空间哈希调试】 元素 {i}: 名称=\"{item.DisplayName ?? "无名称"}\"");
|
||||
LogManager.Info($"【空间哈希调试】 InstanceGuid: {item.InstanceGuid}");
|
||||
LogManager.Info($"【空间哈希调试】 GetHashCode: {item.GetHashCode():X}");
|
||||
LogManager.Info($"【空间哈希调试】 边界框: Min({bbox.Min.X:F2}, {bbox.Min.Y:F2}, {bbox.Min.Z:F2})");
|
||||
LogManager.Info($"【空间哈希调试】 边界框: Max({bbox.Max.X:F2}, {bbox.Max.Y:F2}, {bbox.Max.Z:F2})");
|
||||
LogManager.Info($"【空间哈希调试】 哈希键数量: {hashKeys.Count()}, 示例键: [{string.Join(", ", hashKeys.Take(3))}]");
|
||||
}
|
||||
// 记录待索引元素数量
|
||||
LogManager.Info($"【垂直扫描处理器】 待索引元素数量: {itemsWithBounds.Count()}");
|
||||
|
||||
// 构建空间哈希
|
||||
var totalHashEntries = 0;
|
||||
@ -211,44 +199,11 @@ namespace NavisworksTransport.PathPlanning
|
||||
}
|
||||
}
|
||||
|
||||
// 【新增】哈希桶分布统计
|
||||
// 统计哈希桶信息(简化版)
|
||||
var bucketSizes = _spatialHashMap.Values.Select(list => list.Count).ToList();
|
||||
LogManager.Info($"【空间哈希调试】 哈希桶分布统计:");
|
||||
LogManager.Info($"【空间哈希调试】 - 最小桶大小: {bucketSizes.DefaultIfEmpty(0).Min()}");
|
||||
LogManager.Info($"【空间哈希调试】 - 最大桶大小: {bucketSizes.DefaultIfEmpty(0).Max()}");
|
||||
LogManager.Info($"【空间哈希调试】 - 平均桶大小: {bucketSizes.DefaultIfEmpty(0).Average():F1}");
|
||||
LogManager.Info($"【垂直扫描处理器】 空间哈希构建完成 - 哈希桶数量: {_spatialHashMap.Count}, 平均桶大小: {bucketSizes.DefaultIfEmpty(0).Average():F1}");
|
||||
|
||||
// 【新增】显示前5个最大的哈希桶内容
|
||||
var topBuckets = _spatialHashMap.OrderByDescending(kvp => kvp.Value.Count).Take(5).ToList();
|
||||
LogManager.Info($"【空间哈希调试】 前5个最大哈希桶:");
|
||||
for (int i = 0; i < topBuckets.Count; i++)
|
||||
{
|
||||
var bucket = topBuckets[i];
|
||||
LogManager.Info($"【空间哈希调试】 桶 {i}: 键=\"{bucket.Key}\", 元素数量={bucket.Value.Count}");
|
||||
var sampleElements = bucket.Value.Take(3).ToList();
|
||||
foreach (var element in sampleElements)
|
||||
{
|
||||
LogManager.Info($"【空间哈希调试】 包含元素: \"{element.DisplayName ?? "无名称"}\" (GUID: {element.InstanceGuid}, Hash: {element.GetHashCode():X})");
|
||||
}
|
||||
}
|
||||
|
||||
// 【新增】验证几个测试点的哈希键计算
|
||||
LogManager.Info($"【空间哈希调试】 测试点哈希键验证:");
|
||||
var testPoints = new[]
|
||||
{
|
||||
new Point3D(-228.17, -57.82, 35.40), // 对应日志中的点11370
|
||||
new Point3D(-212.17, 69.18, 35.40), // 对应日志中的点7580
|
||||
new Point3D(-79.17, -9.82, 35.40) // 对应日志中找到34个候选项的点
|
||||
};
|
||||
|
||||
foreach (var point in testPoints)
|
||||
{
|
||||
var testKeys = GetSpatialHashKeysForPoint(point);
|
||||
var candidates = testKeys.SelectMany(key => _spatialHashMap.ContainsKey(key) ? _spatialHashMap[key] : new List<ModelItem>()).Distinct().ToList();
|
||||
var candidatesCount = candidates.Count;
|
||||
LogManager.Info($"【空间哈希调试】 测试点({point.X:F2}, {point.Y:F2}, {point.Z:F2}): 哈希键数量={testKeys.Count()}, 候选项={candidatesCount}");
|
||||
LogManager.Info($"【空间哈希调试】 哈希键: [{string.Join(", ", testKeys)}]");
|
||||
}
|
||||
// 空间哈希索引构建完成
|
||||
|
||||
var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
|
||||
LogManager.Info($"【垂直扫描处理器】 空间哈希索引构建完成,耗时: {elapsed:F1}ms");
|
||||
@ -274,27 +229,7 @@ namespace NavisworksTransport.PathPlanning
|
||||
var results = new ConcurrentDictionary<Point3D, List<HeightInterval>>();
|
||||
var pointsList = gridPoints?.ToList() ?? new List<Point3D>();
|
||||
|
||||
// 性能测试模式:随机抽样10个有代表性的点进行详细分析
|
||||
if (pointsList.Count > 10)
|
||||
{
|
||||
LogManager.Info($"[性能测试] 原计划处理{pointsList.Count}个点,测试模式随机抽样10个点");
|
||||
|
||||
var random = new System.Random(42); // 固定种子确保可重复
|
||||
var sampledPoints = new List<Point3D>();
|
||||
|
||||
// 分区抽样:从不同区域抽取点
|
||||
int sectionSize = pointsList.Count / 10;
|
||||
for (int i = 0; i < 10 && i * sectionSize < pointsList.Count; i++)
|
||||
{
|
||||
int startIndex = i * sectionSize;
|
||||
int endIndex = Math.Min((i + 1) * sectionSize, pointsList.Count);
|
||||
int randomIndex = random.Next(startIndex, endIndex);
|
||||
sampledPoints.Add(pointsList[randomIndex]);
|
||||
}
|
||||
|
||||
pointsList = sampledPoints;
|
||||
LogManager.Info($"[性能测试] 抽样完成,选择了10个分布均匀的测试点");
|
||||
}
|
||||
LogManager.Info($"[垂直扫描处理器] 准备处理{pointsList.Count}个点");
|
||||
|
||||
try
|
||||
{
|
||||
@ -366,82 +301,21 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// <returns>可通行的高度区间列表</returns>
|
||||
public List<HeightInterval> ScanVerticalLine(Point3D basePoint, double scanHeight, double vehicleHeight)
|
||||
{
|
||||
// 判断是否为抽样调试点(从15160个点中平均选择5个)
|
||||
var debugSamplingPoints = new int[] { 0, 3790, 7580, 11370, 15159 };
|
||||
var currentPointIndex = GetCurrentScanIndex(basePoint); // 需要实现此方法获取当前点索引
|
||||
bool isDebugPoint = debugSamplingPoints.Contains(currentPointIndex);
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】开始扫描点 {currentPointIndex}: 坐标({basePoint.X:F2}, {basePoint.Y:F2}, {basePoint.Z:F2}), 扫描高度: {scanHeight}m");
|
||||
}
|
||||
|
||||
// 第一级筛选:邻域筛选 - 获取空间哈希邻域内的候选项
|
||||
var candidateItems = GetCandidateItemsFromSpatialHash(basePoint);
|
||||
|
||||
// 性能测试模式:为所有点输出详细候选项信息
|
||||
bool isTestMode = candidateItems.Count <= 50; // 假设测试模式下候选项不会太多
|
||||
if (isDebugPoint || isTestMode)
|
||||
{
|
||||
LogManager.Info($"=== 详细分析扫描点 {currentPointIndex} ===");
|
||||
LogManager.Info($"空间哈希候选项: {candidateItems.Count} 个");
|
||||
|
||||
for (int i = 0; i < candidateItems.Count; i++)
|
||||
{
|
||||
var item = candidateItems[i];
|
||||
var bbox = item.BoundingBox();
|
||||
LogManager.Info($"候选项 {i}: 名称='{item.DisplayName}'");
|
||||
LogManager.Info($" - 边界框: {bbox?.Min} -> {bbox?.Max}");
|
||||
LogManager.Info($" - 有几何体: {item.HasGeometry}");
|
||||
LogManager.Info($" - 子项数量: {item.Children?.Count() ?? 0}");
|
||||
LogManager.Info($" - 类名: {item.ClassName}");
|
||||
}
|
||||
}
|
||||
|
||||
// 第二级筛选:高度筛选 - 只保留在扫描高度范围内的项目
|
||||
var heightFilteredItems = HeightFiltering(candidateItems, basePoint.Z, basePoint.Z + scanHeight);
|
||||
|
||||
if (isDebugPoint || isTestMode)
|
||||
{
|
||||
LogManager.Info($"高度筛选后: {heightFilteredItems.Count} 个候选项 (筛选范围: [{basePoint.Z:F2}, {basePoint.Z + scanHeight:F2}])");
|
||||
if (candidateItems.Count != heightFilteredItems.Count)
|
||||
{
|
||||
LogManager.Info($"高度筛选过滤掉了 {candidateItems.Count - heightFilteredItems.Count} 个候选项");
|
||||
}
|
||||
}
|
||||
|
||||
// 第三级筛选:空间哈希 - 精确的几何相交测试
|
||||
var intersectionResults = PerformIntersectionTests(heightFilteredItems, basePoint, scanHeight, isDebugPoint, currentPointIndex);
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {currentPointIndex} 相交检测结果: {intersectionResults.Count} 个相交项");
|
||||
}
|
||||
var intersectionResults = PerformIntersectionTests(heightFilteredItems, basePoint, scanHeight);
|
||||
|
||||
// 计算可通行区间
|
||||
var passableIntervals = CalculatePassableIntervals(intersectionResults, basePoint.Z, scanHeight, vehicleHeight, isDebugPoint, currentPointIndex);
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {currentPointIndex} 最终高度区间: {passableIntervals.Count} 个区间");
|
||||
foreach (var interval in passableIntervals)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 区间: [{interval.MinZ:F2}, {interval.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
var passableIntervals = CalculatePassableIntervals(intersectionResults, basePoint.Z, scanHeight, vehicleHeight);
|
||||
|
||||
return passableIntervals;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前扫描点的索引(用于调试抽样)
|
||||
/// </summary>
|
||||
private int GetCurrentScanIndex(Point3D point)
|
||||
{
|
||||
// 简化实现:基于坐标计算一个伪索引
|
||||
// 实际应用中可能需要更精确的索引计算
|
||||
return Math.Abs(point.GetHashCode()) % 15160;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -546,15 +420,10 @@ namespace NavisworksTransport.PathPlanning
|
||||
/// <param name="basePoint">基础点</param>
|
||||
/// <param name="scanHeight">扫描高度</param>
|
||||
/// <returns>相交测试结果</returns>
|
||||
private List<IntersectionResult> PerformIntersectionTests(List<ModelItem> items, Point3D basePoint, double scanHeight, bool isDebugPoint = false, int pointIndex = -1)
|
||||
private List<IntersectionResult> PerformIntersectionTests(List<ModelItem> items, Point3D basePoint, double scanHeight)
|
||||
{
|
||||
var results = new ConcurrentBag<IntersectionResult>();
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 开始相交测试,候选项目数量: {items.Count}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 并行执行相交测试,添加更强的异常处理
|
||||
@ -567,14 +436,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
var intersectionData = TestVerticalLineIntersection(item, basePoint, scanHeight);
|
||||
if (intersectionData != null)
|
||||
{
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 发现相交项目: {item.DisplayName}");
|
||||
LogManager.Info($"【调试抽样】 - Z高度范围: [{intersectionData.MinZ:F2}, {intersectionData.MaxZ:F2}]");
|
||||
LogManager.Info($"【调试抽样】 - 相交点: ({intersectionData.IntersectionPoint.X:F2}, {intersectionData.IntersectionPoint.Y:F2}, {intersectionData.IntersectionPoint.Z:F2})");
|
||||
LogManager.Info($"【调试抽样】 - 高度跨度: {intersectionData.MaxZ - intersectionData.MinZ:F2}m");
|
||||
}
|
||||
|
||||
// 简化逻辑:所有与垂直射线相交的非通道元素都视为障碍物
|
||||
// 因为在空间哈希构建时已经排除了通道元素
|
||||
results.Add(new IntersectionResult
|
||||
@ -585,10 +446,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
IsPassable = false // 不可通行
|
||||
});
|
||||
}
|
||||
else if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 项目无相交: {item.DisplayName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -611,13 +468,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
var intersectionData = TestVerticalLineIntersection(item, basePoint, scanHeight);
|
||||
if (intersectionData != null)
|
||||
{
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 串行发现相交项目: {item.DisplayName}");
|
||||
LogManager.Info($"【调试抽样】 - Z高度范围: [{intersectionData.MinZ:F2}, {intersectionData.MaxZ:F2}]");
|
||||
LogManager.Info($"【调试抽样】 - 相交点: ({intersectionData.IntersectionPoint.X:F2}, {intersectionData.IntersectionPoint.Y:F2}, {intersectionData.IntersectionPoint.Z:F2})");
|
||||
}
|
||||
|
||||
// 简化逻辑:所有与垂直射线相交的非通道元素都视为障碍物
|
||||
results.Add(new IntersectionResult
|
||||
{
|
||||
@ -636,11 +486,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
}
|
||||
}
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 相交测试完成,找到 {results.Count} 个相交项目");
|
||||
}
|
||||
|
||||
return results.ToList();
|
||||
}
|
||||
|
||||
@ -656,16 +501,8 @@ namespace NavisworksTransport.PathPlanning
|
||||
List<IntersectionResult> intersectionResults,
|
||||
double baseZ,
|
||||
double scanHeight,
|
||||
double vehicleHeight,
|
||||
bool isDebugPoint = false,
|
||||
int pointIndex = -1)
|
||||
double vehicleHeight)
|
||||
{
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 开始计算可通行区间");
|
||||
LogManager.Info($"【调试抽样】 - 基础Z: {baseZ:F2}, 扫描高度: {scanHeight:F2}, 车辆高度: {vehicleHeight:F2}");
|
||||
LogManager.Info($"【调试抽样】 - 相交结果数量: {intersectionResults.Count}");
|
||||
}
|
||||
|
||||
// 收集所有障碍物的高度范围
|
||||
var obstacles = new List<HeightInterval>();
|
||||
@ -680,11 +517,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
result.IntersectionData.MaxZ
|
||||
);
|
||||
obstacles.Add(obstacleInterval);
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 障碍物: {result.ModelItem.DisplayName}, 高度范围: [{obstacleInterval.MinZ:F2}, {obstacleInterval.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
else if (result.IsPassable && result.IntersectionData != null)
|
||||
{
|
||||
@ -696,26 +528,12 @@ namespace NavisworksTransport.PathPlanning
|
||||
result.IntersectionData.MaxZ
|
||||
);
|
||||
floors.Add(floorInterval);
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 地面: {result.ModelItem.DisplayName}, 高度范围: [{floorInterval.MinZ:F2}, {floorInterval.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 合并重叠的障碍物区间
|
||||
var mergedObstacles = MergeOverlappingIntervals(obstacles);
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 合并后障碍物数量: {mergedObstacles.Count}");
|
||||
foreach (var obs in mergedObstacles)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 合并障碍物: [{obs.MinZ:F2}, {obs.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
|
||||
// 计算可通行区间
|
||||
var passableIntervals = new List<HeightInterval>();
|
||||
@ -725,10 +543,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
if (!floors.Any())
|
||||
{
|
||||
floors.Add(new HeightInterval(baseZ - 0.1, baseZ + 0.1));
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 未找到地面,使用默认地面: [{baseZ - 0.1:F2}, {baseZ + 0.1:F2}]");
|
||||
}
|
||||
}
|
||||
|
||||
// 对每个潜在的地面,计算其上方的可通行空间
|
||||
@ -737,39 +551,21 @@ namespace NavisworksTransport.PathPlanning
|
||||
double floorTop = floor.MaxZ;
|
||||
double availableTop = baseZ + scanHeight;
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 处理地面: 地面顶部={floorTop:F2}, 可用顶部={availableTop:F2}");
|
||||
}
|
||||
|
||||
// 检查地面上方是否有足够的净空高度
|
||||
var conflictingObstacles = mergedObstacles
|
||||
.Where(obs => obs.MinZ < availableTop && obs.MaxZ > floorTop)
|
||||
.OrderBy(obs => obs.MinZ)
|
||||
.ToList();
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 冲突障碍物数量: {conflictingObstacles.Count}");
|
||||
}
|
||||
|
||||
if (!conflictingObstacles.Any())
|
||||
{
|
||||
// 没有障碍物,整个高度范围都可通行
|
||||
double clearHeight = availableTop - floorTop;
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 无障碍物,净空高度: {clearHeight:F2}m, 最小需要: {MIN_PASSABLE_HEIGHT:F2}m");
|
||||
}
|
||||
|
||||
if (clearHeight >= MIN_PASSABLE_HEIGHT)
|
||||
{
|
||||
var interval = new HeightInterval(floorTop, availableTop);
|
||||
passableIntervals.Add(interval);
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 添加可通行区间: [{interval.MinZ:F2}, {interval.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -777,11 +573,6 @@ namespace NavisworksTransport.PathPlanning
|
||||
// 有障碍物,计算障碍物之间的可通行空间
|
||||
double currentBottom = floorTop;
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 有障碍物,开始计算空隙,起始底部: {currentBottom:F2}");
|
||||
}
|
||||
|
||||
foreach (var obstacle in conflictingObstacles)
|
||||
{
|
||||
double obstacleBottom = Math.Max(obstacle.MinZ, currentBottom);
|
||||
@ -789,56 +580,31 @@ namespace NavisworksTransport.PathPlanning
|
||||
if (obstacleBottom > currentBottom)
|
||||
{
|
||||
double clearHeight = obstacleBottom - currentBottom;
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 障碍物前空隙: 底部={currentBottom:F2}, 顶部={obstacleBottom:F2}, 净空={clearHeight:F2}");
|
||||
}
|
||||
|
||||
if (clearHeight >= vehicleHeight)
|
||||
{
|
||||
var interval = new HeightInterval(currentBottom, obstacleBottom);
|
||||
passableIntervals.Add(interval);
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 添加障碍物前区间: [{interval.MinZ:F2}, {interval.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentBottom = Math.Max(currentBottom, obstacle.MaxZ);
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 障碍物后,更新底部为: {currentBottom:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
// 检查最后一个障碍物之后的空间
|
||||
if (currentBottom < availableTop)
|
||||
{
|
||||
double clearHeight = availableTop - currentBottom;
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 最后障碍物后空隙: 底部={currentBottom:F2}, 顶部={availableTop:F2}, 净空={clearHeight:F2}");
|
||||
}
|
||||
|
||||
if (clearHeight >= vehicleHeight)
|
||||
{
|
||||
var interval = new HeightInterval(currentBottom, availableTop);
|
||||
passableIntervals.Add(interval);
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】 - 添加最后区间: [{interval.MinZ:F2}, {interval.MaxZ:F2}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDebugPoint)
|
||||
{
|
||||
LogManager.Info($"【调试抽样】点 {pointIndex} 计算完成,最终可通行区间数量: {passableIntervals.Count}");
|
||||
}
|
||||
|
||||
return passableIntervals;
|
||||
}
|
||||
|
||||
@ -918,6 +684,38 @@ namespace NavisworksTransport.PathPlanning
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用包围盒进行快速垂直相交检测
|
||||
var bbox = item.BoundingBox();
|
||||
if (bbox == null)
|
||||
return null;
|
||||
|
||||
// 检查XY平面投影是否包含扫描点
|
||||
bool intersectsXY = (basePoint.X >= bbox.Min.X && basePoint.X <= bbox.Max.X &&
|
||||
basePoint.Y >= bbox.Min.Y && basePoint.Y <= bbox.Max.Y);
|
||||
|
||||
if (intersectsXY)
|
||||
{
|
||||
// 计算Z轴相交区间
|
||||
double scanMinZ = basePoint.Z;
|
||||
double scanMaxZ = basePoint.Z + scanHeight;
|
||||
|
||||
double intersectionMinZ = Math.Max(bbox.Min.Z, scanMinZ);
|
||||
double intersectionMaxZ = Math.Min(bbox.Max.Z, scanMaxZ);
|
||||
|
||||
if (intersectionMaxZ > intersectionMinZ)
|
||||
{
|
||||
return new IntersectionData
|
||||
{
|
||||
MinZ = intersectionMinZ,
|
||||
MaxZ = intersectionMaxZ,
|
||||
IntersectionPoint = new Point3D(basePoint.X, basePoint.Y, (intersectionMinZ + intersectionMaxZ) / 2)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
/* 原有射线法实现 - 保留作为参考
|
||||
if (!item.HasGeometry)
|
||||
return null;
|
||||
|
||||
@ -957,10 +755,11 @@ namespace NavisworksTransport.PathPlanning
|
||||
}
|
||||
|
||||
return null;
|
||||
*/
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.Debug($"【垂直扫描处理器】 射线相交测试异常: {item.DisplayName}, {ex.Message}");
|
||||
LogManager.Debug($"【垂直扫描处理器】 包围盒相交测试异常: {item.DisplayName}, {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user