Search code examples
algorithmgeometrystarling-frameworkcartesian-coordinates

Fastest algorithm for all whole lat/lng intersections in a rotated ellipse?


I'm working on a tile engine for a 2.5D game with parallel (but rotatable) projection. Tiles are flat quads having their vertices adjusted and placements set based on camera position and x/y rotation. There is no yaw (z). Writing the engine in Starling.

The camera's visible area can be described as the grid area that falls within an arbitrarily rotated and arbitrarily tall ellipse of a fixed width.

What I'd like to do now is get a list of the tiles which fall within the screen space, prior to having to project them and without having to test each coordinate set against the zoom radius / sin / cos. This can be a dirty set as long as it's larger than the radius. But I'm looking for the least dirty and most optimized solution.


Solution

  • If I understand correctly what you want to do, this is similar to a filling problem.

    You overlay a rectangular grid over the ellipse, and you want to list the tiles that have at least a corner inside the ellipse. With appropriate scaling, this is the same as scanfilling the ellipse.

    Put the ellipse in its implicit form, ax² + 2bxy + cy² + 2dx + 2ey + f = 0, with coordinates scaled/translated so that the grid points fall at integer coordinates. You first determine the useful range of y values. Then for every scanline, you determine the extreme values of x.

    Let y be fixed, you have a second degree equation in x: ax² + 2(by + d)x + (cy² + 2ey + f) = 0.

    Its discriminant is (by+d)- a(cy²+2ey+f) = (b²-ac)y² + 2(bd-ae)y + (d²-af).

    Solving this second degree equation in y gives you the range of y values; take the ceiling of the smallest and the floor of the largest.

    Then for every integer in this range, solve for x and you'll get the horizontal range.

    [Note that I am using discriminant B²-AC for an equation in the form At² + 2Bt + C= 0.]