Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Computing Intersection Point of Two Line Segments

Tech May 13 2

1. Mathematical Foundation

Given two line segments defined by endpoints A(x1, y1), B(x2, y2) and C(x3, y3), D(x4, y4), we first treat each segment as an infinite line. The intersection of the two lines can be computed by solving the linear equations of the lines. If the intersection lies within the bounding ranges of both segments, the segments intersect.

Line Equation in Slope‑Intercept Form

y = m1 * x + b1   for AB
y = m2 * x + b2   for CD

where

m1 = (y2 - y1) / (x2 - x1)    (if x2 ≠ x1)
b1 = y1 - m1 * x1

m2 = (y4 - y3) / (x4 - x3)
b2 = y3 - m2 * x3

If the lines are not parallel (m1 ≠ m2), the intersection coordinates are:

x0 = (b2 - b1) / (m1 - m2)
y0 = m1 * x0 + b1

For vertical lines (x constant), the slope is infinite and this approach fails. A more robust method uses the general line equation: a*x + b*y + c = 0.

General Linear Equation Approach

From two points (x1, y1) and (x2, y2), the coefficients are:

a = y2 - y1
b = x1 - x2
c = (x2 - x1) * y1 - (y2 - y1) * x1

The intersection (x0, y0) of two lines a1*x + b1*y + c1 = 0 and a2*x + b2*y + c2 = 0 is found using Cramer’s rule:

det = a1 * b2 - a2 * b1
x0 = (b1 * c2 - b2 * c1) / det
y0 = (c1 * a2 - c2 * a1) / det

If det = 0 the lines are parallel (including collinear).

2. Validating Segment Intersection

Once the intersection (x0, y0) is obtained, it lies on the segment if and only if:

(x0 - x1)*(x0 - x2) ≤ 0  AND  (x0 - x3)*(x0 - x4) ≤ 0
(y0 - y1)*(y0 - y2) ≤ 0  AND  (y0 - y3)*(y0 - y4) ≤ 0

Additionally, degenerate cases must be handled:

  • If all four endpoints coincide → the segments are a single point.
  • If one segment is a single point (start == end), check if that point lies on the other segment.
  • If both segments are single points, they intersect only if they are the same point.

3. Java Implementation

The following Java class implements a clean, vector‑based method that avoids divition by zero and handles all common cases.

import java.awt.geom.Point2D;

public class SegmentIntersection {

    /**
     * Checks if two line segments intersect and computes the intersection point.
     *
     * @param p1 segment1 start
     * @param p2 segment1 end
     * @param p3 segment2 start
     * @param p4 segment2 end
     * @return IntersectionResult containing status and intersection point (if any)
     */
    public static IntersectionResult compute(Point2D p1, Point2D p2,
                                              Point2D p3, Point2D p4) {
        double x1 = p1.getX(), y1 = p1.getY();
        double x2 = p2.getX(), y2 = p2.getY();
        double x3 = p3.getX(), y3 = p3.getY();
        double x4 = p4.getX(), y4 = p4.getY();

        // Check if any segment is a point
        boolean seg1IsPoint = (x1 == x2 && y1 == y2);
        boolean seg2IsPoint = (x3 == x4 && y3 == y4);

        if (seg1IsPoint && seg2IsPoint) {
            if (x1 == x3 && y1 == y3) {
                return new IntersectionResult(true, new Point2D.Double(x1, y1), 
                                             "Both segments are the same point");
            }
            return new IntersectionResult(false, null, "Two different points");
        }

        // Compute coefficients of the infinite lines
        double a1 = y2 - y1, b1 = x1 - x2, c1 = (x2 - x1) * y1 - (y2 - y1) * x1;
        double a2 = y4 - y3, b2 = x3 - x4, c2 = (x4 - x3) * y3 - (y4 - y3) * x3;

        double det = a1 * b2 - a2 * b1;

        if (Math.abs(det) < 1e-12) { // parallel (including collinear)
            // Additional check for collinear overlapping segments can be added
            return new IntersectionResult(false, null, "Segments are parallel or collinear");
        }

        // Intersection of infinite lines
        double x0 = (b1 * c2 - b2 * c1) / det;
        double y0 = (c1 * a2 - c2 * a1) / det;

        // Verify if intersection lies within both segments
        boolean onSeg1 = isPointOnSegment(x0, y0, x1, y1, x2, y2);
        boolean onSeg2 = isPointOnSegment(x0, y0, x3, y3, x4, y4);

        if (onSeg1 && onSeg2) {
            return new IntersectionResult(true, new Point2D.Double(x0, y0), 
                                         "Segments intersect");
        } else {
            return new IntersectionResult(false, null, 
                                         "Lines intersect but not within segments");
        }
    }

    private static boolean isPointOnSegment(double px, double py,
                                             double sx, double sy,
                                             double ex, double ey) {
        // Check bounding box (using tolerance for floating-point)
        double eps = 1e-12;
        boolean insideX = (px - sx) * (px - ex) <= eps;
        boolean insideY = (py - sy) * (py - ey) <= eps;
        return insideX && insideY;
    }

    // Helper class to hold result
    public static class IntersectionResult {
        private final boolean intersects;
        private final Point2D point;
        private final String description;

        public IntersectionResult(boolean intersects, Point2D point, String desc) {
            this.intersects = intersects;
            this.point = point;
            this.description = desc;
        }

        public boolean intersects() { return intersects; }
        public Point2D getPoint() { return point; }
        public String getDescription() { return description; }
    }

    // Example usage
    public static void main(String[] args) {
        Point2D a = new Point2D.Double(10, 20);
        Point2D b = new Point2D.Double(100, 200);
        Point2D c = new Point2D.Double(50, 20);
        Point2D d = new Point2D.Double(20, 100);

        IntersectionResult result = compute(a, b, c, d);
        System.out.println(result.getDescription());
        if (result.intersects()) {
            System.out.printf("Intersection at (%.2f, %.2f)%n",
                              result.getPoint().getX(), result.getPoint().getY());
        }
    }
}

4. Output Verification

For the example points (10,20)–(100,200) and (50,20)–(20,100), the program outputs:

Segments intersect
Intersection at (32.86, 65.71)

The same result is obtained with the general equation method.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.