Skip to content

Commit da48fb8

Browse files
FireCoder-Npre-commit-ci[bot]cclauss
authored
Add files via upload (#11784)
* Add files via upload An algorithm to find intersection between 2 lines. * Added doctest to function * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed ruff issues * updating DIRECTORY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com> Co-authored-by: cclauss <cclauss@users.noreply.github.com>
1 parent b050e30 commit da48fb8

2 files changed

Lines changed: 157 additions & 0 deletions

File tree

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@
765765
* [Kth Lexicographic Permutation](maths/kth_lexicographic_permutation.py)
766766
* [Largest Of Very Large Numbers](maths/largest_of_very_large_numbers.py)
767767
* [Least Common Multiple](maths/least_common_multiple.py)
768+
* [Line Intersection](maths/line_intersection.py)
768769
* [Line Length](maths/line_length.py)
769770
* [Liouville Lambda](maths/liouville_lambda.py)
770771
* [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py)

maths/line_intersection.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Function to calculate determinant of a 2x2 matrix
2+
def determinant(m00: float, m01: float, m10: float, m11: float) -> float:
3+
"""
4+
Calculates the determinant of a 2x2 matrix:
5+
6+
| m00 m01 |
7+
| m10 m11 |
8+
9+
Args:
10+
m00 (float): Element in the first row, first column.
11+
m01 (float): Element in the first row, second column.
12+
m10 (float): Element in the second row, first column.
13+
m11 (float): Element in the second row, second column.
14+
15+
Returns:
16+
float: The determinant of the matrix.
17+
18+
Examples:
19+
# Determinant of the identity matrix (should be 1)
20+
>>> determinant(1, 0, 0, 1)
21+
1
22+
23+
# Determinant of a matrix with two equal rows (should be 0)
24+
>>> determinant(1, 2, 1, 2)
25+
0
26+
27+
# Determinant of a matrix with a negative determinant
28+
>>> determinant(1, 2, 3, 4)
29+
-2
30+
31+
# Determinant of a matrix with larger numbers
32+
>>> determinant(10, 20, 30, 40)
33+
-200
34+
"""
35+
return m00 * m11 - m10 * m01
36+
37+
38+
# Function to compute the line equation coefficients from two points
39+
def line_coefficients(p1: list[float] | tuple, p2: list[float] | tuple) -> tuple:
40+
"""
41+
Computes the coefficients A, B, C of the line equation Ax + By + C = 0
42+
from two points.
43+
44+
Args:
45+
p1 (List[float] | tuple): First point (x, y).
46+
p2 (List[float] | tuple): Second point (x, y).
47+
48+
Returns:
49+
tuple: Coefficients (A, B, C) of the line equation.
50+
51+
Examples:
52+
# Vertical line (x = constant)
53+
>>> line_coefficients([1, 0], [1, 2])
54+
(1, 0, 1)
55+
56+
# Horizontal line (y = constant)
57+
>>> line_coefficients([0, 1], [2, 1])
58+
(0.0, -1, 1.0)
59+
60+
# Diagonal line (positive slope)
61+
>>> line_coefficients([0, 0], [1, 1])
62+
(1.0, -1, 0.0)
63+
64+
# Diagonal line (negative slope)
65+
>>> line_coefficients([0, 1], [1, 0])
66+
(-1.0, -1, 1.0)
67+
"""
68+
69+
if p1[0] == p2[0]: # Vertical line
70+
return 1, 0, p1[0]
71+
else: # Non-vertical line
72+
a = (p2[1] - p1[1]) / (p2[0] - p1[0])
73+
b = -1
74+
c = p2[1] - a * p2[0]
75+
return a, b, c
76+
77+
78+
def segment_intersection(
79+
v1: list[float] | tuple,
80+
v2: list[float] | tuple,
81+
v1_prime: list[float] | tuple,
82+
v2_prime: list[float] | tuple,
83+
as_segments: bool = True,
84+
) -> list[float] | None:
85+
"""
86+
Finds the intersection point of two line segments or lines, if it exists.
87+
88+
Args:
89+
v1 (List[float] | tuple): First point of the first segment (x, y).
90+
v2 (List[float] | tuple): Second point of the first segment (x, y).
91+
v1_prime (List[float] | tuple): First point of the second segment (x, y).
92+
v2_prime (List[float] | tuple): Second point of the second segment (x, y).
93+
as_segments (bool):
94+
treat the inputs as line segments (True)
95+
or as infinite lines (False).
96+
97+
Returns:
98+
List[float] | None:
99+
Returns the intersection point [x, y] if existent, otherwise None.
100+
101+
References:
102+
Cramer's rule: https://en.wikipedia.org/wiki/Cramer%27s_rule
103+
104+
Examples:
105+
>>> segment_intersection([0, 0], [1, 1], [1, 0], [0, 1])
106+
[0.5, 0.5]
107+
108+
# No intersection
109+
>>> segment_intersection([0, 0], [1, 1], [2, 2], [3, 3]) is None
110+
True
111+
112+
# Parallel lines
113+
>>> segment_intersection([0, 0], [0, 1], [1, 0], [1, 1]) is None
114+
True
115+
116+
# Intersecting infinite lines
117+
>>> segment_intersection([0, 0], [1, 1], [1, 0], [0, 1], as_segments=False)
118+
[0.5, 0.5]
119+
120+
# Parallel infinite lines (ignoring segment boundaries)
121+
>>> segment_intersection([0, 0], [1, 1], [2, 2], [3, 3], False) is None
122+
True
123+
"""
124+
125+
# Compute line coefficients for the two segments/lines
126+
a, b, c = line_coefficients(v1, v2)
127+
a_prime, b_prime, c_prime = line_coefficients(v1_prime, v2_prime)
128+
129+
# Calculate the determinant (D) of the coefficient matrix
130+
d = determinant(a, b, a_prime, b_prime)
131+
132+
if d == 0:
133+
# If D == 0, the lines are parallel or coincident (no unique solution)
134+
return None
135+
136+
# Cramer's rule to solve for x and y
137+
dx = determinant(-c, b, -c_prime, b_prime)
138+
dy = determinant(a, -c, a_prime, -c_prime)
139+
140+
# Intersection point of the lines
141+
x, y = dx / d, dy / d
142+
143+
if as_segments:
144+
# Check if the intersection point lies within the bounds of both line segments
145+
if (
146+
min(v1[0], v2[0]) <= x <= max(v1[0], v2[0])
147+
and min(v1_prime[0], v2_prime[0]) <= x <= max(v1_prime[0], v2_prime[0])
148+
and min(v1[1], v2[1]) <= y <= max(v1[1], v2[1])
149+
and min(v1_prime[1], v2_prime[1]) <= y <= max(v1_prime[1], v2_prime[1])
150+
):
151+
return [x, y]
152+
153+
return None
154+
else:
155+
# Return the intersection point of the infinite lines
156+
return [x, y]

0 commit comments

Comments
 (0)