GeometriCS/intersections/IntersectionLine2ToLineSegment2.cs

106 lines
3.5 KiB
C#
Raw Permalink Normal View History

namespace GeometriCS
{
/// <summary>
/// Intersection between a line and a line segment. Double precision.
/// </summary>
public class IntersectionLine2ToLineSegment2d
{
/// <summary>
/// Possible statuses the intersection can be.
/// </summary>
public enum Statuses
{
/// <summary>
/// Intersection is valid.
/// </summary>
SUCCESS,
/// <summary>
/// The two lines are parallel.
/// </summary>
PARALLEL,
/// <summary>
/// The line segment is colinear with the line.
/// </summary>
COLINEAR,
/// <summary>
/// The intersection would happen if the intersectors were unbounded, but not inside the bounds.
/// </summary>
OUTOFBOUNDS,
}
/// <summary>
/// The intersecting line.
/// </summary>
public Line2d Line { get; }
/// <summary>
/// The intersecting line segment.
/// </summary>
public LineSegment2d LineSegment { get; }
/// <summary>
/// Status of the intersection.
/// </summary>
public Statuses Status { get; }
/// <summary>
/// The point of the intersection between the line and line segment.
/// </summary>
public Vector2d? Result { get; }
/// <summary>
/// Constructor for Line2d to LinearSegment2d intersection.
/// </summary>
/// <param name="line">The intersecting line.</param>
/// <param name="lineSegment">The intersecting lineSegment.</param>
public IntersectionLine2ToLineSegment2d(Line2d line, LineSegment2d lineSegment)
{
Line = line;
LineSegment = lineSegment;
// Construct line coefficients for the linesegment
(double segment_A, double segment_B, double segment_C) =
Utils.Line2CoefficientsFromTwoPoints(lineSegment.StartPoint, lineSegment.EndPoint);
// Check if lines are parallel
// TODO: Check what happens if coeff_B == 0
// TODO: Find a non-retarded way to put this into a function so
// that it can be reused by all the 2d linear intersections.
if (Utils.DoubleEquals(line.Coeff_A / line.Coeff_B, segment_A / segment_B))
{
// Null result
Result = null;
// Check if lines are coincidental
if (Utils.DoubleEquals(line.Coeff_A / segment_A, line.Coeff_B / segment_B) &&
Utils.DoubleEquals(line.Coeff_A / segment_A, line.Coeff_C / segment_C))
{
Status = Statuses.COLINEAR;
}
else
{
Status = Statuses.PARALLEL;
}
return;
}
// Perform the intersection calculation
double divisor = line.Coeff_A * segment_B - segment_A * line.Coeff_B;
double x0 = (line.Coeff_B * segment_C - segment_B * line.Coeff_C) / divisor;
double y0 = (line.Coeff_C * segment_A - segment_C * line.Coeff_A) / divisor;
Result = new Vector2d(x0, y0);
// Check if result is inside of the segment.
if (lineSegment.Extents.Contains((Vector2d)Result))
{
Status = Statuses.SUCCESS;
}
else
{
Status = Statuses.OUTOFBOUNDS;
}
}
}
}