rj-action-library/Runtime/Math/Geometry/Line2.cs

155 lines
3.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
namespace Rokojori
{
public class Line2
{
public Vector2 start = Vector2.Zero;
public Vector2 end = Vector2.Zero;
public Line2( Vector2 start, Vector2 end )
{
this.start = start;
this.end = end;
}
public Line2(){}
public float A{ get { return end.Y - start.Y; } }
public float B{ get { return start.X - end.X; } }
public float C{ get { return A * start.X + B * start.Y; } }
public Vector2 direction { get { return end - start; } }
public Vector2 reverseDirection { get { return start - end; } }
public float angle
{
get {
var lineDirection = direction;
return Mathf.Atan2( lineDirection.Y, lineDirection.X );
}
}
public float reverseAngle
{
get {
var lineDirection = reverseDirection;
return Mathf.Atan2( lineDirection.Y, lineDirection.X );
}
}
public Vector2? InfiniteIntersectionOf( Line2 line2 )
{
var A1 = A;
var B1 = B;
var A2 = line2.A;
var B2 = line2.B;
var determinant = A1 * B2 - A2 * B1;
if ( Mathf.Abs( determinant ) < Mathf.Epsilon )
{
return null;
}
var inverseDeterminant = 1f / determinant;
var C1 = A1 * start.X + B1 * start.Y;
var C2 = A2 * line2.start.X + B2 * line2.start.Y;
var x = ( B2 * C1 - B1 * C2 ) * inverseDeterminant;
var y = ( A1 * C2 - A2 * C1 ) * inverseDeterminant;
return new Vector2( x, y );
}
public Vector2? IntersectionOf( Line2 other )
{
var possibleIntersection = InfiniteIntersectionOf( other );
if ( possibleIntersection == null )
{
return null;
}
var point = (Vector2) possibleIntersection;
if ( ! IsValueInRange( point.X, start.X, end.X ) )
{
return null;
}
if ( ! IsValueInRange( point.Y, start.Y, end.Y ) )
{
return null;
}
if ( ! IsValueInRange( point.X, other.start.X, other.end.X ) )
{
return null;
}
if ( ! IsValueInRange( point.Y, other.start.Y, other.end.Y ) )
{
return null;
}
return point;
}
public bool IntersectsWith( Line2 other )
{
return IntersectionOf( other ) != null;
}
bool IsValueInRange( float value, float start, float end )
{
var min = Mathf.Min( start, end );
var max = Mathf.Max( start, end );
return min <= value && value <= max;
}
public Vector2 GetPointAtParameter( float t )
{
return start + direction * t;
}
public Vector2 ClosestPointToPoint( Vector2 point )
{
var parameter = MathX.Clamp01( ClostestParameterToPoint( point ) );
return GetPointAtParameter( parameter );
}
public float ClostestParameterToPoint( Vector2 point )
{
var startP = point - start;
var startEnd = end - start;
var startEnd2 = Math2D.Dot( startEnd, startEnd );
var startEnd_startP = Math2D.Dot( startEnd, startP );
if ( startEnd2 == 0 )
{
return 0;
}
var t = startEnd_startP / startEnd2;
return t;
}
public float DistanceToPoint( Vector2 point )
{
return ( point - ClosestPointToPoint( point ) ).Length();
}
}
}