Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Tree: aecdaa6ee9
Fetching contributors…

Cannot retrieve contributors at this time

149 lines (112 sloc) 4.894 kB
""" The geography bits of TileStache.
A Projection defines the relationship between the rendered tiles and the
underlying geographic data. Generally, just one popular projection is used
for most web maps, "spherical mercator".
Built-in projections:
- spherical mercator
- WGS84
Example use projection in a layer definition:
"layer-name": {
"projection": "spherical mercator",
...
}
You can define your own projection, with a module and object name as arguments:
"layer-name": {
...
"projection": "Module:Object"
}
The object must include methods that convert between coordinates, points, and
locations. See the included mercator and WGS84 implementations for example.
You can also instantiate a projection class using this syntax:
"layer-name": {
...
"projection": "Module:Object()"
}
"""
from ModestMaps.Core import Point, Coordinate
from ModestMaps.Geo import deriveTransformation, MercatorProjection, LinearProjection, Location
from math import log as _log, pi as _pi
import Core
import Config
class SphericalMercator(MercatorProjection):
""" Spherical mercator projection for most commonly-used web map tile scheme.
This projection is identified by the name "spherical mercator" in the
TileStache config. The simplified projection used here is described in
greater detail at: http://trac.openlayers.org/wiki/SphericalMercator
"""
srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over'
def __init__(self):
pi = _pi
# Transform from raw mercator projection to tile coordinates
t = deriveTransformation(-pi, pi, 0, 0, pi, pi, 1, 0, -pi, -pi, 0, 1)
MercatorProjection.__init__(self, 0, t)
def coordinateProj(self, coord):
""" Convert from Coordinate object to a Point object in EPSG:900913
"""
# the zoom at which we're dealing with meters on the ground
diameter = 2 * _pi * 6378137
zoom = _log(diameter) / _log(2)
coord = coord.zoomTo(zoom)
# global offsets
point = Point(coord.column, coord.row)
point.x = point.x - diameter/2
point.y = diameter/2 - point.y
return point
def projCoordinate(self, point):
""" Convert from Point object in EPSG:900913 to a Coordinate object
"""
# the zoom at which we're dealing with meters on the ground
diameter = 2 * _pi * 6378137
zoom = _log(diameter) / _log(2)
# global offsets
coord = Coordinate(point.y, point.x, zoom)
coord.column = coord.column + diameter/2
coord.row = diameter/2 - coord.row
return coord
def locationProj(self, location):
""" Convert from Location object to a Point object in EPSG:900913
"""
return self.coordinateProj(self.locationCoordinate(location))
def projLocation(self, point):
""" Convert from Point object in EPSG:900913 to a Location object
"""
return self.coordinateLocation(self.projCoordinate(point))
class WGS84(LinearProjection):
""" Unprojected projection for the other commonly-used web map tile scheme.
This projection is identified by the name "WGS84" in the TileStache config.
"""
srs = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
def __init__(self):
p = _pi
# Transform from geography in radians to tile coordinates
t = deriveTransformation(-p, p/2, 0, 0, p, p/2, 2, 0, -p, -p/2, 0, 1)
LinearProjection.__init__(self, 0, t)
def coordinateProj(self, coord):
""" Convert from Coordinate object to a Point object in EPSG:4326
"""
return self.locationProj(self.coordinateLocation(coord))
def projCoordinate(self, point):
""" Convert from Point object in EPSG:4326 to a Coordinate object
"""
return self.locationCoordinate(self.projLocation(point))
def locationProj(self, location):
""" Convert from Location object to a Point object in EPSG:4326
"""
return Point(location.lon, location.lat)
def projLocation(self, point):
""" Convert from Point object in EPSG:4326 to a Location object
"""
return Location(point.y, point.x)
def getProjectionByName(name):
""" Retrieve a projection object by name.
Raise an exception if the name doesn't work out.
"""
if name.lower() == 'spherical mercator':
return SphericalMercator()
elif name.lower() == 'wgs84':
return WGS84()
else:
try:
return Config.loadClassPath(name)
except Exception, e:
raise Core.KnownUnknown('Failed projection in configuration: "%s" - %s' % (name, e))
Jump to Line
Something went wrong with that request. Please try again.