2009-12-22 23:18:51 +08:00
|
|
|
from django.contrib.gis import gdal
|
2012-07-20 20:48:51 +08:00
|
|
|
from django.utils import six
|
2012-08-12 18:32:08 +08:00
|
|
|
from django.utils.encoding import python_2_unicode_compatible
|
2009-12-22 23:18:51 +08:00
|
|
|
|
2013-05-09 23:13:13 +08:00
|
|
|
|
2012-08-12 18:32:08 +08:00
|
|
|
@python_2_unicode_compatible
|
2009-12-22 23:18:51 +08:00
|
|
|
class SpatialRefSysMixin(object):
|
|
|
|
"""
|
|
|
|
The SpatialRefSysMixin is a class used by the database-dependent
|
2014-03-02 22:25:53 +08:00
|
|
|
SpatialRefSys objects to reduce redundant code.
|
2009-12-22 23:18:51 +08:00
|
|
|
"""
|
|
|
|
@property
|
|
|
|
def srs(self):
|
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
Returns a GDAL SpatialReference object.
|
2009-12-22 23:18:51 +08:00
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
# TODO: Is caching really necessary here? Is complexity worth it?
|
|
|
|
if hasattr(self, '_srs'):
|
|
|
|
# Returning a clone of the cached SpatialReference object.
|
|
|
|
return self._srs.clone()
|
2009-12-22 23:18:51 +08:00
|
|
|
else:
|
2016-06-14 22:18:33 +08:00
|
|
|
# Attempting to cache a SpatialReference object.
|
|
|
|
|
|
|
|
# Trying to get from WKT first.
|
|
|
|
try:
|
|
|
|
self._srs = gdal.SpatialReference(self.wkt)
|
|
|
|
return self.srs
|
|
|
|
except Exception as e:
|
|
|
|
msg = e
|
|
|
|
|
|
|
|
try:
|
|
|
|
self._srs = gdal.SpatialReference(self.proj4text)
|
|
|
|
return self.srs
|
|
|
|
except Exception as e:
|
|
|
|
msg = e
|
|
|
|
|
|
|
|
raise Exception('Could not get OSR SpatialReference from WKT: %s\nError:\n%s' % (self.wkt, msg))
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def ellipsoid(self):
|
|
|
|
"""
|
|
|
|
Returns a tuple of the ellipsoid parameters:
|
|
|
|
(semimajor axis, semiminor axis, and inverse flattening).
|
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.ellipsoid
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"Returns the projection name."
|
|
|
|
return self.srs.name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def spheroid(self):
|
|
|
|
"Returns the spheroid name for this spatial reference."
|
|
|
|
return self.srs['spheroid']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def datum(self):
|
|
|
|
"Returns the datum for this spatial reference."
|
|
|
|
return self.srs['datum']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def projected(self):
|
|
|
|
"Is this Spatial Reference projected?"
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.projected
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def local(self):
|
|
|
|
"Is this Spatial Reference local?"
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.local
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def geographic(self):
|
|
|
|
"Is this Spatial Reference geographic?"
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.geographic
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def linear_name(self):
|
|
|
|
"Returns the linear units name."
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.linear_name
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def linear_units(self):
|
|
|
|
"Returns the linear units."
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.linear_units
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def angular_name(self):
|
|
|
|
"Returns the name of the angular units."
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.angular_name
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def angular_units(self):
|
|
|
|
"Returns the angular units."
|
2016-06-14 22:18:33 +08:00
|
|
|
return self.srs.angular_units
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@property
|
|
|
|
def units(self):
|
|
|
|
"Returns a tuple of the units and the name."
|
|
|
|
if self.projected or self.local:
|
|
|
|
return (self.linear_units, self.linear_name)
|
|
|
|
elif self.geographic:
|
|
|
|
return (self.angular_units, self.angular_name)
|
|
|
|
else:
|
|
|
|
return (None, None)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_units(cls, wkt):
|
|
|
|
"""
|
2016-04-19 17:35:50 +08:00
|
|
|
Return a tuple of (unit_value, unit_name) for the given WKT without
|
|
|
|
using any of the database fields.
|
2009-12-22 23:18:51 +08:00
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
return gdal.SpatialReference(wkt).units
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_spheroid(cls, wkt, string=True):
|
|
|
|
"""
|
|
|
|
Class method used by GeometryField on initialization to
|
|
|
|
retrieve the `SPHEROID[..]` parameters from the given WKT.
|
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
srs = gdal.SpatialReference(wkt)
|
|
|
|
sphere_params = srs.ellipsoid
|
|
|
|
sphere_name = srs['spheroid']
|
2009-12-22 23:18:51 +08:00
|
|
|
|
|
|
|
if not string:
|
|
|
|
return sphere_name, sphere_params
|
|
|
|
else:
|
|
|
|
# `string` parameter used to place in format acceptable by PostGIS
|
|
|
|
if len(sphere_params) == 3:
|
|
|
|
radius, flattening = sphere_params[0], sphere_params[2]
|
|
|
|
else:
|
|
|
|
radius, flattening = sphere_params
|
|
|
|
return 'SPHEROID["%s",%s,%s]' % (sphere_name, radius, flattening)
|
|
|
|
|
2012-08-12 18:32:08 +08:00
|
|
|
def __str__(self):
|
2009-12-22 23:18:51 +08:00
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
Returns the string representation, a 'pretty' OGC WKT.
|
2009-12-22 23:18:51 +08:00
|
|
|
"""
|
2016-06-14 22:18:33 +08:00
|
|
|
return six.text_type(self.srs)
|