Source code for pygeotile.point
import math
from collections import namedtuple
from .meta import resolution, ORIGIN_SHIFT, TILE_SIZE
BasePoint = namedtuple('BasePoint', 'latitude longitude')
[docs]class Point(BasePoint):
"""Immutable Point class"""
[docs] @classmethod
def from_latitude_longitude(cls, latitude=0.0, longitude=0.0):
"""Creates a point from lat/lon in WGS84"""
assert -180.0 <= longitude <= 180.0, 'Longitude needs to be a value between -180.0 and 180.0.'
assert -90.0 <= latitude <= 90.0, 'Latitude needs to be a value between -90.0 and 90.0.'
return cls(latitude=latitude, longitude=longitude)
[docs] @classmethod
def from_pixel(cls, pixel_x=0, pixel_y=0, zoom=None):
"""Creates a point from pixels X Y Z (zoom) in pyramid"""
max_pixel = (2 ** zoom) * TILE_SIZE
assert 0 <= pixel_x <= max_pixel, 'Point X needs to be a value between 0 and (2^zoom) * 256.'
assert 0 <= pixel_y <= max_pixel, 'Point Y needs to be a value between 0 and (2^zoom) * 256.'
meter_x = pixel_x * resolution(zoom) - ORIGIN_SHIFT
meter_y = pixel_y * resolution(zoom) - ORIGIN_SHIFT
meter_x, meter_y = cls._sign_meters(meters=(meter_x, meter_y), pixels=(pixel_x, pixel_y), zoom=zoom)
return cls.from_meters(meter_x=meter_x, meter_y=meter_y)
[docs] @classmethod
def from_meters(cls, meter_x=0.0, meter_y=0.0):
"""Creates a point from X Y Z (zoom) meters in Spherical Mercator EPSG:900913"""
assert -ORIGIN_SHIFT <= meter_x <= ORIGIN_SHIFT, \
'Meter X needs to be a value between -{0} and {0}.'.format(ORIGIN_SHIFT)
assert -ORIGIN_SHIFT <= meter_y <= ORIGIN_SHIFT, \
'Meter Y needs to be a value between -{0} and {0}.'.format(ORIGIN_SHIFT)
longitude = (meter_x / ORIGIN_SHIFT) * 180.0
latitude = (meter_y / ORIGIN_SHIFT) * 180.0
latitude = 180.0 / math.pi * (2 * math.atan(math.exp(latitude * math.pi / 180.0)) - math.pi / 2.0)
return cls(latitude=latitude, longitude=longitude)
@property
def latitude_longitude(self):
"""Gets lat/lon in WGS84"""
return self.latitude, self.longitude
[docs] def pixels(self, zoom=None):
"""Gets pixels of the EPSG:4326 pyramid by a specific zoom, converted from lat/lon in WGS84"""
meter_x, meter_y = self.meters
pixel_x = (meter_x + ORIGIN_SHIFT) / resolution(zoom=zoom)
pixel_y = (meter_y - ORIGIN_SHIFT) / resolution(zoom=zoom)
return abs(round(pixel_x)), abs(round(pixel_y))
@property
def meters(self):
"""Gets the XY meters in Spherical Mercator EPSG:900913, converted from lat/lon in WGS84"""
latitude, longitude = self.latitude_longitude
meter_x = longitude * ORIGIN_SHIFT / 180.0
meter_y = math.log(math.tan((90.0 + latitude) * math.pi / 360.0)) / (math.pi / 180.0)
meter_y = meter_y * ORIGIN_SHIFT / 180.0
return meter_x, meter_y
@staticmethod
def _sign_meters(meters, pixels, zoom):
half_size = int((TILE_SIZE * 2 ** zoom) / 2)
pixel_x, pixel_y = pixels
meter_x, meter_y = meters
meter_x, meter_y = abs(meter_x), abs(meter_y)
if pixel_x < half_size:
meter_x *= -1
if pixel_y > half_size:
meter_y *= -1
return meter_x, meter_y
__all__ = ['Point']