Skip to content

Add files via upload #11784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions maths/line_intersection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Function to calculate determinant of a 2x2 matrix
def determinant(a: float, b: float, c: float, d: float) -> float:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file maths/line_intersection.py, please provide doctest for the function determinant

Please provide descriptive name for the parameter: a

Please provide descriptive name for the parameter: b

Please provide descriptive name for the parameter: c

Please provide descriptive name for the parameter: d

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file maths/line_intersection.py, please provide doctest for the function determinant

Please provide descriptive name for the parameter: a

Please provide descriptive name for the parameter: b

Please provide descriptive name for the parameter: c

Please provide descriptive name for the parameter: d

"""
Calculates the determinant of a 2x2 matrix:

| a b |
| c d |

Args:
a, b, c, d (float): Elements of the 2x2 matrix.

Returns:
float: The determinant of the matrix.
"""
return a * d - c * b


# Function to compute the line equation coefficients from two points
def line_coefficients(p1: list[float] | tuple, p2: list[float] | tuple) -> tuple:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file maths/line_intersection.py, please provide doctest for the function line_coefficients

"""
Computes the coefficients A, B, C of the line equation Ax + By + C = 0

Check failure on line 21 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W291)

maths/line_intersection.py:21:75: W291 Trailing whitespace
from two points.

Args:
p1 (List[float] | tuple): First point (x, y).
p2 (List[float] | tuple): Second point (x, y).

Returns:
tuple: Coefficients (A, B, C) of the line equation.

Check failure on line 30 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

maths/line_intersection.py:30:1: W293 Blank line contains whitespace
Examples:
# Vertical line (x = constant)
>>> line_coefficients([1, 0], [1, 2])
(1, 0, 1)

# Horizontal line (y = constant)
>>> line_coefficients([0, 1], [2, 1])
(0.0, -1, 1)

# Diagonal line (positive slope)
>>> line_coefficients([0, 0], [1, 1])
(1.0, -1, 0)

# Diagonal line (negative slope)
>>> line_coefficients([0, 1], [1, 0])
(-1.0, -1, 1)
"""

Check failure on line 48 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W293)

maths/line_intersection.py:48:1: W293 Blank line contains whitespace
if p1[0] == p2[0]: # Vertical line
return 1, 0, p1[0]
else: # Non-vertical line
a = (p2[1] - p1[1]) / (p2[0] - p1[0])
b = -1
c = p2[1] - a * p2[0]
return a, b, c


def segment_intersection(
v1: list[float] | tuple,
v2: list[float] | tuple,
v1_prime: list[float] | tuple,
v2_prime: list[float] | tuple,
as_segments: bool = True,
) -> list[float] | None:
"""
Finds the intersection point of two line segments or lines, if it exists.

Args:
v1 (List[float] | tuple): First point of the first segment (x, y).
v2 (List[float] | tuple): Second point of the first segment (x, y).
v1_prime (List[float] | tuple): First point of the second segment (x, y).
v2_prime (List[float] | tuple): Second point of the second segment (x, y).
as_segments (bool): treat the inputs as line segments (True) or as infinite lines (False).

Check failure on line 73 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

maths/line_intersection.py:73:89: E501 Line too long (99 > 88)

Returns:
List[float] | None:
Returns the intersection point [x, y] if the segments/lines intersect, otherwise None.

Check failure on line 77 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

maths/line_intersection.py:77:89: E501 Line too long (98 > 88)

References:
Cramer's rule: https://en.wikipedia.org/wiki/Cramer%27s_rule

Examples:
>>> segment_intersection([0, 0], [1, 1], [1, 0], [0, 1])
[0.5, 0.5]

# No intersection
>>> segment_intersection([0, 0], [1, 1], [2, 2], [3, 3]) is None
True

# Parallel lines
>>> segment_intersection([0, 0], [0, 1], [1, 0], [1, 1]) is None
True

# Parallel infinite lines (ignoring segment boundaries)
>>> segment_intersection([0, 0], [1, 1], [2, 2], [3, 3], as_segments=False) is None

Check failure on line 95 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

maths/line_intersection.py:95:89: E501 Line too long (91 > 88)
True

# Intersecting infinite lines
>>> segment_intersection([0, 0], [1, 1], [1, 0], [0, 1], as_segments=False)
[0.5, 0.5]
"""

# Compute line coefficients for the two segments/lines
a, b, c = line_coefficients(v1, v2)
a_prime, b_prime, c_prime = line_coefficients(v1_prime, v2_prime)

# Calculate the determinant (D) of the coefficient matrix
d = determinant(a, b, a_prime, b_prime)

if d == 0:
# If D == 0, the lines are parallel or coincident (no unique solution)
return None

# Cramer's rule to solve for x and y
dx = determinant(-c, b, -c_prime, b_prime)
dy = determinant(a, -c, a_prime, -c_prime)

# Intersection point of the lines
x, y = dx / d, dy / d

if as_segments:
# Check if the intersection point lies within the bounds of both line segments
if (
min(v1[0], v2[0]) <= x <= max(v1[0], v2[0])
and min(v1_prime[0], v2_prime[0]) <= x <= max(v1_prime[0], v2_prime[0])
and min(v1[1], v2[1]) <= y <= max(v1[1], v2[1])
and min(v1_prime[1], v2_prime[1]) <= y <= max(v1_prime[1], v2_prime[1])
):
return [x, y]

return None
else:
# Return the intersection point of the infinite lines
return [x, y]
Loading