0

This python code finds the intersection for lines and I have modified it for handling colinear lines so it returns the intersection of 2 lines when they are collinear.

enter image description here

How to handle cases when they are overlapping in that case it should not return any point of intersection.

enter image description here

The output for this comes

(2,0)

But it should not return an intersection as both of the 2 lines are overlapped.

Input

line1 = ((0, 0), (2, 0))
line2 = ((1, 0), (2, 0))
 

Code

def line_intersection(line1, line2):
    x1, y1 = line1[0]
    x2, y2 = line1[1]
    x3, y3 = line2[0]
    x4, y4 = line2[1]

    # Check if the lines are collinear
    if (y2 - y1) * (x4 - x3) == (y4 - y3) * (x2 - x1):
        # Check if they have a common endpoint
        if (x1, y1) == (x3, y3) or (x1, y1) == (x4, y4) or (x2, y2) == (x3, y3) or (x2, y2) == (x4, y4):
            return (x1, y1) if (x1, y1) == (x3, y3) or (x1, y1) == (x4, y4) else (x2, y2)
        else:
            # Return "overlapping" if the lines overlap
            if max(x1, x2) >= min(x3, x4) and min(x1, x2) <= max(x3, x4) and max(y1, y2) >= min(y3, y4) and min(y1, y2) <= max(y3, y4):
                return "overlapping"
            else:
                return None

    def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

    xdiff = (x1 - x3, x2 - x4)
    ydiff = (y1 - y3, y2 - y4)

    div = det(xdiff, ydiff)
    if div == 0:
        return None
    d = (det((x1, y1), (x2, y2)), det((x3, y3), (x4, y4)))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div
    point = (x, y)

    # Check if the intersection point is on both lines
    if (x >= min(x1, x2) and x <= max(x1, x2)) and (y >= min(y1, y2) and y <= max(y1, y2)) and (x >= min(x3, x4) and x <= max(x3, x4)) and (y >= min(y3, y4) and y <= max(y3, y4)):
        return point
    else:
        return None
amit
  • 51
  • 5
  • It is returning (2,0) in your "Check if they have a common endpoint", because the lines DO have a common endpoint. – Tim Roberts Feb 04 '23 at 23:51

1 Answers1

0

Your method of vector differences makes it very hard to precisely dectect colinearity or overlapping lines.

I think it would be much easier if you used the angles of the directing vectors to detect colinearity (this way is also better to avoid aprox. erors in comparisons).

import math

def get_angle(vector):

    #if vector lenght == 0
    if vector[0] == vector[1] == 0:
        return None

    angle = math.atan(vector[0]/vector[1]) if not vector[1] == 0 else math.pi/2 if vector[0] > 0 else -math.pi/2
    while angle < 0:
        angle = angle+(math.pi)
    return angle
    

def similar_angle(angle1, angle2):
    if angle1 == None or angle2 == None:
        return True
    return abs(angle1 - angle2) < 0.0001


x1, y1 = 0,0
x2, y2 = 1,1

x3, y3 = 0,1
x4, y4 = 1,2


#direction vectors of both lines
v12 = (x2-x1, y2-y1)
v34 = (x4-x3, y4-y3)


#angles of each vector
vs = [v12, v34]
angles = list()
for v in vs:
    angle = get_angle(v)
    angles.append(angle)


#colinearity
if abs(angles[0] - angles[1]) < 0.0001:
    print('colinear')

    condition_1 = similar_angle( get_angle( (x4-x1, y4-y1) ), get_angle( (x3-x1, y3-y1) ) )
    condition_2 = similar_angle( get_angle( (x4-x1, y4-y1) ), get_angle( (x4-x2, y4-y2) ) )

    #overlapped
    if condition_1 and condition_2:
        print('overlapped')

else:
    print('not colinear')

Thierry Lathuille
  • 23,663
  • 10
  • 44
  • 50