mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
213 lines
4.7 KiB
Beef
213 lines
4.7 KiB
Beef
using System;
|
||
using GlitchyEngine.Math;
|
||
namespace Sandbox
|
||
{
|
||
struct Line2D
|
||
{
|
||
public Vector2 Start;
|
||
public Vector2 End;
|
||
|
||
public this(Vector2 start, Vector2 end)
|
||
{
|
||
Start = start;
|
||
End = end;
|
||
}
|
||
|
||
/// Returns true if the given point lies on the line.
|
||
public bool OnLine(Vector2 point)
|
||
{
|
||
Vector2 startToPoint = point - Start;
|
||
Vector2 startToEnd = End - Start;
|
||
|
||
float cross = cross(startToPoint, startToEnd);
|
||
|
||
if(!MathHelper.IsZero(cross))
|
||
return false;
|
||
|
||
if(Math.Abs(startToEnd.X) >= Math.Abs(startToEnd.Y))
|
||
{
|
||
return (startToEnd.X > 0.0f) ?
|
||
(Start.X <= point.X && point.X <= End.X) :
|
||
(End.X <= point.X && point.X <= Start.X);
|
||
}
|
||
else
|
||
{
|
||
return (startToEnd.Y > 0.0f) ?
|
||
(Start.Y <= point.Y && point.Y <= End.Y) :
|
||
(End.Y <= point.Y && point.Y <= Start.Y);
|
||
}
|
||
}
|
||
|
||
[Inline]
|
||
private float cross(Vector2 v, Vector2 w)
|
||
{
|
||
return v.X * w.Y - v.Y * w.X;
|
||
}
|
||
|
||
public enum LineIntersection
|
||
{
|
||
case Collinear(Line2D IntersectionLine);
|
||
case CollinearNoIntersect;
|
||
case Parallel;
|
||
case Intersection(Vector2 Point);
|
||
case None;
|
||
}
|
||
|
||
private Result<(float Start, float End)> IntervalIntersection(float startA, float endA, float startB, float endB)
|
||
{
|
||
if(startB > endA || startA > endB)
|
||
return .Err;
|
||
else
|
||
{
|
||
float start = Math.Max(startA, startB);
|
||
float end = Math.Min(endA, endB);
|
||
|
||
return .Ok((start, end));
|
||
}
|
||
}
|
||
|
||
public LineIntersection Intersects(Line2D line)
|
||
{
|
||
Vector2 A = this.Start;
|
||
Vector2 B = this.End;
|
||
Vector2 C = line.Start;
|
||
Vector2 D = line.End;
|
||
|
||
float numR = ((A.Y-C.Y) * (D.X-C.X) - (A.X-C.X) * (D.Y-C.Y));
|
||
float den = ((B.X-A.X) * (D.Y-C.Y)-(B.Y-A.Y) * (D.X-C.X));
|
||
|
||
float r = numR / den;
|
||
float s = ((A.Y-C.Y) * (B.X-A.X) - (A.X-C.X) * (B.Y-A.Y)) / den;
|
||
|
||
if((0 <= r && r <= 1) && (0 <= s && s <= 1))
|
||
{
|
||
Vector2 P = A + r * (B - A);
|
||
|
||
return .Intersection(P);
|
||
}
|
||
else if(MathHelper.IsZero(den))
|
||
{
|
||
if(MathHelper.IsZero(numR))
|
||
{
|
||
Vector2 AtoB = B - A;
|
||
Vector2 CtoD = D - C;
|
||
|
||
float r_dot_r = Vector2.Dot(AtoB, AtoB);
|
||
|
||
// t0 = (q − p) · r / (r · r)
|
||
float t0 = Vector2.Dot((C - A), AtoB) / r_dot_r;
|
||
|
||
// t1 = (q + s − p) · r / (r · r) = t0 + s · r / (r · r)
|
||
float t1 = t0 + Vector2.Dot(CtoD, AtoB) / r_dot_r;
|
||
|
||
// do interval intersection
|
||
|
||
if(Vector2.Dot(CtoD, AtoB) < 0)
|
||
{
|
||
Swap!(t0, t1);
|
||
}
|
||
|
||
if(IntervalIntersection(t0, t1, 0, 1) case .Ok(let intersection))
|
||
{
|
||
return .Collinear(Line2D(A + intersection.Start * AtoB, A + intersection.End * AtoB));
|
||
}
|
||
else
|
||
{
|
||
return .CollinearNoIntersect;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return .Parallel;
|
||
}
|
||
}
|
||
|
||
return .None;
|
||
}
|
||
|
||
public static void TestIntersects()
|
||
{
|
||
|
||
{
|
||
Line2D line = .(.(0, 0), .(4, 0));
|
||
|
||
Line2D intersecting = .(.(2, 2), .(2, -2));
|
||
|
||
var result = line.Intersects(intersecting);
|
||
Vector2 intersection;
|
||
Runtime.Assert(result case .Intersection(out intersection));
|
||
Runtime.Assert(intersection == .(2, 0));
|
||
}
|
||
|
||
{
|
||
Line2D line = .(.(0, -1), .(5, 2));
|
||
|
||
Line2D intersecting = .(.(1, 3), .(4, -2));
|
||
|
||
var result = line.Intersects(intersecting);
|
||
Vector2 intersection;
|
||
Runtime.Assert(result case .Intersection(out intersection));
|
||
Runtime.Assert(intersection == .(2.5f, 0.5f));
|
||
}
|
||
|
||
{
|
||
Line2D line = .(.(-1, 0), .(1, 0));
|
||
|
||
Line2D collinear = .(.(2, 0), .( 4, 0));
|
||
|
||
var result = line.Intersects(collinear);
|
||
|
||
Runtime.Assert(result case .CollinearNoIntersect);
|
||
}
|
||
|
||
{
|
||
Line2D line = .(.(-1, 0), .(2, 0));
|
||
|
||
Line2D collinear = .(.(1, 0), .( 4, 0));
|
||
|
||
var result = line.Intersects(collinear);
|
||
|
||
Line2D intersection;
|
||
Runtime.Assert(result case .Collinear(out intersection));
|
||
|
||
Runtime.Assert(intersection.Start == .(1, 0));
|
||
Runtime.Assert(intersection.End == .(2, 0));
|
||
}
|
||
|
||
{
|
||
Line2D line = .(.(-1, 5), .(2, 5));
|
||
|
||
Line2D collinear = .(.(4, 5), .(1, 5));
|
||
|
||
var result = line.Intersects(collinear);
|
||
|
||
Line2D intersection;
|
||
Runtime.Assert(result case .Collinear(out intersection));
|
||
|
||
Runtime.Assert(intersection.Start == .(1, 5));
|
||
Runtime.Assert(intersection.End == .(2, 5));
|
||
}
|
||
}
|
||
|
||
/*
|
||
public bool Intersects(Line2D line)
|
||
{
|
||
float x1 = Start.X;
|
||
float x2 = End.X;
|
||
float x3 = line.Start.X;
|
||
float x4 = line.End.X;
|
||
|
||
float y1 = Start.Y;
|
||
float y2 = End.Y;
|
||
float y3 = line.Start.Y;
|
||
float y4 = line.End.Y;
|
||
|
||
float t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
|
||
|
||
float u = ((x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
|
||
|
||
return (0.0f <= t && t <= 1.0f && 0.0f <= u && u <= 1.0f);
|
||
}
|
||
*/
|
||
}
|
||
} |