A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using osu.Framework.Graphics.Primitives;
6using osuTK;
7
8namespace osu.Framework.Extensions.PolygonExtensions
9{
10 public static class PolygonExtensions
11 {
12 /// <summary>
13 /// Computes the axes for each edge in a polygon.
14 /// </summary>
15 /// <param name="polygon">The polygon to compute the axes of.</param>
16 /// <param name="normalize">Whether the normals should be normalized. Allows computation of the exact intersection point.</param>
17 /// <returns>The axes of the polygon.</returns>
18 public static Span<Vector2> GetAxes<TPolygon>(TPolygon polygon, bool normalize = false)
19 where TPolygon : IPolygon
20 {
21 var axisVertices = polygon.GetAxisVertices();
22 return getAxes(axisVertices, new Vector2[axisVertices.Length], normalize);
23 }
24
25 /// <summary>
26 /// Computes the axes for each edge in a polygon.
27 /// </summary>
28 /// <param name="polygon">The polygon to compute the axes of.</param>
29 /// <param name="buffer">A buffer to be used as storage for the axes. Must have a length of at least the count of vertices in <paramref name="polygon"/>.</param>
30 /// <param name="normalize">Whether the normals should be normalized. Allows computation of the exact intersection point.</param>
31 /// <returns>The axes of the polygon. Returned as a slice of <paramref name="buffer"/>.</returns>
32 public static Span<Vector2> GetAxes<TPolygon>(this TPolygon polygon, Span<Vector2> buffer, bool normalize = false)
33 where TPolygon : IPolygon
34 => getAxes(polygon.GetAxisVertices(), buffer, normalize);
35
36 /// <summary>
37 /// Computes the axes for a set of vertices.
38 /// </summary>
39 /// <param name="vertices">The vertices to compute the axes for.</param>
40 /// <param name="buffer">A buffer to be used as storage for the axes. Must have a length of at least the count of <paramref name="vertices"/>.</param>
41 /// <param name="normalize">Whether the normals should be normalized. Allows computation of the exact intersection point.</param>
42 /// <returns>The axes represented by <paramref name="vertices"/>. Returned as a slice of <paramref name="buffer"/>.</returns>
43 private static Span<Vector2> getAxes(ReadOnlySpan<Vector2> vertices, Span<Vector2> buffer, bool normalize = false)
44 {
45 if (buffer.Length < vertices.Length)
46 throw new ArgumentException($"Axis buffer must have a length of {vertices.Length}, but was {buffer.Length}.", nameof(buffer));
47
48 for (int i = 0; i < vertices.Length; i++)
49 {
50 // Construct an edge between two sequential points
51 Vector2 v1 = vertices[i];
52 Vector2 v2 = vertices[i == vertices.Length - 1 ? 0 : i + 1];
53 Vector2 edge = v2 - v1;
54
55 // Find the normal to the edge
56 Vector2 normal = new Vector2(-edge.Y, edge.X);
57
58 if (normalize)
59 normal = Vector2.Normalize(normal);
60
61 buffer[i] = normal;
62 }
63
64 return buffer.Slice(0, vertices.Length);
65 }
66 }
67}