123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- """
- The Spatial Reference class, represents OGR Spatial Reference objects.
-
- Example:
- >>> from django.contrib.gis.gdal import SpatialReference
- >>> srs = SpatialReference('WGS84')
- >>> print(srs)
- GEOGCS["WGS 84",
- DATUM["WGS_1984",
- SPHEROID["WGS 84",6378137,298.257223563,
- AUTHORITY["EPSG","7030"]],
- TOWGS84[0,0,0,0,0,0,0],
- AUTHORITY["EPSG","6326"]],
- PRIMEM["Greenwich",0,
- AUTHORITY["EPSG","8901"]],
- UNIT["degree",0.01745329251994328,
- AUTHORITY["EPSG","9122"]],
- AUTHORITY["EPSG","4326"]]
- >>> print(srs.proj)
- +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
- >>> print(srs.ellipsoid)
- (6378137.0, 6356752.3142451793, 298.25722356300003)
- >>> print(srs.projected, srs.geographic)
- False True
- >>> srs.import_epsg(32140)
- >>> print(srs.name)
- NAD83 / Texas South Central
- """
- from ctypes import byref, c_char_p, c_int
-
- from django.contrib.gis.gdal.base import GDALBase
- from django.contrib.gis.gdal.error import SRSException
- from django.contrib.gis.gdal.prototypes import srs as capi
- from django.utils.encoding import force_bytes, force_text
-
-
- class SpatialReference(GDALBase):
- """
- A wrapper for the OGRSpatialReference object. According to the GDAL Web site,
- the SpatialReference object "provide[s] services to represent coordinate
- systems (projections and datums) and to transform between them."
- """
- destructor = capi.release_srs
-
- def __init__(self, srs_input='', srs_type='user'):
- """
- Create a GDAL OSR Spatial Reference object from the given input.
- The input may be string of OGC Well Known Text (WKT), an integer
- EPSG code, a PROJ.4 string, and/or a projection "well known" shorthand
- string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83').
- """
-
- if srs_type == 'wkt':
- self.ptr = capi.new_srs(c_char_p(b''))
- self.import_wkt(srs_input)
- return
- elif isinstance(srs_input, str):
- try:
- # If SRID is a string, e.g., '4326', then make acceptable
- # as user input.
- srid = int(srs_input)
- srs_input = 'EPSG:%d' % srid
- except ValueError:
- pass
- elif isinstance(srs_input, int):
- # EPSG integer code was input.
- srs_type = 'epsg'
- elif isinstance(srs_input, self.ptr_type):
- srs = srs_input
- srs_type = 'ogr'
- else:
- raise TypeError('Invalid SRS type "%s"' % srs_type)
-
- if srs_type == 'ogr':
- # Input is already an SRS pointer.
- srs = srs_input
- else:
- # Creating a new SRS pointer, using the string buffer.
- buf = c_char_p(b'')
- srs = capi.new_srs(buf)
-
- # If the pointer is NULL, throw an exception.
- if not srs:
- raise SRSException('Could not create spatial reference from: %s' % srs_input)
- else:
- self.ptr = srs
-
- # Importing from either the user input string or an integer SRID.
- if srs_type == 'user':
- self.import_user_input(srs_input)
- elif srs_type == 'epsg':
- self.import_epsg(srs_input)
-
- def __getitem__(self, target):
- """
- Return the value of the given string attribute node, None if the node
- doesn't exist. Can also take a tuple as a parameter, (target, child),
- where child is the index of the attribute in the WKT. For example:
-
- >>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]'
- >>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326
- >>> print(srs['GEOGCS'])
- WGS 84
- >>> print(srs['DATUM'])
- WGS_1984
- >>> print(srs['AUTHORITY'])
- EPSG
- >>> print(srs['AUTHORITY', 1]) # The authority value
- 4326
- >>> print(srs['TOWGS84', 4]) # the fourth value in this wkt
- 0
- >>> print(srs['UNIT|AUTHORITY']) # For the units authority, have to use the pipe symbole.
- EPSG
- >>> print(srs['UNIT|AUTHORITY', 1]) # The authority value for the units
- 9122
- """
- if isinstance(target, tuple):
- return self.attr_value(*target)
- else:
- return self.attr_value(target)
-
- def __str__(self):
- "Use 'pretty' WKT."
- return self.pretty_wkt
-
- # #### SpatialReference Methods ####
- def attr_value(self, target, index=0):
- """
- The attribute value for the given target node (e.g. 'PROJCS'). The index
- keyword specifies an index of the child node to return.
- """
- if not isinstance(target, str) or not isinstance(index, int):
- raise TypeError
- return capi.get_attr_value(self.ptr, force_bytes(target), index)
-
- def auth_name(self, target):
- "Return the authority name for the given string target node."
- return capi.get_auth_name(self.ptr, force_bytes(target))
-
- def auth_code(self, target):
- "Return the authority code for the given string target node."
- return capi.get_auth_code(self.ptr, force_bytes(target))
-
- def clone(self):
- "Return a clone of this SpatialReference object."
- return SpatialReference(capi.clone_srs(self.ptr))
-
- def from_esri(self):
- "Morph this SpatialReference from ESRI's format to EPSG."
- capi.morph_from_esri(self.ptr)
-
- def identify_epsg(self):
- """
- This method inspects the WKT of this SpatialReference, and will
- add EPSG authority nodes where an EPSG identifier is applicable.
- """
- capi.identify_epsg(self.ptr)
-
- def to_esri(self):
- "Morph this SpatialReference to ESRI's format."
- capi.morph_to_esri(self.ptr)
-
- def validate(self):
- "Check to see if the given spatial reference is valid."
- capi.srs_validate(self.ptr)
-
- # #### Name & SRID properties ####
- @property
- def name(self):
- "Return the name of this Spatial Reference."
- if self.projected:
- return self.attr_value('PROJCS')
- elif self.geographic:
- return self.attr_value('GEOGCS')
- elif self.local:
- return self.attr_value('LOCAL_CS')
- else:
- return None
-
- @property
- def srid(self):
- "Return the SRID of top-level authority, or None if undefined."
- try:
- return int(self.attr_value('AUTHORITY', 1))
- except (TypeError, ValueError):
- return None
-
- # #### Unit Properties ####
- @property
- def linear_name(self):
- "Return the name of the linear units."
- units, name = capi.linear_units(self.ptr, byref(c_char_p()))
- return name
-
- @property
- def linear_units(self):
- "Return the value of the linear units."
- units, name = capi.linear_units(self.ptr, byref(c_char_p()))
- return units
-
- @property
- def angular_name(self):
- "Return the name of the angular units."
- units, name = capi.angular_units(self.ptr, byref(c_char_p()))
- return name
-
- @property
- def angular_units(self):
- "Return the value of the angular units."
- units, name = capi.angular_units(self.ptr, byref(c_char_p()))
- return units
-
- @property
- def units(self):
- """
- Return a 2-tuple of the units value and the units name. Automatically
- determine whether to return the linear or angular units.
- """
- units, name = None, None
- if self.projected or self.local:
- units, name = capi.linear_units(self.ptr, byref(c_char_p()))
- elif self.geographic:
- units, name = capi.angular_units(self.ptr, byref(c_char_p()))
- if name is not None:
- name = force_text(name)
- return (units, name)
-
- # #### Spheroid/Ellipsoid Properties ####
- @property
- def ellipsoid(self):
- """
- Return a tuple of the ellipsoid parameters:
- (semimajor axis, semiminor axis, and inverse flattening)
- """
- return (self.semi_major, self.semi_minor, self.inverse_flattening)
-
- @property
- def semi_major(self):
- "Return the Semi Major Axis for this Spatial Reference."
- return capi.semi_major(self.ptr, byref(c_int()))
-
- @property
- def semi_minor(self):
- "Return the Semi Minor Axis for this Spatial Reference."
- return capi.semi_minor(self.ptr, byref(c_int()))
-
- @property
- def inverse_flattening(self):
- "Return the Inverse Flattening for this Spatial Reference."
- return capi.invflattening(self.ptr, byref(c_int()))
-
- # #### Boolean Properties ####
- @property
- def geographic(self):
- """
- Return True if this SpatialReference is geographic
- (root node is GEOGCS).
- """
- return bool(capi.isgeographic(self.ptr))
-
- @property
- def local(self):
- "Return True if this SpatialReference is local (root node is LOCAL_CS)."
- return bool(capi.islocal(self.ptr))
-
- @property
- def projected(self):
- """
- Return True if this SpatialReference is a projected coordinate system
- (root node is PROJCS).
- """
- return bool(capi.isprojected(self.ptr))
-
- # #### Import Routines #####
- def import_epsg(self, epsg):
- "Import the Spatial Reference from the EPSG code (an integer)."
- capi.from_epsg(self.ptr, epsg)
-
- def import_proj(self, proj):
- "Import the Spatial Reference from a PROJ.4 string."
- capi.from_proj(self.ptr, proj)
-
- def import_user_input(self, user_input):
- "Import the Spatial Reference from the given user input string."
- capi.from_user_input(self.ptr, force_bytes(user_input))
-
- def import_wkt(self, wkt):
- "Import the Spatial Reference from OGC WKT (string)"
- capi.from_wkt(self.ptr, byref(c_char_p(force_bytes(wkt))))
-
- def import_xml(self, xml):
- "Import the Spatial Reference from an XML string."
- capi.from_xml(self.ptr, xml)
-
- # #### Export Properties ####
- @property
- def wkt(self):
- "Return the WKT representation of this Spatial Reference."
- return capi.to_wkt(self.ptr, byref(c_char_p()))
-
- @property
- def pretty_wkt(self, simplify=0):
- "Return the 'pretty' representation of the WKT."
- return capi.to_pretty_wkt(self.ptr, byref(c_char_p()), simplify)
-
- @property
- def proj(self):
- "Return the PROJ.4 representation for this Spatial Reference."
- return capi.to_proj(self.ptr, byref(c_char_p()))
-
- @property
- def proj4(self):
- "Alias for proj()."
- return self.proj
-
- @property
- def xml(self, dialect=''):
- "Return the XML representation of this Spatial Reference."
- return capi.to_xml(self.ptr, byref(c_char_p()), force_bytes(dialect))
-
-
- class CoordTransform(GDALBase):
- "The coordinate system transformation object."
- destructor = capi.destroy_ct
-
- def __init__(self, source, target):
- "Initialize on a source and target SpatialReference objects."
- if not isinstance(source, SpatialReference) or not isinstance(target, SpatialReference):
- raise TypeError('source and target must be of type SpatialReference')
- self.ptr = capi.new_ct(source._ptr, target._ptr)
- self._srs1_name = source.name
- self._srs2_name = target.name
-
- def __str__(self):
- return 'Transform from "%s" to "%s"' % (self._srs1_name, self._srs2_name)
|