mapbox/tilebelt

bbox with lat 0

morganherlocker opened this issue · 8 comments

Wacky results being returned when bbox lat is 0:

http://requirebin.com/?gist=9220fab6e4d2a5e5ac67

More wacky results:

> var tb = require('tilebelt')
undefined
> tb.bboxToTile([ -10, -10, 10, 10 ])
[ 2028179000, -2027568643, 0 ]
> tb.bboxToTile([ -10, 1, 10, 10 ])
[ 2028179000, 2135552577, 0 ]
> tb.bboxToTile([ 1, -10, 10, 10 ])
[ -2135553184, -2027568643, 0 ]
> tb.bboxToTile([ 1, 1, 10, 10 ])
[ -16, 15, 5 ]
> tb.bboxToTile([ 1, 0, 10, 10 ])
[ -2135553184, -2147483648, 0 ]
> tb.bboxToTile([ 1, 0, 10, 10 ])
[ -2135553184, -2147483648, 0 ]

Seems to occur when your bbox crosses lat or lng = 0

The issue is specifically in calculating the zoom from the bbox

https://github.com/mapbox/tilebelt/blob/master/index.js#L140-L151

When it crosses the line, the z zeroes out, which messes up the z/y calculations.

Oops, yes, this is a bug in my code. The problem is that if the tile is z0, the >> (32 - z) shift is undefined because it's shifting all the bits away. The C code needs to be

    if (*z == 0) {
            *x = *y = 0;
    } else {
            *x = x1 >> (32 - *z);
            *y = y1 >> (32 - *z);
    }

instead.

And in Javascript it needs to be >>> instead of >> so that it doesn't sign-extend 1s from a negative x or y into the bits at the top.

@ericfischer with this in place I still see somewhat-unexpected results depending on which side of a bbox touches the equator/prime meridian:

> tb.bboxToTile([0, 1, 10, 10])
[ -16, 15, 5 ]
> tb.bboxToTile([-10, 1, 0, 10])
[ 0, 0, 0 ]
> tb.bboxToTile([1, 0, 10, 10])
[ 0, 0, 0 ]
> tb.bboxToTile([1, -10, 10, 0])
[ -16, -16, 5 ]

@rclark I don't think your change has the >> to >>> fix. That at least fixes the -16.

bboxToTile([0, 1, 10, 10])
[16, 15, 5]
bboxToTile([-10, 1, 0, 10])
[0, 0, 0]
bboxToTile([1, 0, 10, 10])
[0, 0, 0]
bboxToTile([1, -10, 10, 0])
[16, 16, 5]

The difference by quadrant is because 0° is 0x8000000, not 0x7FFFFFF, so it's in the same quadrant as things to the bottom and right of it and not as things to the top and left of it. You could somehow make it a division between tiles instead of inside any tile, but then how do you index a line feature that's right on the line?

I see -- thanks for the explanation.

I wonder if there's some adjustment to the math that would make it do something more satisfying. It all gets so weird at the tile edges.