315 lines
13 KiB
C#
315 lines
13 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using Autodesk.Navisworks.Api;
|
||
using NavisworksTransport.Utils;
|
||
using NavisworksTransport.Utils.CoordinateSystem;
|
||
|
||
namespace NavisworksTransport.PathPlanning
|
||
{
|
||
/// <summary>
|
||
/// 空中路径生成器
|
||
/// 用于生成吊装路径(起点吊起 → 平移 → 终点吊下)
|
||
/// 支持智能方向判断和基于地面投影点的动态路径生成
|
||
/// </summary>
|
||
public class AerialPathGenerator
|
||
{
|
||
private readonly HostCoordinateAdapter _adapter;
|
||
|
||
/// <summary>
|
||
/// 方向判断容差(米)
|
||
/// 当两个方向的距离差小于此值时,默认选择纵向
|
||
/// </summary>
|
||
private const double DIRECTION_TOLERANCE = 0.001;
|
||
|
||
public AerialPathGenerator()
|
||
: this(HostCoordinateAdapter.CreateFromManager())
|
||
{
|
||
}
|
||
|
||
public AerialPathGenerator(HostCoordinateAdapter adapter)
|
||
{
|
||
_adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成吊装路径(起点吊起 → 平移 → 终点吊下)
|
||
/// 保留原有方法以保持向后兼容
|
||
/// </summary>
|
||
/// <param name="startPoint">起点(吊起位置)</param>
|
||
/// <param name="endPoint">终点(下降位置)</param>
|
||
/// <param name="liftHeightModelUnits">提升高度(模型单位)</param>
|
||
/// <returns>4个路径点:起吊点、提升点、平移终点、下降点</returns>
|
||
public List<PathPoint> GenerateThreeStepHoistingPath(
|
||
Point3D startPoint,
|
||
Point3D endPoint,
|
||
double liftHeightModelUnits)
|
||
{
|
||
if (startPoint == null)
|
||
throw new ArgumentNullException(nameof(startPoint));
|
||
if (endPoint == null)
|
||
throw new ArgumentNullException(nameof(endPoint));
|
||
if (liftHeightModelUnits <= 0)
|
||
throw new ArgumentException("提升高度必须大于0", nameof(liftHeightModelUnits));
|
||
|
||
var pathPoints = new List<PathPoint>();
|
||
|
||
// 点1:起吊点(物体初始位置)
|
||
var startPointPath = new PathPoint(
|
||
startPoint,
|
||
"起吊点",
|
||
PathPointType.StartPoint);
|
||
startPointPath.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(startPointPath);
|
||
|
||
// 点2:提升点(起点正上方,达到提升高度)
|
||
var liftPoint = HoistingCoordinateHelper.OffsetAlongUp(startPoint, liftHeightModelUnits, _adapter);
|
||
var liftPointPath = new PathPoint(
|
||
liftPoint,
|
||
"提升点",
|
||
PathPointType.WayPoint);
|
||
liftPointPath.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(liftPointPath);
|
||
|
||
// 点3:平移终点(终点正上方,保持提升高度)
|
||
var moveEndPoint = HoistingCoordinateHelper.ProjectToAerialElevation(endPoint, liftPoint, _adapter);
|
||
var moveEndPointPath = new PathPoint(
|
||
moveEndPoint,
|
||
"平移终点",
|
||
PathPointType.WayPoint);
|
||
moveEndPointPath.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(moveEndPointPath);
|
||
|
||
// 点4:下降点(终点位置,物体最终位置)
|
||
var endPointPath = new PathPoint(
|
||
endPoint,
|
||
"下降点",
|
||
PathPointType.EndPoint);
|
||
endPointPath.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(endPointPath);
|
||
|
||
return pathPoints;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断移动方向并生成路径点
|
||
/// 根据用户点击的地面投影位置和上一个路径点,自动判断纵向或横向移动
|
||
/// </summary>
|
||
/// <param name="previousPoint">上一个路径点</param>
|
||
/// <param name="clickedGroundPoint">用户点击的地面投影位置</param>
|
||
/// <param name="targetHeightModelUnits">目标高度(模型单位)</param>
|
||
/// <param name="pointIndex">路径点序号</param>
|
||
/// <returns>生成的路径点</returns>
|
||
public PathPoint GenerateSmartHoistingPoint(
|
||
Point3D previousPoint,
|
||
Point3D clickedGroundPoint,
|
||
double targetHeightModelUnits,
|
||
int pointIndex)
|
||
{
|
||
if (previousPoint == null)
|
||
throw new ArgumentNullException(nameof(previousPoint));
|
||
if (clickedGroundPoint == null)
|
||
throw new ArgumentNullException(nameof(clickedGroundPoint));
|
||
// 注意:targetHeightModelUnits 是绝对高度,可以是负数(如果起点在地下)
|
||
|
||
// 计算两个方向的距离
|
||
double deltaX = Math.Abs(clickedGroundPoint.X - previousPoint.X);
|
||
double deltaY = Math.Abs(clickedGroundPoint.Y - previousPoint.Y);
|
||
|
||
// 使用目标高度作为Z坐标,XY使用地面点击位置
|
||
Point3D newPoint = HoistingCoordinateHelper.SetElevation(
|
||
clickedGroundPoint,
|
||
targetHeightModelUnits,
|
||
_adapter);
|
||
|
||
// 判断移动方向(仅用于记录,不影响位置)
|
||
HoistingPointDirection direction;
|
||
if (Math.Abs(deltaX - deltaY) < DIRECTION_TOLERANCE)
|
||
{
|
||
// 距离相等,默认选择纵向
|
||
direction = HoistingPointDirection.Longitudinal;
|
||
}
|
||
else if (deltaX > deltaY)
|
||
{
|
||
// 更偏向纵向移动(X轴)
|
||
direction = HoistingPointDirection.Longitudinal;
|
||
}
|
||
else
|
||
{
|
||
// 更偏向横向移动(Y轴)
|
||
direction = HoistingPointDirection.Lateral;
|
||
}
|
||
|
||
string pointName = $"路径点{pointIndex}";
|
||
var pathPoint = new PathPoint(newPoint, pointName, PathPointType.WayPoint);
|
||
pathPoint.Direction = direction;
|
||
|
||
return pathPoint;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 基于智能判断生成吊装路径
|
||
/// 支持用户点击地面投影位置,系统自动判断方向并生成空中路径点
|
||
/// </summary>
|
||
/// <param name="startPoint">地面起点(用户点击)</param>
|
||
/// <param name="endPoint">地面终点(用户点击)</param>
|
||
/// <param name="liftHeightMeters">吊装高度(米)</param>
|
||
/// <param name="groundIntermediatePoints">用户点击的地面中间点列表</param>
|
||
/// <returns>生成的路径点列表</returns>
|
||
public List<PathPoint> GenerateSmartHoistingPath(
|
||
Point3D startPoint,
|
||
Point3D endPoint,
|
||
double liftHeightMeters,
|
||
List<Point3D> groundIntermediatePoints)
|
||
{
|
||
if (startPoint == null)
|
||
throw new ArgumentNullException(nameof(startPoint));
|
||
if (endPoint == null)
|
||
throw new ArgumentNullException(nameof(endPoint));
|
||
if (liftHeightMeters <= 0)
|
||
throw new ArgumentException("提升高度必须大于0", nameof(liftHeightMeters));
|
||
if (groundIntermediatePoints == null)
|
||
throw new ArgumentNullException(nameof(groundIntermediatePoints));
|
||
|
||
var pathPoints = new List<PathPoint>();
|
||
double liftHeightModelUnits = UnitsConverter.ConvertFromMeters(liftHeightMeters);
|
||
double liftElevation = HoistingCoordinateHelper.GetElevation(startPoint, _adapter) + liftHeightModelUnits;
|
||
|
||
// 点1:起吊点(地面起点)
|
||
var startPathPoint = new PathPoint(
|
||
startPoint,
|
||
"起吊点",
|
||
PathPointType.StartPoint);
|
||
startPathPoint.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(startPathPoint);
|
||
|
||
// 点2:提升点(起点正上方,吊装高度)
|
||
var liftPoint = HoistingCoordinateHelper.OffsetAlongUp(startPoint, liftHeightModelUnits, _adapter);
|
||
var liftPathPoint = new PathPoint(
|
||
liftPoint,
|
||
"提升点",
|
||
PathPointType.WayPoint);
|
||
liftPathPoint.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(liftPathPoint);
|
||
|
||
// 中间点(智能判断方向)
|
||
Point3D previousPoint = liftPoint;
|
||
|
||
for (int i = 0; i < groundIntermediatePoints.Count; i++)
|
||
{
|
||
var newPoint = GenerateSmartHoistingPoint(
|
||
previousPoint,
|
||
groundIntermediatePoints[i],
|
||
liftElevation,
|
||
i + 1);
|
||
|
||
pathPoints.Add(newPoint);
|
||
previousPoint = newPoint.Position;
|
||
}
|
||
|
||
// 最后一个空中点(用于垂直下降)
|
||
var lastAerialPoint = previousPoint;
|
||
var descendPathPoint = new PathPoint(
|
||
lastAerialPoint,
|
||
"下降点",
|
||
PathPointType.WayPoint);
|
||
descendPathPoint.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(descendPathPoint);
|
||
|
||
// 落地点(地面终点)
|
||
var endPathPoint = new PathPoint(
|
||
endPoint,
|
||
"落地点",
|
||
PathPointType.EndPoint);
|
||
endPathPoint.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(endPathPoint);
|
||
|
||
return pathPoints;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成多层阶梯式吊装路径
|
||
/// 支持在多个高度层进行水平移动,可混合上升和下降
|
||
/// </summary>
|
||
/// <param name="startPoint">起点(地面起吊位置)</param>
|
||
/// <param name="endPoint">终点(地面落点位置)</param>
|
||
/// <param name="levels">层级信息列表(按顺序执行)</param>
|
||
/// <returns>路径点列表</returns>
|
||
public List<PathPoint> GenerateMultiLevelHoistingPath(
|
||
Point3D startPoint,
|
||
Point3D endPoint,
|
||
List<HoistingLevel> levels)
|
||
{
|
||
if (startPoint == null)
|
||
throw new ArgumentNullException(nameof(startPoint));
|
||
if (endPoint == null)
|
||
throw new ArgumentNullException(nameof(endPoint));
|
||
if (levels == null || levels.Count == 0)
|
||
throw new ArgumentException("至少需要指定一个层级", nameof(levels));
|
||
|
||
var pathPoints = new List<PathPoint>();
|
||
|
||
// 点1:起吊点(物体初始位置)
|
||
var startPointPath = new PathPoint(
|
||
startPoint,
|
||
"起吊点",
|
||
PathPointType.StartPoint);
|
||
startPointPath.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(startPointPath);
|
||
|
||
Point3D currentPoint = startPoint;
|
||
|
||
// 按层级顺序生成路径点
|
||
for (int i = 0; i < levels.Count; i++)
|
||
{
|
||
var level = levels[i];
|
||
double levelHeightModelUnits = UnitsConverter.ConvertFromMeters(level.HeightInMeters);
|
||
double currentHeight = HoistingCoordinateHelper.GetElevation(startPoint, _adapter) + levelHeightModelUnits;
|
||
|
||
// 垂直移动点(上升或下降到该层级高度)
|
||
var verticalPoint = HoistingCoordinateHelper.SetElevation(currentPoint, currentHeight, _adapter);
|
||
|
||
string verticalPointName = level.IsRise ? $"提升点{i + 1}" : $"下降点{i + 1}";
|
||
var verticalPathPoint = new PathPoint(
|
||
verticalPoint,
|
||
verticalPointName,
|
||
PathPointType.WayPoint);
|
||
verticalPathPoint.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(verticalPathPoint);
|
||
|
||
// 水平移动点(移动到该层级的目标位置,保持高度)
|
||
var horizontalPoint = HoistingCoordinateHelper.SetElevation(level.HorizontalTarget, currentHeight, _adapter);
|
||
|
||
string horizontalPointName = $"平移点{i + 1}";
|
||
var horizontalPathPoint = new PathPoint(
|
||
horizontalPoint,
|
||
horizontalPointName,
|
||
PathPointType.WayPoint);
|
||
horizontalPathPoint.Direction = HoistingPointDirection.Longitudinal;
|
||
pathPoints.Add(horizontalPathPoint);
|
||
|
||
// 更新当前点为水平移动后的位置
|
||
currentPoint = horizontalPoint;
|
||
}
|
||
|
||
// 最后:垂直下降到地面终点
|
||
var descendPoint = HoistingCoordinateHelper.ProjectToAerialElevation(endPoint, currentPoint, _adapter);
|
||
var descendPathPoint = new PathPoint(
|
||
descendPoint,
|
||
"最终下降点",
|
||
PathPointType.WayPoint);
|
||
descendPathPoint.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(descendPathPoint);
|
||
|
||
// 点N:落地点(物体最终位置)
|
||
var endPointPath = new PathPoint(
|
||
endPoint,
|
||
"落地点",
|
||
PathPointType.EndPoint);
|
||
endPointPath.Direction = HoistingPointDirection.Vertical;
|
||
pathPoints.Add(endPointPath);
|
||
|
||
return pathPoints;
|
||
}
|
||
}
|
||
}
|