155 lines
3.3 KiB
C#
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();
|
|
}
|
|
|
|
|
|
|
|
}
|
|
} |