I am working on a geometric problem involving a line defined by:
- A midpoint (X,Y),
- A directional vector (Nx,Ny),
- An image of dimensions (width,height).
[![enter image description here][1]][1]
My goal is to compute the two points where this line intersects the borders of the image, defined by:
- $x_{start}$=0 (left border),
- $x_{end}$=width (right border),
- $y_{start}$= ? (left border),
- $y_{end}$= ? (right border).
Current Calculations
I use the following formulas to compute the intersections:
Left border (x=0):
- yleft=Y−XNx⋅Ny
If yleft is within the bounds of the image (0≤yleft≤height), I retain the point (0,yleft).
Right border (x=width):
- yright=Y+width−XNx⋅Ny
If yright is within the bounds of the image (0≤yright≤height), I retain the point (width,yright).
Top border (y=0y=0):
- xtop=X−YNy⋅Nx
If xtop is within the bounds of the image (0≤xtop≤width0≤xtop≤width), I retain the point (xtop,0)(xtop,0).
Bottom border (y=heighty=height):
- xbottom=X+height−YNy⋅Nx
If xbottom is within the bounds of the image (0≤xbottom≤width), I retain the point (xbottom,height).
Problem
Using the following input values:
- X=1000, Y=500,
- Nx=0.866 (cos(30∘)
- Ny=0.5 (sin(30∘)),
- width=1920
- height=1080,
I get the following result: Intersection points: [(134.0,0),(1920,1031.18)]
I expected the first point to lie exactly on the left border (x=0), but instead, the line intersects the top border (y=0) at x=134.0.
Code
import math def get_horizon_line(X, Y, Nx, Ny, width, height): """ Computes the two points where the horizon line intersects the image borders. Args: X (float): X-coordinate of the midpoint on the horizon line. Y (float): Y-coordinate of the midpoint on the horizon line. Nx (float): Cosine of the direction of the line. Ny (float): Sine of the direction of the line. width (int): Width of the image. height (int): Height of the image. Returns: list: [(x_start, y_start), (x_end, y_end)] Points where the line intersects the borders. """ intersections = [] # Intersection with the left border (x = 0) if Nx != 0: # Avoid division by zero y_left = Y - (X / Nx) * Ny if 0 <= y_left <= height: # Check if the intersection is within bounds intersections.append((0, y_left)) # Intersection with the right border (x = width) if Nx != 0: y_right = Y + ((width - X) / Nx) * Ny if 0 <= y_right <= height: intersections.append((width, y_right)) # Intersection with the top border (y = 0) if Ny != 0: x_top = X - (Y / Ny) * Nx if 0 <= x_top <= width: intersections.append((x_top, 0)) # Intersection with the bottom border (y = height) if Ny != 0: x_bottom = X + ((height - Y) / Ny) * Nx if 0 <= x_bottom <= width: intersections.append((x_bottom, height)) # Ensure exactly two points are returned: one for x = 0 and one for x = width if len(intersections) >= 2: intersections = sorted(intersections, key=lambda p: p[0]) # Sort by x-coordinate return [intersections[0], intersections[-1]] # Leftmost and rightmost points else: raise ValueError("Line does not intersect enough borders within the image.") # Example usage X = 1000 # Midpoint x-coordinate Y = 500 # Midpoint y-coordinate Nx = math.cos(math.radians(30)) # Directional cosine Ny = math.sin(math.radians(30)) # Directional sine width = 1920 height = 1080 points = get_horizon_line(X, Y, Nx, Ny, width, height) print(f"Points of intersection: {points}") Which returns:
Points of intersection: [(133.97459621556118, 0), (1920, 1031.1622476544555)] which is odd for 133.97 as I was expecting 0 ? [1]: https://i.sstatic.net/fzSHoY16.png