From 4e43fb89b37c994da0ebb8d7d8b13217d93c929b Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Thu, 11 Sep 2025 03:14:02 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8=E7=BD=91?= =?UTF-8?q?=E6=A0=BC=E5=B7=A6=E4=B8=8B=E8=A7=92=E5=9D=90=E6=A0=87=E7=B3=BB?= =?UTF-8?q?=EF=BC=8C=E4=B8=8EA*=E7=AE=97=E6=B3=95=E5=BA=93=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PathPlanning/AutoPathFinder.cs | 41 +++++++++---------- src/PathPlanning/GridMap.cs | 8 ++-- src/PathPlanning/GridMapGenerator.cs | 13 +++--- src/PathPlanning/OptimizedHeightCalculator.cs | 4 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/PathPlanning/AutoPathFinder.cs b/src/PathPlanning/AutoPathFinder.cs index fda1225..1c834ae 100644 --- a/src/PathPlanning/AutoPathFinder.cs +++ b/src/PathPlanning/AutoPathFinder.cs @@ -632,15 +632,15 @@ namespace NavisworksTransport.PathPlanning { // 添加第一条边的起点 var startNode = astarPath.Edges[0].Start; - var startGridX = (int)Math.Round(startNode.Position.X / cellSizeInMeters); - var startGridY = (int)Math.Round(startNode.Position.Y / cellSizeInMeters); + var startGridX = (int)Math.Floor(startNode.Position.X / cellSizeInMeters); + var startGridY = (int)Math.Floor(startNode.Position.Y / cellSizeInMeters); gridPath.Add(new GridPoint2D(startGridX, startGridY)); // 添加每条边的终点(避免重复) foreach (var edge in astarPath.Edges) { - var gridX = (int)Math.Round(edge.End.Position.X / cellSizeInMeters); - var gridY = (int)Math.Round(edge.End.Position.Y / cellSizeInMeters); + var gridX = (int)Math.Floor(edge.End.Position.X / cellSizeInMeters); + var gridY = (int)Math.Floor(edge.End.Position.Y / cellSizeInMeters); var gridPoint = new GridPoint2D(gridX, gridY); // 检查是否与上一个点重复(理论上A*不应该产生重复,但保险起见) @@ -668,18 +668,15 @@ namespace NavisworksTransport.PathPlanning // 获取单位转换因子(米转世界单位) double metersToWorldUnit = 1.0 / UnitsConverter.ConvertToMeters(1.0); - - // 计算半个网格的偏移量(用于从左下角调整到中心) - double halfCellOffset = gridMap.CellSize * 0.5; - // 将A*返回的网格左下角坐标调整到网格中心 + // A*返回的是网格左下角坐标,直接使用,不需要偏移 if (astarPath.Edges.Count > 0) { - // 添加第一条边的起点(调整到网格中心) + // 添加第一条边的起点(网格左下角) var startNode = astarPath.Edges[0].Start; var startWorldPos = new Point3D( - gridMap.Origin.X + startNode.Position.X * metersToWorldUnit + halfCellOffset, // 添加半格偏移到中心 - gridMap.Origin.Y + startNode.Position.Y * metersToWorldUnit + halfCellOffset, // 添加半格偏移到中心 + gridMap.Origin.X + startNode.Position.X * metersToWorldUnit, // 直接转换,不加偏移 + gridMap.Origin.Y + startNode.Position.Y * metersToWorldUnit, // 直接转换,不加偏移 0 // Z坐标后续通过高度插值处理 ); @@ -697,10 +694,10 @@ namespace NavisworksTransport.PathPlanning // 添加每条边的终点(避免重复) foreach (var edge in astarPath.Edges) { - // 将A*的米坐标转换为世界坐标,并调整到网格中心 + // 将A*的米坐标转换为世界坐标(网格左下角) var endWorldPos = new Point3D( - gridMap.Origin.X + edge.End.Position.X * metersToWorldUnit + halfCellOffset, // 添加半格偏移到中心 - gridMap.Origin.Y + edge.End.Position.Y * metersToWorldUnit + halfCellOffset, // 添加半格偏移到中心 + gridMap.Origin.X + edge.End.Position.X * metersToWorldUnit, // 直接转换,不加偏移 + gridMap.Origin.Y + edge.End.Position.Y * metersToWorldUnit, // 直接转换,不加偏移 0 // Z坐标后续处理 ); @@ -724,7 +721,7 @@ namespace NavisworksTransport.PathPlanning } } - LogManager.Info($"[路径转换] 转换完成,生成{worldPath.Count}个世界坐标点(调整到网格中心)"); + LogManager.Info($"[路径转换] 转换完成,生成{worldPath.Count}个世界坐标点(网格左下角)"); return worldPath; } @@ -1163,8 +1160,9 @@ namespace NavisworksTransport.PathPlanning try { // 将世界坐标转换为网格坐标 - int gridX = (int)Math.Round((point.X - gridMap.Bounds.Min.X) / gridMap.CellSize); - int gridY = (int)Math.Round((point.Y - gridMap.Bounds.Min.Y) / gridMap.CellSize); + var gridPos = gridMap.WorldToGrid(point); + int gridX = gridPos.X; + int gridY = gridPos.Y; LogManager.Info($"[高度检查] 检查点 ({point.X:F2}, {point.Y:F2}, {point.Z:F2}) -> 网格坐标 ({gridX}, {gridY})"); @@ -1276,8 +1274,9 @@ namespace NavisworksTransport.PathPlanning try { // 将世界坐标转换为网格坐标 - int gridX = (int)Math.Round((point.X - gridMap.Bounds.Min.X) / gridMap.CellSize); - int gridY = (int)Math.Round((point.Y - gridMap.Bounds.Min.Y) / gridMap.CellSize); + var gridPos = gridMap.WorldToGrid(point); + int gridX = gridPos.X; + int gridY = gridPos.Y; // 确保坐标在有效范围内 if (gridX < 0 || gridX >= gridMap.Width || gridY < 0 || gridY >= gridMap.Height) @@ -1363,8 +1362,8 @@ namespace NavisworksTransport.PathPlanning // 计算完成百分比 var lastNode = astarPath.Edges.Last().End; - var actualEndGridX = (int)Math.Round(lastNode.Position.X / cellSizeInMeters); - var actualEndGridY = (int)Math.Round(lastNode.Position.Y / cellSizeInMeters); + var actualEndGridX = (int)Math.Floor(lastNode.Position.X / cellSizeInMeters); + var actualEndGridY = (int)Math.Floor(lastNode.Position.Y / cellSizeInMeters); var actualEndGrid = new GridPoint2D(actualEndGridX, actualEndGridY); var actualEndCell = gridMap.GetCell(actualEndGrid); var actualEndWorld = gridMap.GridToWorld3D(actualEndGrid, actualEndCell?.WorldPosition.Z ?? 0); diff --git a/src/PathPlanning/GridMap.cs b/src/PathPlanning/GridMap.cs index e19dab2..305b73b 100644 --- a/src/PathPlanning/GridMap.cs +++ b/src/PathPlanning/GridMap.cs @@ -181,18 +181,18 @@ namespace NavisworksTransport.PathPlanning double gridX = (worldPosition.X - Origin.X) / CellSize; double gridY = (worldPosition.Y - Origin.Y) / CellSize; - return new GridPoint2D((int)Math.Round(gridX), (int)Math.Round(gridY)); + return new GridPoint2D((int)Math.Floor(gridX), (int)Math.Floor(gridY)); } /// /// 将网格坐标转换为世界2D坐标(纯坐标转换,不涉及Z坐标计算) /// /// 网格坐标 - /// 世界2D坐标点 + /// 世界2D坐标点(网格左下角) public Point3D GridToWorld2D(GridPoint2D gridPosition) { - double worldX = Origin.X + (gridPosition.X + 0.5) * CellSize; - double worldY = Origin.Y + (gridPosition.Y + 0.5) * CellSize; + double worldX = Origin.X + gridPosition.X * CellSize; + double worldY = Origin.Y + gridPosition.Y * CellSize; return new Point3D(worldX, worldY, 0); // Z设为0,调用者可以替换 } diff --git a/src/PathPlanning/GridMapGenerator.cs b/src/PathPlanning/GridMapGenerator.cs index d3b1f70..4afb17f 100644 --- a/src/PathPlanning/GridMapGenerator.cs +++ b/src/PathPlanning/GridMapGenerator.cs @@ -506,8 +506,9 @@ namespace NavisworksTransport.PathPlanning var intervals = kvp.Value; // 将世界坐标转换为网格坐标 - int gridX = (int)Math.Round((point.X - gridMap.Bounds.Min.X) / gridMap.CellSize); - int gridY = (int)Math.Round((point.Y - gridMap.Bounds.Min.Y) / gridMap.CellSize); + var gridPos = gridMap.WorldToGrid(new Point3D(point.X, point.Y, 0)); + int gridX = gridPos.X; + int gridY = gridPos.Y; // 确保坐标在有效范围内 if (gridX >= 0 && gridX < gridMap.Width && gridY >= 0 && gridY < gridMap.Height) @@ -533,8 +534,8 @@ namespace NavisworksTransport.PathPlanning { // 通道区域有足够净空高度,设置为可通行 // 🔥 关键修复:使用SetCell方法正确更新网格统计 - var gridPos = new GridPoint2D(gridX, gridY); - gridMap.SetCell(gridPos, true, 1.0, CategoryAttributeManager.LogisticsElementType.通道); + var cellPos = new GridPoint2D(gridX, gridY); + gridMap.SetCell(cellPos, true, 1.0, CategoryAttributeManager.LogisticsElementType.通道); // 设置世界坐标和高度信息 var updatedCell = gridMap.Cells[gridX, gridY]; @@ -546,8 +547,8 @@ namespace NavisworksTransport.PathPlanning else { // 通道区域但净空高度不足,标记为不可通行但保持通道类型 - var gridPos = new GridPoint2D(gridX, gridY); - gridMap.SetCell(gridPos, false, double.MaxValue, CategoryAttributeManager.LogisticsElementType.通道); + var cellPos = new GridPoint2D(gridX, gridY); + gridMap.SetCell(cellPos, false, double.MaxValue, CategoryAttributeManager.LogisticsElementType.通道); // 设置世界坐标和高度信息 var updatedCell = gridMap.Cells[gridX, gridY]; diff --git a/src/PathPlanning/OptimizedHeightCalculator.cs b/src/PathPlanning/OptimizedHeightCalculator.cs index 4a5d517..693338b 100644 --- a/src/PathPlanning/OptimizedHeightCalculator.cs +++ b/src/PathPlanning/OptimizedHeightCalculator.cs @@ -326,8 +326,8 @@ namespace NavisworksTransport.PathPlanning { // 对坐标进行网格对齐 double sampleIntervalModel = _sampleInterval * 39.37; - int gridX = (int)Math.Round(worldX / sampleIntervalModel); - int gridY = (int)Math.Round(worldY / sampleIntervalModel); + int gridX = (int)Math.Floor(worldX / sampleIntervalModel); + int gridY = (int)Math.Floor(worldY / sampleIntervalModel); return $"{gridX}_{gridY}"; }