/// <summary> /// Calculates the squared shortest distance between a line segment and point. /// </summary> /// <param name="line">The line segment involved in the calculation.</param> /// <param name="point">The point involved in the calculation.</param> /// <returns>The shortest squared distance between the given line segment and point.</returns> public static double CalculateSquaredDistanceFromLineToPoint(DoubleLine line, DoublePoint point) { // Calculate the projection of the given point onto the given line var numerator = (point.X - line._start.X) * (line._end.X - line._start.X) + (point.Y - line._start.Y) * (line._end.Y - line._start.Y); var denominator = DoublePoint.CalculateSquaredDistance(line._start, line._end); var projection = numerator / denominator; // If the projection is beyond the segment, return the distance to // either the start or end point on the line segment (whichever // happens to be the shortest) if (projection < 0 || projection > 1) { var distanceToStart = DoublePoint.CalculateSquaredDistance(line._start, point); var distanceToEnd = DoublePoint.CalculateSquaredDistance(line._end, point); return(distanceToStart < distanceToEnd ? distanceToStart : distanceToEnd); } // Create a point on the line segment from which to measure the distance to the given point var segmentPoint = new DoublePoint(line._start.X + projection * (line._end.X - line._start.X), line._start.Y + projection * (line._end.Y - line._start.Y)); // Measure the distance from this point on the segment to the given point return(DoublePoint.CalculateSquaredDistance(segmentPoint, point)); }
#pragma warning restore 1591 #region Static Methods /// <summary> /// Calculates the midpoint of the given line segment. /// </summary> /// <param name="line">The line segment of which to find the midpoint.</param> /// <returns>The midpoint of the given line segment.</returns> public static DoublePoint CalculateMidpoint(DoubleLine line) { // Half the sum of both the start and end X and Y coordinates var x = (line._start.X + line._end.X) / 2; var y = (line._start.Y + line._end.Y) / 2; // Return a new point based on those halved coordinates return(new DoublePoint(x, y)); }
/// <summary> /// Calculates the closest point on the line segment to the given point. /// </summary> /// <param name="line">The line segment on which to find the closest point.</param> /// <param name="point">The source point.</param> /// <returns>The closest point on the line segment.</returns> public static DoublePoint CalculateLineSegmentClosestPoint(DoubleLine line, DoublePoint point) { // Calculate the projection of the given point onto the given line var numerator = (point.X - line._start.X) * (line._end.X - line._start.X) + (point.Y - line._start.Y) * (line._end.Y - line._start.Y); var denominator = DoublePoint.CalculateSquaredDistance(line._start, line._end); var projection = numerator / denominator; // Return the intersection point on the line segment return(new DoublePoint(line._start.X + projection * (line._end.X - line._start.X), line._start.Y + projection * (line._end.Y - line._start.Y))); }
/// <summary> /// Calculates the intersection between two line segments. /// </summary> /// <param name="a">The first line segment.</param> /// <param name="b">The segment line segment.</param> /// <param name="intersectionFound">Whether or not the lines intersect.</param> /// <returns>The point of intersection between the two given line segments.</returns> public static DoublePoint CalculateLineIntersection(DoubleLine a, DoubleLine b, out bool intersectionFound) { // Calculate the determinant's denominator var denominator = (a._start.X - a._end.X) * (b._start.Y - b._end.Y) - (a._start.Y - a._end.Y) * (b._start.X - b._end.X); if (denominator != 0) { // Calculate the determinants var xDeterminant = ((a._start.X * a._end.Y - a._start.Y * a._end.X) * (b._start.X - b._end.X) - (a._start.X - a._end.X) * (b._start.X * b._end.Y - b._start.Y * b._end.X)) / denominator; var yDeterminant = ((a._start.X * a._end.Y - a._start.Y * a._end.X) * (b._start.Y - b._end.Y) - (a._start.Y - a._end.Y) * (b._start.X * b._end.Y - b._start.Y * b._end.X)) / denominator; // Ensure that the intersection point actually lies within both line segments if (MathUtils.AlmostGreaterThanOrEqual(xDeterminant, Math.Min(a._start.X, a._end.X)) && MathUtils.AlmostLessThanOrEqual(xDeterminant, Math.Max(a._start.X, a._end.X)) && MathUtils.AlmostGreaterThanOrEqual(xDeterminant, Math.Min(b._start.X, b._end.X)) && MathUtils.AlmostLessThanOrEqual(xDeterminant, Math.Max(b._start.X, b._end.X)) && MathUtils.AlmostGreaterThanOrEqual(yDeterminant, Math.Min(a._start.Y, a._end.Y)) && MathUtils.AlmostLessThanOrEqual(yDeterminant, Math.Max(a._start.Y, a._end.Y)) && MathUtils.AlmostGreaterThanOrEqual(yDeterminant, Math.Min(b._start.Y, b._end.Y)) && MathUtils.AlmostLessThanOrEqual(yDeterminant, Math.Max(b._start.Y, b._end.Y)) ) { intersectionFound = true; return(new DoublePoint(xDeterminant, yDeterminant)); } } // If the denominator came out to 0 or the point isn't within both // line segments, then the lines don't intersect intersectionFound = false; return(new DoublePoint(0, 0)); }
/// <summary> /// Calculates the length of the given line segment. /// </summary> /// <param name="line">The line segment to measure.</param> /// <returns>The length of the line segment.</returns> public static double CalculateLineSegmentLength(DoubleLine line) { return(DoublePoint.CalculateEuclideanDistance(line._start, line._end)); }
/// <summary> /// Calculates the squared length of the given line segment. /// </summary> /// <param name="line">The line segment to measure.</param> /// <returns>The squared length of the line segment.</returns> public static double CalculateSquaredLineSegmentLength(DoubleLine line) { return(DoublePoint.CalculateSquaredDistance(line._start, line._end)); }
/// <summary> /// Calculates the euclidean shortest distance between a line segment and point. /// </summary> /// <param name="line">The line segment involved in the calculation.</param> /// <param name="point">The point involved in the calculation.</param> /// <returns>The shortest euclidean distance between the given line segment and point.</returns> public static double CalculateEuclideanDistanceFromLineToPoint(DoubleLine line, DoublePoint point) { return(Math.Sqrt(CalculateSquaredDistanceFromLineToPoint(line, point))); }