using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using MultiWheelC.TrajectoryPlanning.Utils;
namespace MultiWheelC.TrajectoryPlanning.PathSmoothing.LocalG2;
/// 一个局部 G2 候选可替换的弧长窗口。
internal sealed class LocalG2WindowVariant
{
/// 创建同一平滑区域内一个可尝试替换的弧长窗口变体。
/// 区域内候选的稳定从零开始索引。
/// 窗口起点弧长,单位 m。
/// 窗口终点弧长,单位 m。
/// 过渡点左侧窗口长度,单位 m。
/// 过渡点右侧窗口长度,单位 m。
internal LocalG2WindowVariant(int candidateIndex, double startArcLengthMeters, double endArcLengthMeters,
double leftWindowLengthMeters, double rightWindowLengthMeters)
{
if (candidateIndex < 0 || startArcLengthMeters < 0d || endArcLengthMeters < startArcLengthMeters ||
leftWindowLengthMeters < 0d || rightWindowLengthMeters < 0d)
{
throw new ArgumentOutOfRangeException(nameof(candidateIndex));
}
CandidateIndex = candidateIndex;
StartArcLengthMeters = startArcLengthMeters;
EndArcLengthMeters = endArcLengthMeters;
LeftWindowLengthMeters = leftWindowLengthMeters;
RightWindowLengthMeters = rightWindowLengthMeters;
}
internal int CandidateIndex { get; }
internal double StartArcLengthMeters { get; }
internal double EndArcLengthMeters { get; }
internal double LeftWindowLengthMeters { get; }
internal double RightWindowLengthMeters { get; }
}
/// 至少存在一个联合合法生成窗口变体的一组曲率过渡。
internal sealed class LocalG2SmoothingRegion
{
/// 创建一个包含共同可用窗口变体的局部曲率过渡区域。
/// 所属方向段在预处理路径中的从零开始索引。
/// 归并到该区域的曲率跳变集合。
/// 所有候选允许的最晚窗口起点,单位 m。
/// 所有候选允许的最早窗口终点,单位 m。
/// 至少一个合法的窗口变体集合。
internal LocalG2SmoothingRegion(
int segmentIndex,
IReadOnlyList transitions,
double maximumStartArcLengthMeters,
double maximumEndArcLengthMeters,
IReadOnlyList windowVariants)
{
if (segmentIndex < 0 || transitions == null || transitions.Count == 0 ||
!NumericGuard.IsFinite(maximumStartArcLengthMeters) ||
!NumericGuard.IsFinite(maximumEndArcLengthMeters) ||
maximumStartArcLengthMeters < 0d ||
maximumEndArcLengthMeters < maximumStartArcLengthMeters ||
windowVariants == null || windowVariants.Count == 0)
{
throw new ArgumentOutOfRangeException(nameof(transitions));
}
SegmentIndex = segmentIndex;
Transitions = Copy(transitions);
MaximumStartArcLengthMeters = maximumStartArcLengthMeters;
MaximumEndArcLengthMeters = maximumEndArcLengthMeters;
WindowVariants = Copy(windowVariants);
}
internal int SegmentIndex { get; }
internal IReadOnlyList Transitions { get; }
internal double MaximumStartArcLengthMeters { get; }
internal double MaximumEndArcLengthMeters { get; }
internal IReadOnlyList WindowVariants { get; }
private static IReadOnlyList Copy(IReadOnlyList source)
{
var copy = new List(source.Count);
for (int index = 0; index < source.Count; index++) copy.Add(source[index]);
return new ReadOnlyCollection(copy);
}
}