161 lines
5.4 KiB
C#
161 lines
5.4 KiB
C#
using Autodesk.Navisworks.Api;
|
||
using static NavisworksTransport.CategoryAttributeManager;
|
||
|
||
namespace NavisworksTransport.PathPlanning
|
||
{
|
||
/// <summary>
|
||
/// 体素单元类 - 表示3D网格中的单个体素
|
||
/// 用于体素网格路径规划,存储体素的属性和状态信息
|
||
/// </summary>
|
||
public class VoxelCell
|
||
{
|
||
/// <summary>
|
||
/// 体素类型(对应物流元素分类)
|
||
/// </summary>
|
||
public LogisticsElementType Type { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否可通行
|
||
/// true: 该体素为自由空间,可以通行
|
||
/// false: 该体素为障碍物或不可通行区域
|
||
/// </summary>
|
||
public bool IsPassable { get; set; }
|
||
|
||
/// <summary>
|
||
/// 到最近障碍物的距离(模型单位)
|
||
/// 使用Signed Distance Field (SDF)计算
|
||
/// 正值:自由空间,数值表示到最近障碍物的距离
|
||
/// 负值:障碍物内部,数值表示到障碍物表面的距离
|
||
/// 零值:障碍物表面
|
||
/// </summary>
|
||
public double Distance { get; set; }
|
||
|
||
/// <summary>
|
||
/// 速度限制(米/秒)
|
||
/// 根据体素所在区域的特性设置(如通道、电梯等)
|
||
/// 0.0 表示无速度限制(使用默认速度)
|
||
/// </summary>
|
||
public double SpeedLimit { get; set; }
|
||
|
||
/// <summary>
|
||
/// 源模型元素
|
||
/// 如果该体素对应某个BIM模型元素,存储其引用
|
||
/// 用于追溯体素属性的来源
|
||
/// </summary>
|
||
public ModelItem SourceItem { get; set; }
|
||
|
||
/// <summary>
|
||
/// 通行成本
|
||
/// 用于A*路径规划算法
|
||
/// 考虑因素:距离、速度限制、碰撞风险等
|
||
/// 值越大表示通行代价越高
|
||
/// </summary>
|
||
public double Cost { get; set; }
|
||
|
||
/// <summary>
|
||
/// 构造函数 - 创建默认的可通行体素
|
||
/// </summary>
|
||
public VoxelCell()
|
||
{
|
||
Type = LogisticsElementType.通道;
|
||
IsPassable = true;
|
||
Distance = double.MaxValue; // 初始化为无限远(远离障碍物)
|
||
SpeedLimit = 0.0; // 无速度限制
|
||
SourceItem = null;
|
||
Cost = 1.0; // 默认通行成本
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构造函数 - 创建指定属性的体素
|
||
/// </summary>
|
||
/// <param name="isPassable">是否可通行</param>
|
||
/// <param name="type">体素类型</param>
|
||
/// <param name="distance">到最近障碍物的距离</param>
|
||
public VoxelCell(bool isPassable, LogisticsElementType type = LogisticsElementType.通道, double distance = double.MaxValue)
|
||
{
|
||
Type = type;
|
||
IsPassable = isPassable;
|
||
Distance = distance;
|
||
SpeedLimit = 0.0;
|
||
SourceItem = null;
|
||
Cost = isPassable ? 1.0 : double.MaxValue; // 不可通行区域成本为无穷大
|
||
}
|
||
|
||
/// <summary>
|
||
/// 克隆体素单元
|
||
/// </summary>
|
||
/// <returns>体素单元的深拷贝</returns>
|
||
public VoxelCell Clone()
|
||
{
|
||
return new VoxelCell
|
||
{
|
||
Type = this.Type,
|
||
IsPassable = this.IsPassable,
|
||
Distance = this.Distance,
|
||
SpeedLimit = this.SpeedLimit,
|
||
SourceItem = this.SourceItem,
|
||
Cost = this.Cost
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置为障碍物体素
|
||
/// </summary>
|
||
/// <param name="sourceItem">源模型元素</param>
|
||
public void SetAsObstacle(ModelItem sourceItem = null)
|
||
{
|
||
IsPassable = false;
|
||
Type = LogisticsElementType.障碍物;
|
||
Distance = 0.0; // 障碍物表面距离为0
|
||
Cost = double.MaxValue;
|
||
SourceItem = sourceItem;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置为自由空间体素
|
||
/// </summary>
|
||
/// <param name="distance">到最近障碍物的距离</param>
|
||
public void SetAsFreeSpace(double distance = double.MaxValue)
|
||
{
|
||
IsPassable = true;
|
||
Type = LogisticsElementType.通道;
|
||
Distance = distance;
|
||
Cost = 1.0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据距离更新通行成本
|
||
/// 距离障碍物越近,成本越高(避免贴边行走)
|
||
/// </summary>
|
||
/// <param name="safetyMargin">安全边距(模型单位)</param>
|
||
public void UpdateCostFromDistance(double safetyMargin)
|
||
{
|
||
if (!IsPassable)
|
||
{
|
||
Cost = double.MaxValue;
|
||
return;
|
||
}
|
||
|
||
if (Distance < safetyMargin)
|
||
{
|
||
// 在安全边距内,成本线性增加
|
||
double ratio = Distance / safetyMargin;
|
||
Cost = 1.0 + (1.0 - ratio) * 10.0; // 成本范围:1.0 ~ 11.0
|
||
}
|
||
else
|
||
{
|
||
Cost = 1.0; // 安全距离外,标准成本
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回体素单元的字符串表示
|
||
/// </summary>
|
||
public override string ToString()
|
||
{
|
||
string passableStr = IsPassable ? "可通行" : "障碍";
|
||
return $"VoxelCell[{passableStr}, Type={Type}, Dist={Distance:F2}, Cost={Cost:F2}]";
|
||
}
|
||
}
|
||
}
|