# Commits

committed 4070d8f

Cleanup of spatial range queries.

• Participants
• Parent commits 8c08b45

# File lupyne/engine/spatial/__init__.py

`         "Generate tile keys within distance of given point, adjusting precision to limit the number considered."`
`         x, y = self.LatLonToMeters(lat, lng)`
`         for precision in range(precision, 0, -1):`
`-            left, bottom = self.MetersToTile(x-distance, y-distance, precision)`
`-            right, top = self.MetersToTile(x+distance, y+distance, precision)`
`-            count = (right+1 - left) * (top+1 - bottom)`
`-            if count > self.base ** precision: # spanned globe`
`-                for tile in range(self.base):`
`-                    yield str(tile)`
`-                return`
`-            if count <= limit:`
`+            left, bottom = (max(value, 0) for value in self.MetersToTile(x-distance, y-distance, precision))`
`+            right, top = (min(value + 1, 2 ** precision) for value in self.MetersToTile(x+distance, y+distance, precision))`
`+            if (right - left) * (top - bottom) <= limit:`
`                 break`
`-        for i, j in itertools.product(range(left, right+1), range(bottom, top+1)):`
`+        for i, j in itertools.product(range(left, right), range(bottom, top)):`
`             left, bottom, right, top = self.TileBounds(i, j, precision)`
`             dx = min(0, x-left, right-x)`
`             dy = min(0, y-bottom, top-y)`
`         "Generate tiles from points (lng, lat)."`
`         tiles = set(self.encode(lat, lng, self.precision) for lng, lat in points)`
`         return NumericField.items(self, *(int(tile, self.base) for tile in tiles))`
`+    def ranges(self, tiles):`
`+        "Generate range queries by grouping adjacent tiles."`
`+        precision, = set(map(len, tiles))`
`+        step = self.base ** (self.precision - precision)`
`+        tiles = (int(tile, self.base) * step for tile in tiles)`
`+        start = next(tiles)`
`+        stop = start + step`
`+        for tile in tiles:`
`+            if tile != stop:`
`+                yield self.range(start, stop)`
`+                start = tile`
`+            stop = tile + step`
`+        yield self.range(start, stop)`
`     def prefix(self, tile):`
`         "Return range query which is equivalent to the prefix of the tile."`
`-        shift = self.base ** (self.precision - len(tile))`
`-        value = int(tile, self.base) * shift`
`-        return self.range(value, value + shift)`
`+        return next(self.ranges([tile]))`
`     def near(self, lng, lat, precision=None):`
`         "Return prefix query for point at given precision."`
`         return self.prefix(self.encode(lat, lng, precision or self.precision))`
`         :param limit: maximum number of tiles to consider`
`         """`
`         tiles = sorted(self.radiate(lat, lng, distance, self.precision, limit))`
`-        precision, = set(map(len, tiles))`
`-        shift = self.base ** (self.precision - precision)`
`-        slices = []`
`-        for tile in tiles:`
`-            tile = int(tile, self.base) * shift`
`-            if slices and slices[-1][1] == tile:`
`-                slices[-1] = slices[-1][0], tile + shift`
`-            else:`
`-                slices.append((tile, tile + shift))`
`-        return Query.any(*itertools.starmap(self.range, slices))`
`+        return Query.any(*self.ranges(tiles))`
` `
` class PolygonField(PointField):`
`     """PointField which implicitly supports polygons (technically linear rings of points).`

# File lupyne/engine/spatial/globalmaptiles.py

`-#!/usr/bin/env python`
` ###############################################################################`
` # \$Id\$`
` #`