Last active
June 24, 2020 11:36
-
-
Save JimBobSquarePants/22ace5133a232b25bacf447f641ae451 to your computer and use it in GitHub Desktop.
Calculating intersections between two segments.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
var tl = new Vector2(0, 0); | |
var br = new Vector2(5, 3); | |
var tr = new Vector2(5, 0); | |
var bl = new Vector2(0, 3); | |
var tlbr = new Segment(tl, br); | |
var trbl = new Segment(tr, bl); | |
tlbr.FindIntersection(trbl).Dump(); | |
} | |
// Define other methods, classes and namespaces here | |
public readonly struct Segment | |
{ | |
public readonly Vector2 Start; | |
public readonly Vector2 End; | |
public readonly Vector2 Min; | |
public readonly Vector2 Max; | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public Segment(Vector2 start, Vector2 end) | |
{ | |
this.Start = start; | |
this.End = end; | |
this.Min = Vector2.Min(start, end); | |
this.Max = Vector2.Max(start, end); | |
} | |
public Vector2 Vector() => this.End - this.Start; | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public Vector2 FindIntersection(in Segment other) | |
{ | |
Vector2 p0p1 = this.Vector(); | |
Vector2 np0p1 = -p0p1; | |
Vector2 op0p1 = other.Vector(); | |
var matrix = new Matrix2x2(op0p1.X, np0p1.X, op0p1.Y, np0p1.Y); | |
if (!Matrix2x2.Invert(matrix, out Matrix2x2 inverted)) | |
{ | |
return new Vector2(float.MaxValue); | |
} | |
return p0p1 * Matrix2x2.Multiply(inverted, this.Start - other.Start); | |
} | |
} | |
private struct Matrix2x2 | |
{ | |
/// <summary> | |
/// The first element of the first row | |
/// </summary> | |
public float M11; | |
/// <summary> | |
/// The second element of the first row | |
/// </summary> | |
public float M12; | |
/// <summary> | |
/// The first element of the second row | |
/// </summary> | |
public float M21; | |
/// <summary> | |
/// The second element of the second row | |
/// </summary> | |
public float M22; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="Matrix2x2"/> struct. | |
/// </summary> | |
/// <param name="m11">The value at row 1, column 1 of the matrix.</param> | |
/// <param name="m12">The value at row 1, column 2 of the matrix.</param> | |
/// <param name="m21">The value at row 2, column 1 of the matrix.</param> | |
/// <param name="m22">The value at row 2, column 2 of the matrix.</param> | |
public Matrix2x2(float m11, float m12, float m21, float m22) | |
{ | |
this.M11 = m11; | |
this.M12 = m12; | |
this.M21 = m21; | |
this.M22 = m22; | |
} | |
/// <summary> | |
/// Scales all elements in a matrix by the given scalar factor. | |
/// </summary> | |
/// <param name="value1">The source matrix.</param> | |
/// <param name="value2">The scaling value to use.</param> | |
/// <returns>The resulting matrix.</returns> | |
public static Matrix2x2 operator /(Matrix2x2 value1, float value2) | |
{ | |
Matrix2x2 m; | |
m.M11 = value1.M11 / value2; | |
m.M12 = value1.M12 / value2; | |
m.M21 = value1.M21 / value2; | |
m.M22 = value1.M22 / value2; | |
return m; | |
} | |
/// <summary> | |
/// Calculates the determinant for this matrix. | |
/// </summary> | |
/// <returns>The determinant.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public readonly float GetDeterminant() | |
=> (this.M11 * this.M22) - (this.M21 * this.M12); | |
/// <summary> | |
/// Attempts to invert the given matrix. If the operation succeeds, the inverted matrix is stored in the result parameter. | |
/// </summary> | |
/// <param name="matrix">The source matrix.</param> | |
/// <param name="result">The output matrix.</param> | |
/// <returns>True if the operation succeeded, False otherwise.</returns> | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static bool Invert(Matrix2x2 matrix, out Matrix2x2 result) | |
{ | |
float det = matrix.GetDeterminant(); | |
if (MathF.Abs(det) < float.Epsilon) | |
{ | |
result = new Matrix2x2(float.NaN, float.NaN, float.NaN, float.NaN); | |
return false; | |
} | |
float invDet = 1F / det; | |
result.M11 = matrix.M22 * invDet; | |
result.M12 = -matrix.M12 * invDet; | |
result.M21 = -matrix.M21 * invDet; | |
result.M22 = matrix.M11 * invDet; | |
return true; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static Vector2 Multiply(Matrix2x2 matrix, Vector2 position) | |
{ | |
return new Vector2( | |
position.X * matrix.M11 + position.Y * matrix.M12, | |
position.X * matrix.M21 + position.Y * matrix.M22); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment