// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using osu.Framework.Graphics.Primitives; using osuTK; namespace osu.Framework.Extensions.PolygonExtensions { public static class PolygonExtensions { /// /// Computes the axes for each edge in a polygon. /// /// The polygon to compute the axes of. /// Whether the normals should be normalized. Allows computation of the exact intersection point. /// The axes of the polygon. public static Span GetAxes(TPolygon polygon, bool normalize = false) where TPolygon : IPolygon { var axisVertices = polygon.GetAxisVertices(); return getAxes(axisVertices, new Vector2[axisVertices.Length], normalize); } /// /// Computes the axes for each edge in a polygon. /// /// The polygon to compute the axes of. /// A buffer to be used as storage for the axes. Must have a length of at least the count of vertices in . /// Whether the normals should be normalized. Allows computation of the exact intersection point. /// The axes of the polygon. Returned as a slice of . public static Span GetAxes(this TPolygon polygon, Span buffer, bool normalize = false) where TPolygon : IPolygon => getAxes(polygon.GetAxisVertices(), buffer, normalize); /// /// Computes the axes for a set of vertices. /// /// The vertices to compute the axes for. /// A buffer to be used as storage for the axes. Must have a length of at least the count of . /// Whether the normals should be normalized. Allows computation of the exact intersection point. /// The axes represented by . Returned as a slice of . private static Span getAxes(ReadOnlySpan vertices, Span buffer, bool normalize = false) { if (buffer.Length < vertices.Length) throw new ArgumentException($"Axis buffer must have a length of {vertices.Length}, but was {buffer.Length}.", nameof(buffer)); for (int i = 0; i < vertices.Length; i++) { // Construct an edge between two sequential points Vector2 v1 = vertices[i]; Vector2 v2 = vertices[i == vertices.Length - 1 ? 0 : i + 1]; Vector2 edge = v2 - v1; // Find the normal to the edge Vector2 normal = new Vector2(-edge.Y, edge.X); if (normalize) normal = Vector2.Normalize(normal); buffer[i] = normal; } return buffer.Slice(0, vertices.Length); } } }