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(); } } }