| | | 1 | | //======================================================================= |
| | | 2 | | // GridConvexPolygon2d.cs |
| | | 3 | | //======================================================================= |
| | | 4 | | // MIT License, Copyright (c) 2024-present David Oravsky (mrdav30) |
| | | 5 | | // See LICENSE file in the project root for full license information. |
| | | 6 | | //======================================================================= |
| | | 7 | | |
| | | 8 | | using System; |
| | | 9 | | using System.Runtime.CompilerServices; |
| | | 10 | | using FixedMathSharp; |
| | | 11 | | |
| | | 12 | | namespace GridForge.Grids.Topology; |
| | | 13 | | |
| | | 14 | | /// <summary> |
| | | 15 | | /// Stores a boundary-ordered convex polygon produced by exact grid-cell contact clipping. |
| | | 16 | | /// </summary> |
| | | 17 | | public readonly struct GridConvexPolygon2d |
| | | 18 | | { |
| | | 19 | | /// <summary> |
| | | 20 | | /// Maximum vertices in the intersection of two rectangular or hexagonal cell footprints. |
| | | 21 | | /// </summary> |
| | | 22 | | public const int MaxVertexCount = 12; |
| | | 23 | | |
| | | 24 | | private readonly Vector2d _vertex0; |
| | | 25 | | private readonly Vector2d _vertex1; |
| | | 26 | | private readonly Vector2d _vertex2; |
| | | 27 | | private readonly Vector2d _vertex3; |
| | | 28 | | private readonly Vector2d _vertex4; |
| | | 29 | | private readonly Vector2d _vertex5; |
| | | 30 | | private readonly Vector2d _vertex6; |
| | | 31 | | private readonly Vector2d _vertex7; |
| | | 32 | | private readonly Vector2d _vertex8; |
| | | 33 | | private readonly Vector2d _vertex9; |
| | | 34 | | private readonly Vector2d _vertex10; |
| | | 35 | | private readonly Vector2d _vertex11; |
| | | 36 | | |
| | | 37 | | /// <summary> |
| | | 38 | | /// Number of boundary-ordered vertices in this polygon. |
| | | 39 | | /// </summary> |
| | | 40 | | public int VertexCount { get; } |
| | | 41 | | |
| | | 42 | | internal GridConvexPolygon2d(ReadOnlySpan<Vector2d> vertices) |
| | | 43 | | { |
| | 54 | 44 | | if (vertices.Length > MaxVertexCount) |
| | 1 | 45 | | throw new ArgumentOutOfRangeException(nameof(vertices)); |
| | | 46 | | |
| | 53 | 47 | | VertexCount = vertices.Length; |
| | 53 | 48 | | _vertex0 = GetOrDefault(vertices, 0); |
| | 53 | 49 | | _vertex1 = GetOrDefault(vertices, 1); |
| | 53 | 50 | | _vertex2 = GetOrDefault(vertices, 2); |
| | 53 | 51 | | _vertex3 = GetOrDefault(vertices, 3); |
| | 53 | 52 | | _vertex4 = GetOrDefault(vertices, 4); |
| | 53 | 53 | | _vertex5 = GetOrDefault(vertices, 5); |
| | 53 | 54 | | _vertex6 = GetOrDefault(vertices, 6); |
| | 53 | 55 | | _vertex7 = GetOrDefault(vertices, 7); |
| | 53 | 56 | | _vertex8 = GetOrDefault(vertices, 8); |
| | 53 | 57 | | _vertex9 = GetOrDefault(vertices, 9); |
| | 53 | 58 | | _vertex10 = GetOrDefault(vertices, 10); |
| | 53 | 59 | | _vertex11 = GetOrDefault(vertices, 11); |
| | 53 | 60 | | } |
| | | 61 | | |
| | | 62 | | /// <summary> |
| | | 63 | | /// Gets one boundary-ordered polygon vertex. |
| | | 64 | | /// </summary> |
| | | 65 | | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
| | 108 | 66 | | public Vector2d GetVertex(int index) => index switch |
| | 108 | 67 | | { |
| | 46 | 68 | | 0 when VertexCount > 0 => _vertex0, |
| | 46 | 69 | | 1 when VertexCount > 1 => _vertex1, |
| | 46 | 70 | | 2 when VertexCount > 2 => _vertex2, |
| | 46 | 71 | | 3 when VertexCount > 3 => _vertex3, |
| | 6 | 72 | | 4 when VertexCount > 4 => _vertex4, |
| | 6 | 73 | | 5 when VertexCount > 5 => _vertex5, |
| | 4 | 74 | | 6 when VertexCount > 6 => _vertex6, |
| | 2 | 75 | | 7 when VertexCount > 7 => _vertex7, |
| | 2 | 76 | | 8 when VertexCount > 8 => _vertex8, |
| | 2 | 77 | | 9 when VertexCount > 9 => _vertex9, |
| | 2 | 78 | | 10 when VertexCount > 10 => _vertex10, |
| | 4 | 79 | | 11 when VertexCount > 11 => _vertex11, |
| | 2 | 80 | | _ => throw new ArgumentOutOfRangeException(nameof(index)) |
| | 108 | 81 | | }; |
| | | 82 | | |
| | | 83 | | /// <summary> |
| | | 84 | | /// Copies the boundary-ordered vertices into caller-owned storage. |
| | | 85 | | /// </summary> |
| | | 86 | | public void CopyTo(Span<Vector2d> destination) |
| | | 87 | | { |
| | 24 | 88 | | if (destination.Length < VertexCount) |
| | 1 | 89 | | throw new ArgumentException("The destination is smaller than the polygon.", nameof(destination)); |
| | | 90 | | |
| | 254 | 91 | | for (int i = 0; i < VertexCount; i++) |
| | 104 | 92 | | destination[i] = GetVertex(i); |
| | 23 | 93 | | } |
| | | 94 | | |
| | | 95 | | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
| | | 96 | | private static Vector2d GetOrDefault(ReadOnlySpan<Vector2d> vertices, int index) => |
| | 636 | 97 | | index < vertices.Length ? vertices[index] : default; |
| | | 98 | | } |