Coverage for pyguymer3/intersection.py: 66%
29 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def intersection(
5 p1,
6 p2,
7 p3,
8 p4,
9 /,
10):
11 """
12 This function finds the intersection of two line segments (defined by four
13 points).
14 """
16 # Import special modules ...
17 try:
18 import numpy
19 except:
20 raise Exception("\"numpy\" is not installed; run \"pip install --user numpy\"") from None
22 # Catch simple misses ...
23 if max(p1[0], p2[0]) < min(p3[0], p4[0]):
24 # NOTE: line segment #1 is left of line segment #2.
25 return False
26 if min(p1[0], p2[0]) > max(p3[0], p4[0]):
27 # NOTE: line segment #1 is right of line segment #2.
28 return False
29 if max(p1[1], p2[1]) < min(p3[1], p4[1]):
30 # NOTE: line segment #1 is below line segment #2.
31 return False
32 if min(p1[1], p2[1]) > max(p3[1], p4[1]):
33 # NOTE: line segment #1 is above line segment #2.
34 return False
36 # Find gradients of the two lines ...
37 m1 = (p2[1] - p1[1]) / (p2[0] - p1[0])
38 m2 = (p4[1] - p3[1]) / (p4[0] - p3[0])
40 # Find intercepts of the two lines ...
41 c1 = p1[1] - m1 * p1[0]
42 c2 = p3[1] - m2 * p3[0]
44 # Assemble matrices ...
45 a = numpy.array([[-m1, 1.0], [-m2, 1.0]])
46 b = numpy.array([c1, c2])
48 # Solve two linear equations ...
49 p5 = numpy.linalg.solve(a, b)
51 # Catch complex misses ...
52 if not min(p1[0], p2[0]) <= p5[0] <= max(p1[0], p2[0]):
53 # NOTE: intersection is either left or right of line segment #1.
54 return False
55 if not min(p1[1], p2[1]) <= p5[1] <= max(p1[1], p2[1]):
56 # NOTE: intersection is either above or below line segment #1.
57 return False
58 if not min(p3[0], p4[0]) <= p5[0] <= max(p3[0], p4[0]):
59 # NOTE: intersection is either left or right of line segment #2.
60 return False
61 if not min(p3[1], p4[1]) <= p5[1] <= max(p3[1], p4[1]):
62 # NOTE: intersection is either above or below line segment #2.
63 return False
65 # Return answer ...
66 return p5