using System; using System.Collections.Generic; namespace TrajectoryPlanningVisualization; public sealed class VisualizationPolyline { public VisualizationPolyline(string id, string legendChinese, string kind, VisualizationLineStyle lineStyle, IReadOnlyList points) { Id = VisualizationContract.RequireText(id, nameof(id)); LegendChinese = VisualizationContract.RequireText(legendChinese, nameof(legendChinese)); Kind = VisualizationContract.RequireText(kind, nameof(kind)); LineStyle = lineStyle; Points = VisualizationContract.Copy(points, nameof(points)); } public string Id { get; } public string LegendChinese { get; } public string Kind { get; } public VisualizationLineStyle LineStyle { get; } public IReadOnlyList Points { get; } } public sealed class VisualizationMarker { public VisualizationMarker(string id, string kind, string labelChinese, VisualizationPoint position) { Id = VisualizationContract.RequireText(id, nameof(id)); Kind = VisualizationContract.RequireText(kind, nameof(kind)); LabelChinese = VisualizationContract.RequireText(labelChinese, nameof(labelChinese)); Position = position ?? throw new ArgumentNullException(nameof(position)); } public string Id { get; } public string Kind { get; } public string LabelChinese { get; } public VisualizationPoint Position { get; } } public sealed class VisualizationDirectionSegment { public VisualizationDirectionSegment(int segmentIndex, string direction, bool startsAtGearSwitch, bool endsAtGearSwitch, IReadOnlyList points) { SegmentIndex = segmentIndex; Direction = VisualizationContract.RequireText(direction, nameof(direction)); StartsAtGearSwitch = startsAtGearSwitch; EndsAtGearSwitch = endsAtGearSwitch; Points = VisualizationContract.Copy(points, nameof(points)); } public int SegmentIndex { get; } public string Direction { get; } public bool StartsAtGearSwitch { get; } public bool EndsAtGearSwitch { get; } public IReadOnlyList Points { get; } } public sealed class VisualizationOccupancyGrid { public VisualizationOccupancyGrid(VisualizationBounds bounds, double resolutionMeters, int rows, int columns, byte[] occupancyBits) { Bounds = bounds ?? throw new ArgumentNullException(nameof(bounds)); VisualizationContract.RequireFinite(resolutionMeters, nameof(resolutionMeters)); if (resolutionMeters <= 0d) { throw new ArgumentOutOfRangeException(nameof(resolutionMeters)); } if (rows <= 0) { throw new ArgumentOutOfRangeException(nameof(rows)); } if (columns <= 0) { throw new ArgumentOutOfRangeException(nameof(columns)); } if (occupancyBits == null) { throw new ArgumentNullException(nameof(occupancyBits)); } long cellCount = (long)rows * columns; long requiredByteCount = (cellCount + 7L) / 8L; if (occupancyBits.Length != requiredByteCount) { throw new ArgumentException("Occupancy bit count does not match the grid dimensions.", nameof(occupancyBits)); } var bitsCopy = new byte[occupancyBits.Length]; Buffer.BlockCopy(occupancyBits, 0, bitsCopy, 0, bitsCopy.Length); ResolutionMeters = resolutionMeters; Rows = rows; Columns = columns; OccupancyBitsBase64 = Convert.ToBase64String(bitsCopy); } public VisualizationBounds Bounds { get; } public double ResolutionMeters { get; } public int Rows { get; } public int Columns { get; } public string OccupancyBitsBase64 { get; } }