Skip to content

Instantly share code, notes, and snippets.

@JimBobSquarePants
Last active June 24, 2020 11:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JimBobSquarePants/22ace5133a232b25bacf447f641ae451 to your computer and use it in GitHub Desktop.
Save JimBobSquarePants/22ace5133a232b25bacf447f641ae451 to your computer and use it in GitHub Desktop.
Calculating intersections between two segments.
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