javageometryintersectionsquareline-segment

intersection between a line and square


I have a square in 2d space (width = height). The square is currently defined by two points: BottomLeft(X1,Y1) and TopRight(X2,Y2).

The square is axis-aligned, so finding the other two corners is as easy as (X1, Y2) and (X2, Y1).

I also have two points - one is always inside the square, and the other is definitely outside. They aren't necessarily at the centre of the square - they can be wherever. I know their coordinates too.

What I need is to find the intersection point between the line segment defined by these two points, and the side of the square. I also want to know which side of the square I intersected. What gives me trouble are cases where the line goes diagonally, and close to the corner of the square - so for example it can either intersect top or the side line.

The brute-force method is to try and calculate the intersections for each side of the square and check if it exists. It can be optimized by calculating where in relation to the square the second point lies, and discarding two lines (for example if both X and Y coordinates increase, there's no need to check bottom and left sides of the square).

I'm wondering if there's a better/faster solution to my problem? I'll be writing in Java


Solution

  • Let inside point is (x0, y0), outside point is (ox, oy)

    Represent line in parametric form

    enter image description here

    vx = ox - x0
    vy = oy - y0
    
    //equations:
    x = x0 + vx * t
    y = y0 + vy * t
    

    Now find potential border positions depending on direction:

    if vx > 0 then
       ex = x2
    else
       ex = x1
    
    if vy > 0 then
        ey = y2
    else
       ey = y1
    

    Check extra cases of horizontal/vertical line direction:

     if vx = 0 then
          return cx = x0,  cy = ey
    
     if vy = 0 then
          return cx = ex, cy = y0
    

    In general case find parameters of intersections with horizontal and vertical edge lines

     tx = (ex - x0) / vx
     ty = (ey - y0) / vy
    

    And get intersection for smaller parameter value

     if tx <= ty then //meet vertical edge first
         return cx = ex, cy = y0 + tx * vy
     else
        return  cx = x0 + ty * vx,  cy = ey