2026-08-03 22:27:00 +08:00
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace MultiWheelC.TrajectoryPlanning.EMPlanner;
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 方向段的不可变参考边界标识,携带局部与源路径弧长以及边界语义。
|
|
|
|
|
/// 两个弧长均以 m 计;相等性仅代表同一段、同一局部位置和同一类型,不以源弧长参与判等。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public sealed class ReferenceBoundary : IEquatable<ReferenceBoundary>
|
|
|
|
|
{
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 创建已验证的参考边界。
|
|
|
|
|
/// 参数:segmentIndex 必须非负,segmentLocalS 与 sourceArcLength 为非负有限 m 制弧长,boundaryType 必须是已定义枚举;非法输入会引发异常。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public ReferenceBoundary(int segmentIndex, double segmentLocalS, EmBoundaryType boundaryType, double sourceArcLength)
|
|
|
|
|
{
|
|
|
|
|
if (segmentIndex < 0)
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(segmentIndex));
|
|
|
|
|
if (double.IsNaN(segmentLocalS) || double.IsInfinity(segmentLocalS) || segmentLocalS < 0d)
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(segmentLocalS));
|
|
|
|
|
if (double.IsNaN(sourceArcLength) || double.IsInfinity(sourceArcLength) || sourceArcLength < 0d)
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(sourceArcLength));
|
|
|
|
|
if (!Enum.IsDefined(typeof(EmBoundaryType), boundaryType))
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(boundaryType));
|
|
|
|
|
|
|
|
|
|
SegmentIndex = segmentIndex;
|
|
|
|
|
SegmentLocalS = segmentLocalS;
|
|
|
|
|
BoundaryType = boundaryType;
|
|
|
|
|
SourceArcLength = sourceArcLength;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 边界所属方向段在路径段序列中的零基索引。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public int SegmentIndex { get; }
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 边界相对该方向段起点的局部参考弧长 S,单位 m。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public double SegmentLocalS { get; }
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 边界的目标、换向或普通边界语义。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public EmBoundaryType BoundaryType { get; }
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 边界在未重基原始平滑路径中的累计弧长,单位 m。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public double SourceArcLength { get; }
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 比较两个边界在优化语义上是否相同。
|
|
|
|
|
/// 参数:other 可为 null;返回:仅段索引、局部 S(精确 double 比较)和边界类型都相同时为 true,源弧长不参与比较。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public bool Equals(ReferenceBoundary other)
|
|
|
|
|
{
|
|
|
|
|
return other != null && SegmentIndex == other.SegmentIndex && SegmentLocalS.Equals(other.SegmentLocalS) &&
|
|
|
|
|
BoundaryType == other.BoundaryType;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 比较任意对象是否为同一参考边界。
|
|
|
|
|
/// 参数:obj 可为空或非边界对象;返回:仅可转换为 <see cref="ReferenceBoundary"/> 且满足强类型相等性时为 true。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public override bool Equals(object obj) { return Equals(obj as ReferenceBoundary); }
|
|
|
|
|
|
2026-08-11 20:32:31 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 计算与边界相等性一致的哈希值。
|
|
|
|
|
/// 返回:由段索引、局部 S 与边界类型组成的哈希;源弧长不参与以保持与 <see cref="Equals(ReferenceBoundary)"/> 一致。
|
|
|
|
|
/// </summary>
|
2026-08-03 22:27:00 +08:00
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
int hash = SegmentIndex;
|
|
|
|
|
hash = (hash * 397) ^ SegmentLocalS.GetHashCode();
|
|
|
|
|
return (hash * 397) ^ (int)BoundaryType;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|