Open In App

CSES Solution – Line Segment Intersection

Last Updated : 20 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

There are two line segments: the first goes through the points (x1,y1) and (x2,y2), and the second goes through the points (x3,y3) and (x4,y4).

Your task is to determine if the line segments intersect, i.e., they have at least one common point.

Example:

Input: points = {1, 1}, {5, 3}, {1, 2}, {4, 3}
Output: No

Input: points = {1, 1}, {5, 3}, {1, 1}, {4, 3}
Output: No

Approach:

  • The main idea is to use the concept of cross products to determine if the line segments intersect.
  • Calculate the cross products of the vectors AB and AC, and CD and AB.
  • Check if the cross products have different signs, If the signs of the cross products are different, it means that the line segments intersect.
  • Check if any of the cross products is zero, then check if the point C or D lies on the line segment AB or point A or B lies on the line segment CD. If so, the line segments intersect.
  • Return “YES” if the line segments intersect, and “NO” otherwise.

Steps-by-step approach:

  • Calculate the cross products of AB and CD, AB and DA, CD and AB, and CD and BA.
  • Check if any of the cross products are zero and if the corresponding points are midpoints.
    • Return true
  • Check if the signs of the cross products are different for AB and CD, and for CD and AB.
    • Return true
  • Otherwise, Return false

Below are the implementation of the above approach:

C++
#include <bits/stdc++.h>
using namespace std;

#define int long long
#define endl '\n'
#define Point complex<int>
#define X real()
#define Y imag()

// Function to calculate cross product of two vectors AB and AC
int crossProduct(Point A, Point B, Point C)
{
    Point AB = B - A; // Vector from A to B
    Point AC = C - A; // Vector from A to C
    return (conj(AB) * AC).Y; // Cross product of AB and AC
}

// Function to compare two points
bool comparePoints(const Point &a, const Point &b)
{
    return (a.X == b.X) ? (a.Y < b.Y) : (a.X < b.X);
}

// Function to check if point C lies between point A and B
bool isMidPoint(Point A, Point B, Point C)
{
    vector<Point> v = {A, B, C};
    sort(v.begin(), v.end(), comparePoints);
    return (v[1] == C);
}

// Function to get sign of a number
int sign(int x)
{
    return (x > 0) - (x < 0);
}

// Function to check if line segments AB and CD intersect
bool doIntersect(Point A, Point B, Point C, Point D)
{
    int crossProduct1 = crossProduct(A, B, C);
    int crossProduct2 = crossProduct(A, B, D);
    int crossProduct3 = crossProduct(C, D, A);
    int crossProduct4 = crossProduct(C, D, B);
    if (crossProduct1 == 0 && isMidPoint(A, B, C))
        return true;
    if (crossProduct2 == 0 && isMidPoint(A, B, D))
        return true;
    if (crossProduct3 == 0 && isMidPoint(C, D, A))
        return true;
    if (crossProduct4 == 0 && isMidPoint(C, D, B))
        return true;
    if (sign(crossProduct1) != sign(crossProduct2) && sign(crossProduct3) != sign(crossProduct4))
        return true;
    return false;
}

signed main()
{
    // Hardcoded input
    vector<vector<Point>> points = {
        {{1, 1}, {5, 3}, {1, 2}, {4, 3}}
    };

    for (auto& point : points) {
        Point A = point[0];
        Point B = point[1];
        Point C = point[2];
        Point D = point[3];
        cout << (doIntersect(A, B, C, D) ? "YES" : "NO") << endl;
    }

    return 0;
}
Java
/*code by flutterfly */
import java.util.*;

class Main {
    // Class to represent complex numbers
    static class Point {
        long x, y;

        Point(long x, long y) {
            this.x = x;
            this.y = y;
        }

        Point subtract(Point p) {
            return new Point(this.x - p.x, this.y - p.y);
        }

        long crossProduct(Point p) {
            return this.x * p.y - this.y * p.x;
        }
    }

    // Function to compare two points
    static class PointComparator implements Comparator<Point> {
        public int compare(Point a, Point b) {
            return (a.x == b.x) ? Long.compare(a.y, b.y) : Long.compare(a.x, b.x);
        }
    }

    // Function to check if point C lies between point A and B
    static boolean isMidPoint(Point a, Point b, Point c) {
        List<Point> points = Arrays.asList(a, b, c);
        points.sort(new PointComparator());
        return points.get(1).equals(c);
    }

    // Function to get sign of a number
    static int sign(long x) {
        return Long.compare(x, 0);
    }

    // Function to check if line segments AB and CD intersect
    static boolean doIntersect(Point a, Point b, Point c, Point d) {
        long crossProduct1 = a.subtract(c).crossProduct(b.subtract(c));
        long crossProduct2 = a.subtract(c).crossProduct(d.subtract(c));
        long crossProduct3 = c.subtract(a).crossProduct(b.subtract(a));
        long crossProduct4 = c.subtract(a).crossProduct(d.subtract(a));

        if (crossProduct1 == 0 && isMidPoint(a, b, c))
            return true;
        if (crossProduct2 == 0 && isMidPoint(a, b, d))
            return true;
        if (crossProduct3 == 0 && isMidPoint(c, d, a))
            return true;
        if (crossProduct4 == 0 && isMidPoint(c, d, b))
            return true;
        if (sign(crossProduct1) != sign(crossProduct2) && sign(crossProduct3) != sign(crossProduct4))
            return true;

        return false;
    }

    public static void main(String[] args) {
        // Hardcoded input
        List<List<Point>> points = new ArrayList<>();
        points.add(Arrays.asList(new Point(1, 1), new Point(5, 3), new Point(1, 2), new Point(4, 3)));

        for (List<Point> point : points) {
            Point A = point.get(0);
            Point B = point.get(1);
            Point C = point.get(2);
            Point D = point.get(3);
            System.out.println(doIntersect(A, B, C, D) ? "YES" : "NO");
        }
    }
}
C#
//code by flutterfly
using System;
using System.Collections.Generic;

class MainClass
{
    // Class to represent complex numbers
    class Point
    {
        public long x, y;

        public Point(long x, long y)
        {
            this.x = x;
            this.y = y;
        }

        public Point Subtract(Point p)
        {
            return new Point(this.x - p.x, this.y - p.y);
        }

        public long CrossProduct(Point p)
        {
            return this.x * p.y - this.y * p.x;
        }
    }

    // Function to compare two points
    class PointComparator : IComparer<Point>
    {
        public int Compare(Point a, Point b)
        {
            return (a.x == b.x) ? a.y.CompareTo(b.y) : a.x.CompareTo(b.x);
        }
    }

    // Function to check if point C lies between point A and B
    static bool IsMidPoint(Point a, Point b, Point c)
    {
        List<Point> points = new List<Point> { a, b, c };
        points.Sort(new PointComparator());
        return points[1].Equals(c);
    }

    // Function to get sign of a number
    static int Sign(long x)
    {
        return x.CompareTo(0);
    }

    // Function to check if line segments AB and CD intersect
    static bool DoIntersect(Point a, Point b, Point c, Point d)
    {
        long crossProduct1 = a.Subtract(c).CrossProduct(b.Subtract(c));
        long crossProduct2 = a.Subtract(c).CrossProduct(d.Subtract(c));
        long crossProduct3 = c.Subtract(a).CrossProduct(b.Subtract(a));
        long crossProduct4 = c.Subtract(a).CrossProduct(d.Subtract(a));

        if (crossProduct1 == 0 && IsMidPoint(a, b, c))
            return true;
        if (crossProduct2 == 0 && IsMidPoint(a, b, d))
            return true;
        if (crossProduct3 == 0 && IsMidPoint(c, d, a))
            return true;
        if (crossProduct4 == 0 && IsMidPoint(c, d, b))
            return true;
        if (Sign(crossProduct1) != Sign(crossProduct2) && Sign(crossProduct3) != Sign(crossProduct4))
            return true;

        return false;
    }

    public static void Main(string[] args)
    {
        // Hardcoded input
        List<List<Point>> points = new List<List<Point>>();
        points.Add(new List<Point> { new Point(1, 1), new Point(5, 3), new Point(1, 2), new Point(4, 3) });

        foreach (List<Point> point in points)
        {
            Point A = point[0];
            Point B = point[1];
            Point C = point[2];
            Point D = point[3];
            Console.WriteLine(DoIntersect(A, B, C, D) ? "YES" : "NO");
        }
    }
}
JavaScript
// Function to calculate cross product of two vectors AB and AC
function crossProduct(A, B, C) {
    let AB = { X: B.X - A.X, Y: B.Y - A.Y }; // Vector from A to B
    let AC = { X: C.X - A.X, Y: C.Y - A.Y }; // Vector from A to C
    return AB.X * AC.Y - AB.Y * AC.X; // Cross product of AB and AC
}

// Function to compare two points
function comparePoints(a, b) {
    return (a.X === b.X) ? (a.Y < b.Y) : (a.X < b.X);
}

// Function to check if point C lies between point A and B
function isMidPoint(A, B, C) {
    let v = [A, B, C];
    v.sort(comparePoints);
    return (v[1] === C);
}

// Function to get sign of a number
function sign(x) {
    return (x > 0) - (x < 0);
}

// Function to check if line segments AB and CD intersect
function doIntersect(A, B, C, D) {
    let crossProduct1 = crossProduct(A, B, C);
    let crossProduct2 = crossProduct(A, B, D);
    let crossProduct3 = crossProduct(C, D, A);
    let crossProduct4 = crossProduct(C, D, B);
    if (crossProduct1 === 0 && isMidPoint(A, B, C))
        return true;
    if (crossProduct2 === 0 && isMidPoint(A, B, D))
        return true;
    if (crossProduct3 === 0 && isMidPoint(C, D, A))
        return true;
    if (crossProduct4 === 0 && isMidPoint(C, D, B))
        return true;
    if (sign(crossProduct1) !== sign(crossProduct2) && sign(crossProduct3) !== sign(crossProduct4))
        return true;
    return false;
}

// Hardcoded input
let points = [
    [{ X: 1, Y: 1 }, { X: 5, Y: 3 }, { X: 1, Y: 2 }, { X: 4, Y: 3 }]
];

for (let point of points) {
    let A = point[0];
    let B = point[1];
    let C = point[2];
    let D = point[3];
    console.log(doIntersect(A, B, C, D) ? "YES" : "NO");
}
Python3
# code by flutterfly
import cmath

# Function to calculate cross product of two vectors AB and AC
def cross_product(A, B, C):
    AB = B - A  # Vector from A to B
    AC = C - A  # Vector from A to C
    return AB.conjugate() * AC  # Cross product of AB and AC

# Function to compare two points
def compare_points(a, b):
    return (a.real == b.real and a.imag < b.imag) or a.real < b.real

# Function to check if point C lies between point A and B
def is_mid_point(A, B, C):
    v = [A, B, C]
    v.sort(key=lambda x: (x.real, x.imag))
    return v[1] == C

# Function to get sign of a number
def sign(x):
    return (x > 0) - (x < 0)

# Function to check if line segments AB and CD intersect
def do_intersect(A, B, C, D):
    cross_product1 = cross_product(A, B, C)
    cross_product2 = cross_product(A, B, D)
    cross_product3 = cross_product(C, D, A)
    cross_product4 = cross_product(C, D, B)
    if cross_product1.imag == 0 and is_mid_point(A, B, C):
        return True
    if cross_product2.imag == 0 and is_mid_point(A, B, D):
        return True
    if cross_product3.imag == 0 and is_mid_point(C, D, A):
        return True
    if cross_product4.imag == 0 and is_mid_point(C, D, B):
        return True
    if sign(cross_product1.imag) != sign(cross_product2.imag) and sign(cross_product3.imag) != sign(cross_product4.imag):
        return True
    return False

# Hardcoded input
points = [
    [complex(1, 1), complex(5, 3), complex(1, 2), complex(4, 3)]
]

for point in points:
    A, B, C, D = point
    print("YES" if do_intersect(A, B, C, D) else "NO")

Output
NO




Time complexity: O(n log n).
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads