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 System.Runtime.CompilerServices;
6using osu.Framework.Graphics.Primitives;
7using osuTK;
8
9namespace osu.Framework.Graphics
10{
11 public static class Vector2Extensions
12 {
13 /// <summary>Transform a Position by the given Matrix</summary>
14 /// <param name="pos">The position to transform</param>
15 /// <param name="mat">The desired transformation</param>
16 /// <returns>The transformed position</returns>
17 public static Vector2 Transform(Vector2 pos, Matrix3 mat)
18 {
19 Transform(ref pos, ref mat, out Vector2 result);
20 return result;
21 }
22
23 /// <summary>Transform a Position by the given Matrix</summary>
24 /// <param name="pos">The position to transform</param>
25 /// <param name="mat">The desired transformation</param>
26 /// <param name="result">The transformed vector</param>
27 public static void Transform(ref Vector2 pos, ref Matrix3 mat, out Vector2 result)
28 {
29 result.X = mat.Row0.X * pos.X + mat.Row1.X * pos.Y + mat.Row2.X;
30 result.Y = mat.Row0.Y * pos.X + mat.Row1.Y * pos.Y + mat.Row2.Y;
31 }
32
33 /// <summary>
34 /// Compute the euclidean distance between two vectors.
35 /// </summary>
36 /// <param name="vec1">The first vector</param>
37 /// <param name="vec2">The second vector</param>
38 /// <returns>The distance</returns>
39 public static float Distance(Vector2 vec1, Vector2 vec2)
40 {
41 Distance(ref vec1, ref vec2, out float result);
42 return result;
43 }
44
45 /// <summary>
46 /// Compute the euclidean distance between two vectors.
47 /// </summary>
48 /// <param name="vec1">The first vector</param>
49 /// <param name="vec2">The second vector</param>
50 /// <param name="result">The distance</param>
51 public static void Distance(ref Vector2 vec1, ref Vector2 vec2, out float result)
52 {
53 result = MathF.Sqrt((vec2.X - vec1.X) * (vec2.X - vec1.X) + (vec2.Y - vec1.Y) * (vec2.Y - vec1.Y));
54 }
55
56 /// <summary>
57 /// Compute the squared euclidean distance between two vectors.
58 /// </summary>
59 /// <param name="vec1">The first vector</param>
60 /// <param name="vec2">The second vector</param>
61 /// <returns>The squared distance</returns>
62 public static float DistanceSquared(Vector2 vec1, Vector2 vec2)
63 {
64 DistanceSquared(ref vec1, ref vec2, out float result);
65 return result;
66 }
67
68 /// <summary>
69 /// Compute the squared euclidean distance between two vectors.
70 /// </summary>
71 /// <param name="vec1">The first vector</param>
72 /// <param name="vec2">The second vector</param>
73 /// <param name="result">The squared distance</param>
74 public static void DistanceSquared(ref Vector2 vec1, ref Vector2 vec2, out float result)
75 {
76 result = (vec2.X - vec1.X) * (vec2.X - vec1.X) + (vec2.Y - vec1.Y) * (vec2.Y - vec1.Y);
77 }
78
79 /// <summary>
80 /// Retrieves the orientation of a set of vertices using the Shoelace formula (https://en.wikipedia.org/wiki/Shoelace_formula)
81 /// </summary>
82 /// <param name="vertices">The vertices.</param>
83 /// <returns>Twice the area enclosed by the vertices.
84 /// The vertices are clockwise-oriented if the value is positive.
85 /// The vertices are counter-clockwise-oriented if the value is negative.</returns>
86 [MethodImpl(MethodImplOptions.AggressiveInlining)]
87 public static float GetOrientation(in ReadOnlySpan<Vector2> vertices)
88 {
89 if (vertices.Length == 0)
90 return 0;
91
92 float rotation = 0;
93 for (int i = 0; i < vertices.Length - 1; ++i)
94 rotation += (vertices[i + 1].X - vertices[i].X) * (vertices[i + 1].Y + vertices[i].Y);
95
96 rotation += (vertices[0].X - vertices[^1].X) * (vertices[0].Y + vertices[^1].Y);
97
98 return rotation;
99 }
100
101 /// <summary>
102 /// Determines whether a point is within the right half-plane of a line.
103 /// </summary>
104 /// <param name="line">The line.</param>
105 /// <param name="point">The point.</param>
106 /// <returns>Whether <paramref name="point"/> is in the right half-plane of <paramref name="line"/>.
107 /// If the point is colinear to the line, it is said to be in the right half-plane of the line.
108 /// </returns>
109 [MethodImpl(MethodImplOptions.AggressiveInlining)]
110 public static bool InRightHalfPlaneOf(this Vector2 point, in Line line)
111 => (line.EndPoint.X - line.StartPoint.X) * (point.Y - line.StartPoint.Y)
112 - (line.EndPoint.Y - line.StartPoint.Y) * (point.X - line.StartPoint.X) <= 0;
113 }
114}