diff --git a/opendm/tiles/gdal2tiles.py b/opendm/tiles/gdal2tiles.py index 081c335a5..bd9225c66 100644 --- a/opendm/tiles/gdal2tiles.py +++ b/opendm/tiles/gdal2tiles.py @@ -209,7 +209,6 @@ def __init__(self, tileSize=256): self.initialResolution = 2 * math.pi * 6378137 / self.tileSize # 156543.03392804062 for tileSize 256 pixels self.originShift = 2 * math.pi * 6378137 / 2.0 - # 20037508.342789244 def LatLonToMeters(self, lat, lon): "Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:3857" @@ -223,10 +222,11 @@ def LatLonToMeters(self, lat, lon): def MetersToLatLon(self, mx, my): "Converts XY point from Spherical Mercator EPSG:3857 to lat/lon in WGS84 Datum" - lon = (mx / self.originShift) * 180.0 - lat = (my / self.originShift) * 180.0 - - lat = 180 / math.pi * (2 * math.atan(math.exp(lat * math.pi / 180.0)) - math.pi / 2.0) + inv_originShift = 180.0 / self.originShift + lon = mx * inv_originShift + lat = my * inv_originShift + pi = math.pi + lat = 180.0 / pi * (2.0 * math.atan(math.exp(lat * pi / 180.0)) - pi / 2.0) return lat, lon def PixelsToMeters(self, px, py, zoom): @@ -356,15 +356,17 @@ class GlobalGeodetic(object): def __init__(self, tmscompatible, tileSize=256): self.tileSize = tileSize + # Precompute inverse, since division for each call may be expensive if tileSize changes. + inv_tileSize = 1.0 / self.tileSize if tmscompatible is not None: # Defaults the resolution factor to 0.703125 (2 tiles @ level 0) # Adhers to OSGeo TMS spec # http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic - self.resFact = 180.0 / self.tileSize + self.resFact = 180.0 * inv_tileSize else: # Defaults the resolution factor to 1.40625 (1 tile @ level 0) # Adheres OpenLayers, MapProxy, etc default resolution for WMTS - self.resFact = 360.0 / self.tileSize + self.resFact = 360.0 * inv_tileSize def LonLatToPixels(self, lon, lat, zoom): "Converts lon/lat to pixel coordinates in given zoom of the EPSG:4326 pyramid" @@ -403,17 +405,22 @@ def ZoomForPixelSize(self, pixelSize): return 0 # We don't want to scale up def TileBounds(self, tx, ty, zoom): - "Returns bounds of the given tile" - res = self.resFact / 2**zoom - return ( - tx*self.tileSize*res - 180, - ty*self.tileSize*res - 90, - (tx+1)*self.tileSize*res - 180, - (ty+1)*self.tileSize*res - 90 - ) + """Returns bounds of the given tile""" + # Use bitshift for integer powers of two for performance + # This avoids repeated computation of the same value + if isinstance(zoom, int) and 0 <= zoom <= 30: + res = self.resFact / (1 << zoom) + else: + res = self.resFact / 2**zoom + tile_factor = self.tileSize * res + tx0 = tx * tile_factor - 180 + ty0 = ty * tile_factor - 90 + tx1 = (tx + 1) * tile_factor - 180 + ty1 = (ty + 1) * tile_factor - 90 + return (tx0, ty0, tx1, ty1) def TileLatLonBounds(self, tx, ty, zoom): - "Returns bounds of the given tile in the SWNE form" + """Returns bounds of the given tile in the SWNE form""" b = self.TileBounds(tx, ty, zoom) return (b[1], b[0], b[3], b[2])