251 lines
10 KiB
C#
251 lines
10 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Autodesk.Navisworks.Api;
|
||
using NavisworksTransport.Core;
|
||
using NavisworksTransport.PathPlanning;
|
||
using NavisworksTransport.Utils;
|
||
using NavisworksTransport.Core.Config;
|
||
|
||
namespace NavisworksTransport.Commands
|
||
{
|
||
/// <summary>
|
||
/// 创建空中路径命令(空轨或吊装)
|
||
/// </summary>
|
||
public class CreateAerialPathCommand : CommandBase
|
||
{
|
||
private readonly AerialPathParameters _parameters;
|
||
private readonly PathPlanningManager _pathPlanningManager;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="parameters">空中路径参数</param>
|
||
public CreateAerialPathCommand(AerialPathParameters parameters)
|
||
{
|
||
_parameters = parameters ?? throw new ArgumentNullException(nameof(parameters));
|
||
_pathPlanningManager = PathPlanningManager.Instance;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行命令
|
||
/// </summary>
|
||
protected override Task<PathPlanningResult> ExecuteInternalAsync(CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
// 验证参数
|
||
var validationResult = ValidateParameters();
|
||
if (!validationResult.IsSuccess)
|
||
{
|
||
return Task.FromResult<PathPlanningResult>(validationResult);
|
||
}
|
||
|
||
string pathTypeName = _parameters.PathType == PathType.Hoisting ? "吊装" : "空轨";
|
||
LogManager.Info($"开始创建{pathTypeName}路径...");
|
||
|
||
List<PathPoint> pathPoints;
|
||
|
||
if (_parameters.PathType == PathType.Hoisting)
|
||
{
|
||
var generator = new AerialPathGenerator();
|
||
|
||
if (_parameters.HoistingMode == HoistingMode.MultiLevel &&
|
||
_parameters.HoistingLevels != null &&
|
||
_parameters.HoistingLevels.Count > 0)
|
||
{
|
||
// 多层阶梯式吊装
|
||
pathPoints = generator.GenerateMultiLevelHoistingPath(
|
||
_parameters.StartPoint,
|
||
_parameters.EndPoint,
|
||
_parameters.HoistingLevels);
|
||
|
||
LogManager.Info($"多层吊装路径: 起点=({_parameters.StartPoint.X:F2},{_parameters.StartPoint.Y:F2},{_parameters.StartPoint.Z:F2}), " +
|
||
$"终点=({_parameters.EndPoint.X:F2},{_parameters.EndPoint.Y:F2},{_parameters.EndPoint.Z:F2}), " +
|
||
$"层级数={_parameters.HoistingLevels.Count}, 总点数={pathPoints.Count}");
|
||
}
|
||
else
|
||
{
|
||
// 单层吊装(传统模式,默认)
|
||
double liftHeightModelUnits = UnitsConverter.ConvertFromMeters(_parameters.LiftHeightMeters);
|
||
pathPoints = generator.GenerateThreeStepHoistingPath(
|
||
_parameters.StartPoint,
|
||
_parameters.EndPoint,
|
||
liftHeightModelUnits);
|
||
|
||
LogManager.Info($"单层吊装路径: 起点=({_parameters.StartPoint.X:F2},{_parameters.StartPoint.Y:F2},{_parameters.StartPoint.Z:F2}), " +
|
||
$"终点=({_parameters.EndPoint.X:F2},{_parameters.EndPoint.Y:F2},{_parameters.EndPoint.Z:F2}), " +
|
||
$"提升高度={_parameters.LiftHeightMeters:F2}米");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 空轨:使用现有的空轨吸附逻辑,从点击点生成路径点
|
||
pathPoints = GenerateRailPathPoints(_parameters.ClickedPoints);
|
||
|
||
LogManager.Info($"空轨路径: 路径点数={pathPoints.Count}");
|
||
}
|
||
|
||
// 创建路径对象
|
||
string routeName = _parameters.PathType == PathType.Hoisting
|
||
? $"吊装路径_{DateTime.Now:HHmmss}"
|
||
: $"空轨路径_{DateTime.Now:HHmmss}";
|
||
|
||
var route = new PathRoute(routeName)
|
||
{
|
||
PathType = _parameters.PathType,
|
||
LiftHeight = _parameters.PathType == PathType.Hoisting ? UnitsConverter.ConvertFromMeters(_parameters.LiftHeightMeters) : 0,
|
||
Points = pathPoints,
|
||
CreatedTime = DateTime.Now,
|
||
LastModified = DateTime.Now
|
||
};
|
||
|
||
// 设置物体参数(从配置获取,转换为模型单位)
|
||
var config = ConfigManager.Instance.Current;
|
||
route.MaxObjectLength = config.PathEditing.ObjectLength;
|
||
route.MaxObjectWidth = config.PathEditing.ObjectWidth;
|
||
route.MaxObjectHeight = config.PathEditing.ObjectHeight;
|
||
route.SafetyMargin = config.PathEditing.SafetyMargin;
|
||
|
||
// 注意:TotalLength 由计算属性实时提供,无需手动设置
|
||
// 它会自动从 Points 计算直线距离
|
||
|
||
LogManager.Info($"{pathTypeName}路径创建成功: {route.Name}, 路径点数: {pathPoints.Count}, 总长度: {route.TotalLength:F2}米");
|
||
|
||
// 保存路径到数据库
|
||
_pathPlanningManager.AddRoute(route);
|
||
|
||
var genericResult = PathPlanningResult<PathRoute>.Success(route, $"{pathTypeName}路径创建成功");
|
||
return Task.FromResult<PathPlanningResult>(genericResult);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
LogManager.Error($"创建空中路径失败: {ex.Message}", ex);
|
||
var genericResult = PathPlanningResult<PathRoute>.Failure($"创建空中路径失败: {ex.Message}", ex);
|
||
return Task.FromResult<PathPlanningResult>(genericResult);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证参数
|
||
/// </summary>
|
||
protected override PathPlanningResult ValidateParameters()
|
||
{
|
||
if (_parameters.PathType == PathType.Hoisting)
|
||
{
|
||
if (_parameters.StartPoint == null)
|
||
return PathPlanningResult.ValidationFailure("起点不能为空");
|
||
|
||
if (_parameters.EndPoint == null)
|
||
return PathPlanningResult.ValidationFailure("终点不能为空");
|
||
|
||
// 单层模式:检查 LiftHeightMeters
|
||
// 多层模式:检查 HoistingLevels
|
||
if (_parameters.HoistingMode == HoistingMode.SingleLevel)
|
||
{
|
||
if (_parameters.LiftHeightMeters <= 0)
|
||
return PathPlanningResult.ValidationFailure("提升高度必须大于0");
|
||
}
|
||
else if (_parameters.HoistingMode == HoistingMode.MultiLevel)
|
||
{
|
||
if (_parameters.HoistingLevels == null || _parameters.HoistingLevels.Count == 0)
|
||
return PathPlanningResult.ValidationFailure("请至少设置一个吊装层级");
|
||
|
||
// 检查每个层级的高度
|
||
foreach (var level in _parameters.HoistingLevels)
|
||
{
|
||
if (level.HeightInMeters <= 0)
|
||
return PathPlanningResult.ValidationFailure($"层级{level.Index + 1}的高度必须大于0");
|
||
}
|
||
}
|
||
}
|
||
else if (_parameters.PathType == PathType.Rail)
|
||
{
|
||
if (_parameters.ClickedPoints == null || _parameters.ClickedPoints.Count == 0)
|
||
return PathPlanningResult.ValidationFailure("点击点不能为空");
|
||
}
|
||
|
||
return PathPlanningResult.Success("参数验证通过");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从点击点生成空轨路径点(使用现有的空轨吸附逻辑)
|
||
/// </summary>
|
||
private List<PathPoint> GenerateRailPathPoints(List<Point3D> clickedPoints)
|
||
{
|
||
var pathPoints = new List<PathPoint>();
|
||
|
||
for (int i = 0; i < clickedPoints.Count; i++)
|
||
{
|
||
var point = clickedPoints[i];
|
||
var pointType = PathPointType.WayPoint;
|
||
|
||
if (i == 0)
|
||
pointType = PathPointType.StartPoint;
|
||
else if (i == clickedPoints.Count - 1)
|
||
pointType = PathPointType.EndPoint;
|
||
|
||
pathPoints.Add(new PathPoint(
|
||
point,
|
||
$"路径点{i + 1}",
|
||
pointType));
|
||
}
|
||
|
||
return pathPoints;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 空中路径参数
|
||
/// </summary>
|
||
public class AerialPathParameters
|
||
{
|
||
/// <summary>
|
||
/// 路径类型(空轨或吊装)
|
||
/// </summary>
|
||
public PathType PathType { get; set; }
|
||
|
||
/// <summary>
|
||
/// 吊装参数:起点(吊起位置)
|
||
/// </summary>
|
||
public Point3D StartPoint { get; set; }
|
||
|
||
/// <summary>
|
||
/// 吊装参数:终点(下降位置)
|
||
/// </summary>
|
||
public Point3D EndPoint { get; set; }
|
||
|
||
/// <summary>
|
||
/// 吊装参数:提升高度(米)
|
||
/// 单层吊装模式使用,多层模式下该值被忽略
|
||
/// </summary>
|
||
public double LiftHeightMeters { get; set; }
|
||
|
||
/// <summary>
|
||
/// 空轨参数:点击点列表
|
||
/// </summary>
|
||
public List<Point3D> ClickedPoints { get; set; }
|
||
|
||
/// <summary>
|
||
/// 吊装路径模式(默认单层,向后兼容)
|
||
/// </summary>
|
||
public HoistingMode HoistingMode { get; set; } = HoistingMode.SingleLevel;
|
||
|
||
/// <summary>
|
||
/// 多层吊装:层级信息列表(仅多层模式使用)
|
||
/// </summary>
|
||
public List<HoistingLevel> HoistingLevels { get; set; }
|
||
|
||
/// <summary>
|
||
/// 默认构造函数
|
||
/// </summary>
|
||
public AerialPathParameters()
|
||
{
|
||
HoistingMode = HoistingMode.SingleLevel;
|
||
HoistingLevels = new List<HoistingLevel>();
|
||
ClickedPoints = new List<Point3D>();
|
||
}
|
||
}
|
||
}
|