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 1 commit
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
116 changes: 116 additions & 0 deletions maths/line_intersection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# 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
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.
"""
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 55 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

maths/line_intersection.py:55: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 59 in maths/line_intersection.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

maths/line_intersection.py:59: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 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 (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