summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/django/contrib/gis/gdal
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/django/contrib/gis/gdal')
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/__init__.py55
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/base.py36
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/datasource.py135
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/driver.py68
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/envelope.py175
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/error.py42
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/feature.py124
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/field.py194
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/geometries.py726
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/geomtype.py87
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/layer.py218
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/libgdal.py109
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/__init__.py0
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/ds.py70
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/errcheck.py128
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/generation.py125
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/geom.py98
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/srs.py71
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/srs.py342
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/tests/__init__.py0
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_driver.py39
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_ds.py244
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_envelope.py93
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_geom.py485
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_srs.py163
25 files changed, 3827 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/__init__.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/__init__.py
new file mode 100644
index 0000000..2aa867b
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/__init__.py
@@ -0,0 +1,55 @@
+"""
+ This module houses ctypes interfaces for GDAL objects. The following GDAL
+ objects are supported:
+
+ CoordTransform: Used for coordinate transformations from one spatial
+ reference system to another.
+
+ Driver: Wraps an OGR data source driver.
+
+ DataSource: Wrapper for the OGR data source object, supports
+ OGR-supported data sources.
+
+ Envelope: A ctypes structure for bounding boxes (GDAL library
+ not required).
+
+ OGRGeometry: Object for accessing OGR Geometry functionality.
+
+ OGRGeomType: A class for representing the different OGR Geometry
+ types (GDAL library not required).
+
+ SpatialReference: Represents OSR Spatial Reference objects.
+
+ The GDAL library will be imported from the system path using the default
+ library name for the current OS. The default library path may be overridden
+ by setting `GDAL_LIBRARY_PATH` in your settings with the path to the GDAL C
+ library on your system.
+
+ GDAL links to a large number of external libraries that consume RAM when
+ loaded. Thus, it may desirable to disable GDAL on systems with limited
+ RAM resources -- this may be accomplished by setting `GDAL_LIBRARY_PATH`
+ to a non-existant file location (e.g., `GDAL_LIBRARY_PATH='/null/path'`;
+ setting to None/False/'' will not work as a string must be given).
+"""
+from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError, SRSException
+from django.contrib.gis.gdal.geomtype import OGRGeomType
+
+# Attempting to import objects that depend on the GDAL library. The
+# HAS_GDAL flag will be set to True if the library is present on
+# the system.
+try:
+ from django.contrib.gis.gdal.driver import Driver
+ from django.contrib.gis.gdal.datasource import DataSource
+ from django.contrib.gis.gdal.libgdal import gdal_version, gdal_full_version, GDAL_VERSION
+ from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
+ from django.contrib.gis.gdal.geometries import OGRGeometry
+ HAS_GDAL = True
+except OGRException:
+ HAS_GDAL = False
+
+try:
+ from django.contrib.gis.gdal.envelope import Envelope
+except ImportError:
+ # No ctypes, but don't raise an exception.
+ pass
+
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/base.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/base.py
new file mode 100644
index 0000000..e86277e
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/base.py
@@ -0,0 +1,36 @@
+from ctypes import c_void_p
+
+from django.contrib.gis.gdal.error import GDALException
+from django.utils import six
+
+class GDALBase(object):
+ """
+ Base object for GDAL objects that has a pointer access property
+ that controls access to the underlying C pointer.
+ """
+ # Initially the pointer is NULL.
+ _ptr = None
+
+ # Default allowed pointer type.
+ ptr_type = c_void_p
+
+ # Pointer access property.
+ def _get_ptr(self):
+ # Raise an exception if the pointer isn't valid don't
+ # want to be passing NULL pointers to routines --
+ # that's very bad.
+ if self._ptr: return self._ptr
+ else: raise GDALException('GDAL %s pointer no longer valid.' % self.__class__.__name__)
+
+ def _set_ptr(self, ptr):
+ # Only allow the pointer to be set with pointers of the
+ # compatible type or None (NULL).
+ if isinstance(ptr, six.integer_types):
+ self._ptr = self.ptr_type(ptr)
+ elif ptr is None or isinstance(ptr, self.ptr_type):
+ self._ptr = ptr
+ else:
+ raise TypeError('Incompatible pointer type')
+
+ ptr = property(_get_ptr, _set_ptr)
+
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/datasource.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/datasource.py
new file mode 100644
index 0000000..c92b2e1
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/datasource.py
@@ -0,0 +1,135 @@
+"""
+ DataSource is a wrapper for the OGR Data Source object, which provides
+ an interface for reading vector geometry data from many different file
+ formats (including ESRI shapefiles).
+
+ When instantiating a DataSource object, use the filename of a
+ GDAL-supported data source. For example, a SHP file or a
+ TIGER/Line file from the government.
+
+ The ds_driver keyword is used internally when a ctypes pointer
+ is passed in directly.
+
+ Example:
+ ds = DataSource('/home/foo/bar.shp')
+ for layer in ds:
+ for feature in layer:
+ # Getting the geometry for the feature.
+ g = feature.geom
+
+ # Getting the 'description' field for the feature.
+ desc = feature['description']
+
+ # We can also increment through all of the fields
+ # attached to this feature.
+ for field in feature:
+ # Get the name of the field (e.g. 'description')
+ nm = field.name
+
+ # Get the type (integer) of the field, e.g. 0 => OFTInteger
+ t = field.type
+
+ # Returns the value the field; OFTIntegers return ints,
+ # OFTReal returns floats, all else returns string.
+ val = field.value
+"""
+# ctypes prerequisites.
+from ctypes import byref
+
+# The GDAL C library, OGR exceptions, and the Layer object.
+from django.contrib.gis.gdal.base import GDALBase
+from django.contrib.gis.gdal.driver import Driver
+from django.contrib.gis.gdal.error import OGRException, OGRIndexError
+from django.contrib.gis.gdal.layer import Layer
+
+# Getting the ctypes prototypes for the DataSource.
+from django.contrib.gis.gdal.prototypes import ds as capi
+
+from django.utils.encoding import force_bytes, force_text
+from django.utils import six
+from django.utils.six.moves import xrange
+
+# For more information, see the OGR C API source code:
+# http://www.gdal.org/ogr/ogr__api_8h.html
+#
+# The OGR_DS_* routines are relevant here.
+class DataSource(GDALBase):
+ "Wraps an OGR Data Source object."
+
+ #### Python 'magic' routines ####
+ def __init__(self, ds_input, ds_driver=False, write=False, encoding='utf-8'):
+ # The write flag.
+ if write:
+ self._write = 1
+ else:
+ self._write = 0
+ # See also http://trac.osgeo.org/gdal/wiki/rfc23_ogr_unicode
+ self.encoding = encoding
+
+ # Registering all the drivers, this needs to be done
+ # _before_ we try to open up a data source.
+ if not capi.get_driver_count():
+ capi.register_all()
+
+ if isinstance(ds_input, six.string_types):
+ # The data source driver is a void pointer.
+ ds_driver = Driver.ptr_type()
+ try:
+ # OGROpen will auto-detect the data source type.
+ ds = capi.open_ds(force_bytes(ds_input), self._write, byref(ds_driver))
+ except OGRException:
+ # Making the error message more clear rather than something
+ # like "Invalid pointer returned from OGROpen".
+ raise OGRException('Could not open the datasource at "%s"' % ds_input)
+ elif isinstance(ds_input, self.ptr_type) and isinstance(ds_driver, Driver.ptr_type):
+ ds = ds_input
+ else:
+ raise OGRException('Invalid data source input type: %s' % type(ds_input))
+
+ if bool(ds):
+ self.ptr = ds
+ self.driver = Driver(ds_driver)
+ else:
+ # Raise an exception if the returned pointer is NULL
+ raise OGRException('Invalid data source file "%s"' % ds_input)
+
+ def __del__(self):
+ "Destroys this DataStructure object."
+ if self._ptr: capi.destroy_ds(self._ptr)
+
+ def __iter__(self):
+ "Allows for iteration over the layers in a data source."
+ for i in xrange(self.layer_count):
+ yield self[i]
+
+ def __getitem__(self, index):
+ "Allows use of the index [] operator to get a layer at the index."
+ if isinstance(index, six.string_types):
+ l = capi.get_layer_by_name(self.ptr, force_bytes(index))
+ if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index)
+ elif isinstance(index, int):
+ if index < 0 or index >= self.layer_count:
+ raise OGRIndexError('index out of range')
+ l = capi.get_layer(self._ptr, index)
+ else:
+ raise TypeError('Invalid index type: %s' % type(index))
+ return Layer(l, self)
+
+ def __len__(self):
+ "Returns the number of layers within the data source."
+ return self.layer_count
+
+ def __str__(self):
+ "Returns OGR GetName and Driver for the Data Source."
+ return '%s (%s)' % (self.name, str(self.driver))
+
+ @property
+ def layer_count(self):
+ "Returns the number of layers in the data source."
+ return capi.get_layer_count(self._ptr)
+
+ @property
+ def name(self):
+ "Returns the name of the data source."
+ name = capi.get_ds_name(self._ptr)
+ return force_text(name, self.encoding, strings_only=True)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/driver.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/driver.py
new file mode 100644
index 0000000..55a5d77
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/driver.py
@@ -0,0 +1,68 @@
+# prerequisites imports
+from ctypes import c_void_p
+from django.contrib.gis.gdal.base import GDALBase
+from django.contrib.gis.gdal.error import OGRException
+from django.contrib.gis.gdal.prototypes import ds as capi
+
+from django.utils import six
+from django.utils.encoding import force_bytes
+
+# For more information, see the OGR C API source code:
+# http://www.gdal.org/ogr/ogr__api_8h.html
+#
+# The OGR_Dr_* routines are relevant here.
+class Driver(GDALBase):
+ "Wraps an OGR Data Source Driver."
+
+ # Case-insensitive aliases for OGR Drivers.
+ _alias = {'esri' : 'ESRI Shapefile',
+ 'shp' : 'ESRI Shapefile',
+ 'shape' : 'ESRI Shapefile',
+ 'tiger' : 'TIGER',
+ 'tiger/line' : 'TIGER',
+ }
+
+ def __init__(self, dr_input):
+ "Initializes an OGR driver on either a string or integer input."
+
+ if isinstance(dr_input, six.string_types):
+ # If a string name of the driver was passed in
+ self._register()
+
+ # Checking the alias dictionary (case-insensitive) to see if an alias
+ # exists for the given driver.
+ if dr_input.lower() in self._alias:
+ name = self._alias[dr_input.lower()]
+ else:
+ name = dr_input
+
+ # Attempting to get the OGR driver by the string name.
+ dr = capi.get_driver_by_name(force_bytes(name))
+ elif isinstance(dr_input, int):
+ self._register()
+ dr = capi.get_driver(dr_input)
+ elif isinstance(dr_input, c_void_p):
+ dr = dr_input
+ else:
+ raise OGRException('Unrecognized input type for OGR Driver: %s' % str(type(dr_input)))
+
+ # Making sure we get a valid pointer to the OGR Driver
+ if not dr:
+ raise OGRException('Could not initialize OGR Driver on input: %s' % str(dr_input))
+ self.ptr = dr
+
+ def __str__(self):
+ "Returns the string name of the OGR Driver."
+ return capi.get_driver_name(self.ptr)
+
+ def _register(self):
+ "Attempts to register all the data source drivers."
+ # Only register all if the driver count is 0 (or else all drivers
+ # will be registered over and over again)
+ if not self.driver_count: capi.register_all()
+
+ # Driver properties
+ @property
+ def driver_count(self):
+ "Returns the number of OGR data source drivers registered."
+ return capi.get_driver_count()
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/envelope.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/envelope.py
new file mode 100644
index 0000000..f145526
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/envelope.py
@@ -0,0 +1,175 @@
+"""
+ The GDAL/OGR library uses an Envelope structure to hold the bounding
+ box information for a geometry. The envelope (bounding box) contains
+ two pairs of coordinates, one for the lower left coordinate and one
+ for the upper right coordinate:
+
+ +----------o Upper right; (max_x, max_y)
+ | |
+ | |
+ | |
+ Lower left (min_x, min_y) o----------+
+"""
+from ctypes import Structure, c_double
+from django.contrib.gis.gdal.error import OGRException
+
+# The OGR definition of an Envelope is a C structure containing four doubles.
+# See the 'ogr_core.h' source file for more information:
+# http://www.gdal.org/ogr/ogr__core_8h-source.html
+class OGREnvelope(Structure):
+ "Represents the OGREnvelope C Structure."
+ _fields_ = [("MinX", c_double),
+ ("MaxX", c_double),
+ ("MinY", c_double),
+ ("MaxY", c_double),
+ ]
+
+class Envelope(object):
+ """
+ The Envelope object is a C structure that contains the minimum and
+ maximum X, Y coordinates for a rectangle bounding box. The naming
+ of the variables is compatible with the OGR Envelope structure.
+ """
+
+ def __init__(self, *args):
+ """
+ The initialization function may take an OGREnvelope structure, 4-element
+ tuple or list, or 4 individual arguments.
+ """
+
+ if len(args) == 1:
+ if isinstance(args[0], OGREnvelope):
+ # OGREnvelope (a ctypes Structure) was passed in.
+ self._envelope = args[0]
+ elif isinstance(args[0], (tuple, list)):
+ # A tuple was passed in.
+ if len(args[0]) != 4:
+ raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0]))
+ else:
+ self._from_sequence(args[0])
+ else:
+ raise TypeError('Incorrect type of argument: %s' % str(type(args[0])))
+ elif len(args) == 4:
+ # Individual parameters passed in.
+ # Thanks to ww for the help
+ self._from_sequence([float(a) for a in args])
+ else:
+ raise OGRException('Incorrect number (%d) of arguments.' % len(args))
+
+ # Checking the x,y coordinates
+ if self.min_x > self.max_x:
+ raise OGRException('Envelope minimum X > maximum X.')
+ if self.min_y > self.max_y:
+ raise OGRException('Envelope minimum Y > maximum Y.')
+
+ def __eq__(self, other):
+ """
+ Returns True if the envelopes are equivalent; can compare against
+ other Envelopes and 4-tuples.
+ """
+ if isinstance(other, Envelope):
+ return (self.min_x == other.min_x) and (self.min_y == other.min_y) and \
+ (self.max_x == other.max_x) and (self.max_y == other.max_y)
+ elif isinstance(other, tuple) and len(other) == 4:
+ return (self.min_x == other[0]) and (self.min_y == other[1]) and \
+ (self.max_x == other[2]) and (self.max_y == other[3])
+ else:
+ raise OGRException('Equivalence testing only works with other Envelopes.')
+
+ def __str__(self):
+ "Returns a string representation of the tuple."
+ return str(self.tuple)
+
+ def _from_sequence(self, seq):
+ "Initializes the C OGR Envelope structure from the given sequence."
+ self._envelope = OGREnvelope()
+ self._envelope.MinX = seq[0]
+ self._envelope.MinY = seq[1]
+ self._envelope.MaxX = seq[2]
+ self._envelope.MaxY = seq[3]
+
+ def expand_to_include(self, *args):
+ """
+ Modifies the envelope to expand to include the boundaries of
+ the passed-in 2-tuple (a point), 4-tuple (an extent) or
+ envelope.
+ """
+ # We provide a number of different signatures for this method,
+ # and the logic here is all about converting them into a
+ # 4-tuple single parameter which does the actual work of
+ # expanding the envelope.
+ if len(args) == 1:
+ if isinstance(args[0], Envelope):
+ return self.expand_to_include(args[0].tuple)
+ elif hasattr(args[0], 'x') and hasattr(args[0], 'y'):
+ return self.expand_to_include(args[0].x, args[0].y, args[0].x, args[0].y)
+ elif isinstance(args[0], (tuple, list)):
+ # A tuple was passed in.
+ if len(args[0]) == 2:
+ return self.expand_to_include((args[0][0], args[0][1], args[0][0], args[0][1]))
+ elif len(args[0]) == 4:
+ (minx, miny, maxx, maxy) = args[0]
+ if minx < self._envelope.MinX:
+ self._envelope.MinX = minx
+ if miny < self._envelope.MinY:
+ self._envelope.MinY = miny
+ if maxx > self._envelope.MaxX:
+ self._envelope.MaxX = maxx
+ if maxy > self._envelope.MaxY:
+ self._envelope.MaxY = maxy
+ else:
+ raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0]))
+ else:
+ raise TypeError('Incorrect type of argument: %s' % str(type(args[0])))
+ elif len(args) == 2:
+ # An x and an y parameter were passed in
+ return self.expand_to_include((args[0], args[1], args[0], args[1]))
+ elif len(args) == 4:
+ # Individual parameters passed in.
+ return self.expand_to_include(args)
+ else:
+ raise OGRException('Incorrect number (%d) of arguments.' % len(args[0]))
+
+ @property
+ def min_x(self):
+ "Returns the value of the minimum X coordinate."
+ return self._envelope.MinX
+
+ @property
+ def min_y(self):
+ "Returns the value of the minimum Y coordinate."
+ return self._envelope.MinY
+
+ @property
+ def max_x(self):
+ "Returns the value of the maximum X coordinate."
+ return self._envelope.MaxX
+
+ @property
+ def max_y(self):
+ "Returns the value of the maximum Y coordinate."
+ return self._envelope.MaxY
+
+ @property
+ def ur(self):
+ "Returns the upper-right coordinate."
+ return (self.max_x, self.max_y)
+
+ @property
+ def ll(self):
+ "Returns the lower-left coordinate."
+ return (self.min_x, self.min_y)
+
+ @property
+ def tuple(self):
+ "Returns a tuple representing the envelope."
+ return (self.min_x, self.min_y, self.max_x, self.max_y)
+
+ @property
+ def wkt(self):
+ "Returns WKT representing a Polygon for this envelope."
+ # TODO: Fix significant figures.
+ return 'POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))' % \
+ (self.min_x, self.min_y, self.min_x, self.max_y,
+ self.max_x, self.max_y, self.max_x, self.min_y,
+ self.min_x, self.min_y)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/error.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/error.py
new file mode 100644
index 0000000..1d89ad1
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/error.py
@@ -0,0 +1,42 @@
+"""
+ This module houses the OGR & SRS Exception objects, and the
+ check_err() routine which checks the status code returned by
+ OGR methods.
+"""
+#### OGR & SRS Exceptions ####
+class GDALException(Exception): pass
+class OGRException(Exception): pass
+class SRSException(Exception): pass
+class OGRIndexError(OGRException, KeyError):
+ """
+ This exception is raised when an invalid index is encountered, and has
+ the 'silent_variable_feature' attribute set to true. This ensures that
+ django's templates proceed to use the next lookup type gracefully when
+ an Exception is raised. Fixes ticket #4740.
+ """
+ silent_variable_failure = True
+
+#### OGR error checking codes and routine ####
+
+# OGR Error Codes
+OGRERR_DICT = { 1 : (OGRException, 'Not enough data.'),
+ 2 : (OGRException, 'Not enough memory.'),
+ 3 : (OGRException, 'Unsupported geometry type.'),
+ 4 : (OGRException, 'Unsupported operation.'),
+ 5 : (OGRException, 'Corrupt data.'),
+ 6 : (OGRException, 'OGR failure.'),
+ 7 : (SRSException, 'Unsupported SRS.'),
+ 8 : (OGRException, 'Invalid handle.'),
+ }
+OGRERR_NONE = 0
+
+def check_err(code):
+ "Checks the given OGRERR, and raises an exception where appropriate."
+
+ if code == OGRERR_NONE:
+ return
+ elif code in OGRERR_DICT:
+ e, msg = OGRERR_DICT[code]
+ raise e(msg)
+ else:
+ raise OGRException('Unknown error code: "%s"' % code)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/feature.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/feature.py
new file mode 100644
index 0000000..a11a687
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/feature.py
@@ -0,0 +1,124 @@
+# The GDAL C library, OGR exception, and the Field object
+from django.contrib.gis.gdal.base import GDALBase
+from django.contrib.gis.gdal.error import OGRException, OGRIndexError
+from django.contrib.gis.gdal.field import Field
+from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType
+
+# ctypes function prototypes
+from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api
+
+from django.utils.encoding import force_bytes, force_text
+from django.utils import six
+from django.utils.six.moves import xrange
+
+# For more information, see the OGR C API source code:
+# http://www.gdal.org/ogr/ogr__api_8h.html
+#
+# The OGR_F_* routines are relevant here.
+class Feature(GDALBase):
+ """
+ This class that wraps an OGR Feature, needs to be instantiated
+ from a Layer object.
+ """
+
+ #### Python 'magic' routines ####
+ def __init__(self, feat, layer):
+ """
+ Initializes Feature from a pointer and its Layer object.
+ """
+ if not feat:
+ raise OGRException('Cannot create OGR Feature, invalid pointer given.')
+ self.ptr = feat
+ self._layer = layer
+
+ def __del__(self):
+ "Releases a reference to this object."
+ if self._ptr: capi.destroy_feature(self._ptr)
+
+ def __getitem__(self, index):
+ """
+ Gets the Field object at the specified index, which may be either
+ an integer or the Field's string label. Note that the Field object
+ is not the field's _value_ -- use the `get` method instead to
+ retrieve the value (e.g. an integer) instead of a Field instance.
+ """
+ if isinstance(index, six.string_types):
+ i = self.index(index)
+ else:
+ if index < 0 or index > self.num_fields:
+ raise OGRIndexError('index out of range')
+ i = index
+ return Field(self, i)
+
+ def __iter__(self):
+ "Iterates over each field in the Feature."
+ for i in xrange(self.num_fields):
+ yield self[i]
+
+ def __len__(self):
+ "Returns the count of fields in this feature."
+ return self.num_fields
+
+ def __str__(self):
+ "The string name of the feature."
+ return 'Feature FID %d in Layer<%s>' % (self.fid, self.layer_name)
+
+ def __eq__(self, other):
+ "Does equivalence testing on the features."
+ return bool(capi.feature_equal(self.ptr, other._ptr))
+
+ #### Feature Properties ####
+ @property
+ def encoding(self):
+ return self._layer._ds.encoding
+
+ @property
+ def fid(self):
+ "Returns the feature identifier."
+ return capi.get_fid(self.ptr)
+
+ @property
+ def layer_name(self):
+ "Returns the name of the layer for the feature."
+ name = capi.get_feat_name(self._layer._ldefn)
+ return force_text(name, self.encoding, strings_only=True)
+
+ @property
+ def num_fields(self):
+ "Returns the number of fields in the Feature."
+ return capi.get_feat_field_count(self.ptr)
+
+ @property
+ def fields(self):
+ "Returns a list of fields in the Feature."
+ return [capi.get_field_name(capi.get_field_defn(self._layer._ldefn, i))
+ for i in xrange(self.num_fields)]
+
+ @property
+ def geom(self):
+ "Returns the OGR Geometry for this Feature."
+ # Retrieving the geometry pointer for the feature.
+ geom_ptr = capi.get_feat_geom_ref(self.ptr)
+ return OGRGeometry(geom_api.clone_geom(geom_ptr))
+
+ @property
+ def geom_type(self):
+ "Returns the OGR Geometry Type for this Feture."
+ return OGRGeomType(capi.get_fd_geom_type(self._layer._ldefn))
+
+ #### Feature Methods ####
+ def get(self, field):
+ """
+ Returns the value of the field, instead of an instance of the Field
+ object. May take a string of the field name or a Field object as
+ parameters.
+ """
+ field_name = getattr(field, 'name', field)
+ return self[field_name].value
+
+ def index(self, field_name):
+ "Returns the index of the given field name."
+ i = capi.get_field_index(self.ptr, force_bytes(field_name))
+ if i < 0:
+ raise OGRIndexError('invalid OFT field name given: "%s"' % field_name)
+ return i
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/field.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/field.py
new file mode 100644
index 0000000..2415f32
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/field.py
@@ -0,0 +1,194 @@
+from ctypes import byref, c_int
+from datetime import date, datetime, time
+from django.contrib.gis.gdal.base import GDALBase
+from django.contrib.gis.gdal.error import OGRException
+from django.contrib.gis.gdal.prototypes import ds as capi
+from django.utils.encoding import force_text
+
+
+# For more information, see the OGR C API source code:
+# http://www.gdal.org/ogr/ogr__api_8h.html
+#
+# The OGR_Fld_* routines are relevant here.
+class Field(GDALBase):
+ """
+ This class wraps an OGR Field, and needs to be instantiated
+ from a Feature object.
+ """
+
+ #### Python 'magic' routines ####
+ def __init__(self, feat, index):
+ """
+ Initializes on the feature object and the integer index of
+ the field within the feature.
+ """
+ # Setting the feature pointer and index.
+ self._feat = feat
+ self._index = index
+
+ # Getting the pointer for this field.
+ fld_ptr = capi.get_feat_field_defn(feat.ptr, index)
+ if not fld_ptr:
+ raise OGRException('Cannot create OGR Field, invalid pointer given.')
+ self.ptr = fld_ptr
+
+ # Setting the class depending upon the OGR Field Type (OFT)
+ self.__class__ = OGRFieldTypes[self.type]
+
+ # OFTReal with no precision should be an OFTInteger.
+ if isinstance(self, OFTReal) and self.precision == 0:
+ self.__class__ = OFTInteger
+ self._double = True
+
+ def __str__(self):
+ "Returns the string representation of the Field."
+ return str(self.value).strip()
+
+ #### Field Methods ####
+ def as_double(self):
+ "Retrieves the Field's value as a double (float)."
+ return capi.get_field_as_double(self._feat.ptr, self._index)
+
+ def as_int(self):
+ "Retrieves the Field's value as an integer."
+ return capi.get_field_as_integer(self._feat.ptr, self._index)
+
+ def as_string(self):
+ "Retrieves the Field's value as a string."
+ string = capi.get_field_as_string(self._feat.ptr, self._index)
+ return force_text(string, encoding=self._feat.encoding, strings_only=True)
+
+ def as_datetime(self):
+ "Retrieves the Field's value as a tuple of date & time components."
+ yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)]
+ status = capi.get_field_as_datetime(
+ self._feat.ptr, self._index, byref(yy), byref(mm), byref(dd),
+ byref(hh), byref(mn), byref(ss), byref(tz))
+ if status:
+ return (yy, mm, dd, hh, mn, ss, tz)
+ else:
+ raise OGRException('Unable to retrieve date & time information from the field.')
+
+ #### Field Properties ####
+ @property
+ def name(self):
+ "Returns the name of this Field."
+ name = capi.get_field_name(self.ptr)
+ return force_text(name, encoding=self._feat.encoding, strings_only=True)
+
+ @property
+ def precision(self):
+ "Returns the precision of this Field."
+ return capi.get_field_precision(self.ptr)
+
+ @property
+ def type(self):
+ "Returns the OGR type of this Field."
+ return capi.get_field_type(self.ptr)
+
+ @property
+ def type_name(self):
+ "Return the OGR field type name for this Field."
+ return capi.get_field_type_name(self.type)
+
+ @property
+ def value(self):
+ "Returns the value of this Field."
+ # Default is to get the field as a string.
+ return self.as_string()
+
+ @property
+ def width(self):
+ "Returns the width of this Field."
+ return capi.get_field_width(self.ptr)
+
+### The Field sub-classes for each OGR Field type. ###
+class OFTInteger(Field):
+ _double = False
+
+ @property
+ def value(self):
+ "Returns an integer contained in this field."
+ if self._double:
+ # If this is really from an OFTReal field with no precision,
+ # read as a double and cast as Python int (to prevent overflow).
+ return int(self.as_double())
+ else:
+ return self.as_int()
+
+ @property
+ def type(self):
+ """
+ GDAL uses OFTReals to represent OFTIntegers in created
+ shapefiles -- forcing the type here since the underlying field
+ type may actually be OFTReal.
+ """
+ return 0
+
+class OFTReal(Field):
+ @property
+ def value(self):
+ "Returns a float contained in this field."
+ return self.as_double()
+
+# String & Binary fields, just subclasses
+class OFTString(Field): pass
+class OFTWideString(Field): pass
+class OFTBinary(Field): pass
+
+# OFTDate, OFTTime, OFTDateTime fields.
+class OFTDate(Field):
+ @property
+ def value(self):
+ "Returns a Python `date` object for the OFTDate field."
+ try:
+ yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
+ return date(yy.value, mm.value, dd.value)
+ except (ValueError, OGRException):
+ return None
+
+class OFTDateTime(Field):
+ @property
+ def value(self):
+ "Returns a Python `datetime` object for this OFTDateTime field."
+ # TODO: Adapt timezone information.
+ # See http://lists.osgeo.org/pipermail/gdal-dev/2006-February/007990.html
+ # The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous),
+ # 100=GMT, 104=GMT+1, 80=GMT-5, etc.
+ try:
+ yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
+ return datetime(yy.value, mm.value, dd.value, hh.value, mn.value, ss.value)
+ except (ValueError, OGRException):
+ return None
+
+class OFTTime(Field):
+ @property
+ def value(self):
+ "Returns a Python `time` object for this OFTTime field."
+ try:
+ yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
+ return time(hh.value, mn.value, ss.value)
+ except (ValueError, OGRException):
+ return None
+
+# List fields are also just subclasses
+class OFTIntegerList(Field): pass
+class OFTRealList(Field): pass
+class OFTStringList(Field): pass
+class OFTWideStringList(Field): pass
+
+# Class mapping dictionary for OFT Types and reverse mapping.
+OGRFieldTypes = { 0 : OFTInteger,
+ 1 : OFTIntegerList,
+ 2 : OFTReal,
+ 3 : OFTRealList,
+ 4 : OFTString,
+ 5 : OFTStringList,
+ 6 : OFTWideString,
+ 7 : OFTWideStringList,
+ 8 : OFTBinary,
+ 9 : OFTDate,
+ 10 : OFTTime,
+ 11 : OFTDateTime,
+ }
+ROGRFieldTypes = dict([(cls, num) for num, cls in OGRFieldTypes.items()])
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/geometries.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/geometries.py
new file mode 100644
index 0000000..0d75620
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/geometries.py
@@ -0,0 +1,726 @@
+"""
+ The OGRGeometry is a wrapper for using the OGR Geometry class
+ (see http://www.gdal.org/ogr/classOGRGeometry.html). OGRGeometry
+ may be instantiated when reading geometries from OGR Data Sources
+ (e.g. SHP files), or when given OGC WKT (a string).
+
+ While the 'full' API is not present yet, the API is "pythonic" unlike
+ the traditional and "next-generation" OGR Python bindings. One major
+ advantage OGR Geometries have over their GEOS counterparts is support
+ for spatial reference systems and their transformation.
+
+ Example:
+ >>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference
+ >>> wkt1, wkt2 = 'POINT(-90 30)', 'POLYGON((0 0, 5 0, 5 5, 0 5)'
+ >>> pnt = OGRGeometry(wkt1)
+ >>> print(pnt)
+ POINT (-90 30)
+ >>> mpnt = OGRGeometry(OGRGeomType('MultiPoint'), SpatialReference('WGS84'))
+ >>> mpnt.add(wkt1)
+ >>> mpnt.add(wkt1)
+ >>> print(mpnt)
+ MULTIPOINT (-90 30,-90 30)
+ >>> print(mpnt.srs.name)
+ WGS 84
+ >>> print(mpnt.srs.proj)
+ +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
+ >>> mpnt.transform_to(SpatialReference('NAD27'))
+ >>> print(mpnt.proj)
+ +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs
+ >>> print(mpnt)
+ MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641)
+
+ The OGRGeomType class is to make it easy to specify an OGR geometry type:
+ >>> from django.contrib.gis.gdal import OGRGeomType
+ >>> gt1 = OGRGeomType(3) # Using an integer for the type
+ >>> gt2 = OGRGeomType('Polygon') # Using a string
+ >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive
+ >>> print(gt1 == 3, gt1 == 'Polygon') # Equivalence works w/non-OGRGeomType objects
+ True True
+"""
+# Python library requisites.
+import sys
+from binascii import a2b_hex, b2a_hex
+from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p
+
+from django.contrib.gis import memoryview
+
+# Getting GDAL prerequisites
+from django.contrib.gis.gdal.base import GDALBase
+from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
+from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException
+from django.contrib.gis.gdal.geomtype import OGRGeomType
+from django.contrib.gis.gdal.libgdal import GDAL_VERSION
+from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
+
+# Getting the ctypes prototype functions that interface w/the GDAL C library.
+from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
+
+# For recognizing geometry input.
+from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
+
+from django.utils import six
+from django.utils.six.moves import xrange
+
+# For more information, see the OGR C API source code:
+# http://www.gdal.org/ogr/ogr__api_8h.html
+#
+# The OGR_G_* routines are relevant here.
+
+#### OGRGeometry Class ####
+class OGRGeometry(GDALBase):
+ "Generally encapsulates an OGR geometry."
+
+ def __init__(self, geom_input, srs=None):
+ "Initializes Geometry on either WKT or an OGR pointer as input."
+
+ str_instance = isinstance(geom_input, six.string_types)
+
+ # If HEX, unpack input to a binary buffer.
+ if str_instance and hex_regex.match(geom_input):
+ geom_input = memoryview(a2b_hex(geom_input.upper().encode()))
+ str_instance = False
+
+ # Constructing the geometry,
+ if str_instance:
+ wkt_m = wkt_regex.match(geom_input)
+ json_m = json_regex.match(geom_input)
+ if wkt_m:
+ if wkt_m.group('srid'):
+ # If there's EWKT, set the SRS w/value of the SRID.
+ srs = int(wkt_m.group('srid'))
+ if wkt_m.group('type').upper() == 'LINEARRING':
+ # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT.
+ # See http://trac.osgeo.org/gdal/ticket/1992.
+ g = capi.create_geom(OGRGeomType(wkt_m.group('type')).num)
+ capi.import_wkt(g, byref(c_char_p(wkt_m.group('wkt').encode())))
+ else:
+ g = capi.from_wkt(byref(c_char_p(wkt_m.group('wkt').encode())), None, byref(c_void_p()))
+ elif json_m:
+ g = capi.from_json(geom_input.encode())
+ else:
+ # Seeing if the input is a valid short-hand string
+ # (e.g., 'Point', 'POLYGON').
+ ogr_t = OGRGeomType(geom_input)
+ g = capi.create_geom(OGRGeomType(geom_input).num)
+ elif isinstance(geom_input, memoryview):
+ # WKB was passed in
+ g = capi.from_wkb(bytes(geom_input), None, byref(c_void_p()), len(geom_input))
+ elif isinstance(geom_input, OGRGeomType):
+ # OGRGeomType was passed in, an empty geometry will be created.
+ g = capi.create_geom(geom_input.num)
+ elif isinstance(geom_input, self.ptr_type):
+ # OGR pointer (c_void_p) was the input.
+ g = geom_input
+ else:
+ raise OGRException('Invalid input type for OGR Geometry construction: %s' % type(geom_input))
+
+ # Now checking the Geometry pointer before finishing initialization
+ # by setting the pointer for the object.
+ if not g:
+ raise OGRException('Cannot create OGR Geometry from input: %s' % str(geom_input))
+ self.ptr = g
+
+ # Assigning the SpatialReference object to the geometry, if valid.
+ if bool(srs): self.srs = srs
+
+ # Setting the class depending upon the OGR Geometry Type
+ self.__class__ = GEO_CLASSES[self.geom_type.num]
+
+ def __del__(self):
+ "Deletes this Geometry."
+ if self._ptr: capi.destroy_geom(self._ptr)
+
+ # Pickle routines
+ def __getstate__(self):
+ srs = self.srs
+ if srs:
+ srs = srs.wkt
+ else:
+ srs = None
+ return bytes(self.wkb), srs
+
+ def __setstate__(self, state):
+ wkb, srs = state
+ ptr = capi.from_wkb(wkb, None, byref(c_void_p()), len(wkb))
+ if not ptr: raise OGRException('Invalid OGRGeometry loaded from pickled state.')
+ self.ptr = ptr
+ self.srs = srs
+
+ @classmethod
+ def from_bbox(cls, bbox):
+ "Constructs a Polygon from a bounding box (4-tuple)."
+ x0, y0, x1, y1 = bbox
+ return OGRGeometry( 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' % (
+ x0, y0, x0, y1, x1, y1, x1, y0, x0, y0) )
+
+ ### Geometry set-like operations ###
+ # g = g1 | g2
+ def __or__(self, other):
+ "Returns the union of the two geometries."
+ return self.union(other)
+
+ # g = g1 & g2
+ def __and__(self, other):
+ "Returns the intersection of this Geometry and the other."
+ return self.intersection(other)
+
+ # g = g1 - g2
+ def __sub__(self, other):
+ "Return the difference this Geometry and the other."
+ return self.difference(other)
+
+ # g = g1 ^ g2
+ def __xor__(self, other):
+ "Return the symmetric difference of this Geometry and the other."
+ return self.sym_difference(other)
+
+ def __eq__(self, other):
+ "Is this Geometry equal to the other?"
+ if isinstance(other, OGRGeometry):
+ return self.equals(other)
+ else:
+ return False
+
+ def __ne__(self, other):
+ "Tests for inequality."
+ return not (self == other)
+
+ def __str__(self):
+ "WKT is used for the string representation."
+ return self.wkt
+
+ #### Geometry Properties ####
+ @property
+ def dimension(self):
+ "Returns 0 for points, 1 for lines, and 2 for surfaces."
+ return capi.get_dims(self.ptr)
+
+ def _get_coord_dim(self):
+ "Returns the coordinate dimension of the Geometry."
+ if isinstance(self, GeometryCollection) and GDAL_VERSION < (1, 5, 2):
+ # On GDAL versions prior to 1.5.2, there exists a bug in which
+ # the coordinate dimension of geometry collections is always 2:
+ # http://trac.osgeo.org/gdal/ticket/2334
+ # Here we workaround by returning the coordinate dimension of the
+ # first geometry in the collection instead.
+ if len(self):
+ return capi.get_coord_dim(capi.get_geom_ref(self.ptr, 0))
+ return capi.get_coord_dim(self.ptr)
+
+ def _set_coord_dim(self, dim):
+ "Sets the coordinate dimension of this Geometry."
+ if not dim in (2, 3):
+ raise ValueError('Geometry dimension must be either 2 or 3')
+ capi.set_coord_dim(self.ptr, dim)
+
+ coord_dim = property(_get_coord_dim, _set_coord_dim)
+
+ @property
+ def geom_count(self):
+ "The number of elements in this Geometry."
+ return capi.get_geom_count(self.ptr)
+
+ @property
+ def point_count(self):
+ "Returns the number of Points in this Geometry."
+ return capi.get_point_count(self.ptr)
+
+ @property
+ def num_points(self):
+ "Alias for `point_count` (same name method in GEOS API.)"
+ return self.point_count
+
+ @property
+ def num_coords(self):
+ "Alais for `point_count`."
+ return self.point_count
+
+ @property
+ def geom_type(self):
+ "Returns the Type for this Geometry."
+ return OGRGeomType(capi.get_geom_type(self.ptr))
+
+ @property
+ def geom_name(self):
+ "Returns the Name of this Geometry."
+ return capi.get_geom_name(self.ptr)
+
+ @property
+ def area(self):
+ "Returns the area for a LinearRing, Polygon, or MultiPolygon; 0 otherwise."
+ return capi.get_area(self.ptr)
+
+ @property
+ def envelope(self):
+ "Returns the envelope for this Geometry."
+ # TODO: Fix Envelope() for Point geometries.
+ return Envelope(capi.get_envelope(self.ptr, byref(OGREnvelope())))
+
+ @property
+ def extent(self):
+ "Returns the envelope as a 4-tuple, instead of as an Envelope object."
+ return self.envelope.tuple
+
+ #### SpatialReference-related Properties ####
+
+ # The SRS property
+ def _get_srs(self):
+ "Returns the Spatial Reference for this Geometry."
+ try:
+ srs_ptr = capi.get_geom_srs(self.ptr)
+ return SpatialReference(srs_api.clone_srs(srs_ptr))
+ except SRSException:
+ return None
+
+ def _set_srs(self, srs):
+ "Sets the SpatialReference for this geometry."
+ # Do not have to clone the `SpatialReference` object pointer because
+ # when it is assigned to this `OGRGeometry` it's internal OGR
+ # reference count is incremented, and will likewise be released
+ # (decremented) when this geometry's destructor is called.
+ if isinstance(srs, SpatialReference):
+ srs_ptr = srs.ptr
+ elif isinstance(srs, six.integer_types + six.string_types):
+ sr = SpatialReference(srs)
+ srs_ptr = sr.ptr
+ else:
+ raise TypeError('Cannot assign spatial reference with object of type: %s' % type(srs))
+ capi.assign_srs(self.ptr, srs_ptr)
+
+ srs = property(_get_srs, _set_srs)
+
+ # The SRID property
+ def _get_srid(self):
+ srs = self.srs
+ if srs: return srs.srid
+ return None
+
+ def _set_srid(self, srid):
+ if isinstance(srid, six.integer_types):
+ self.srs = srid
+ else:
+ raise TypeError('SRID must be set with an integer.')
+
+ srid = property(_get_srid, _set_srid)
+
+ #### Output Methods ####
+ @property
+ def geos(self):
+ "Returns a GEOSGeometry object from this OGRGeometry."
+ from django.contrib.gis.geos import GEOSGeometry
+ return GEOSGeometry(self.wkb, self.srid)
+
+ @property
+ def gml(self):
+ "Returns the GML representation of the Geometry."
+ return capi.to_gml(self.ptr)
+
+ @property
+ def hex(self):
+ "Returns the hexadecimal representation of the WKB (a string)."
+ return b2a_hex(self.wkb).upper()
+
+ @property
+ def json(self):
+ """
+ Returns the GeoJSON representation of this Geometry.
+ """
+ return capi.to_json(self.ptr)
+ geojson = json
+
+ @property
+ def kml(self):
+ "Returns the KML representation of the Geometry."
+ return capi.to_kml(self.ptr, None)
+
+ @property
+ def wkb_size(self):
+ "Returns the size of the WKB buffer."
+ return capi.get_wkbsize(self.ptr)
+
+ @property
+ def wkb(self):
+ "Returns the WKB representation of the Geometry."
+ if sys.byteorder == 'little':
+ byteorder = 1 # wkbNDR (from ogr_core.h)
+ else:
+ byteorder = 0 # wkbXDR
+ sz = self.wkb_size
+ # Creating the unsigned character buffer, and passing it in by reference.
+ buf = (c_ubyte * sz)()
+ wkb = capi.to_wkb(self.ptr, byteorder, byref(buf))
+ # Returning a buffer of the string at the pointer.
+ return memoryview(string_at(buf, sz))
+
+ @property
+ def wkt(self):
+ "Returns the WKT representation of the Geometry."
+ return capi.to_wkt(self.ptr, byref(c_char_p()))
+
+ @property
+ def ewkt(self):
+ "Returns the EWKT representation of the Geometry."
+ srs = self.srs
+ if srs and srs.srid:
+ return 'SRID=%s;%s' % (srs.srid, self.wkt)
+ else:
+ return self.wkt
+
+ #### Geometry Methods ####
+ def clone(self):
+ "Clones this OGR Geometry."
+ return OGRGeometry(capi.clone_geom(self.ptr), self.srs)
+
+ def close_rings(self):
+ """
+ If there are any rings within this geometry that have not been
+ closed, this routine will do so by adding the starting point at the
+ end.
+ """
+ # Closing the open rings.
+ capi.geom_close_rings(self.ptr)
+
+ def transform(self, coord_trans, clone=False):
+ """
+ Transforms this geometry to a different spatial reference system.
+ May take a CoordTransform object, a SpatialReference object, string
+ WKT or PROJ.4, and/or an integer SRID. By default nothing is returned
+ and the geometry is transformed in-place. However, if the `clone`
+ keyword is set, then a transformed clone of this geometry will be
+ returned.
+ """
+ if clone:
+ klone = self.clone()
+ klone.transform(coord_trans)
+ return klone
+
+ # Have to get the coordinate dimension of the original geometry
+ # so it can be used to reset the transformed geometry's dimension
+ # afterwards. This is done because of GDAL bug (in versions prior
+ # to 1.7) that turns geometries 3D after transformation, see:
+ # http://trac.osgeo.org/gdal/changeset/17792
+ if GDAL_VERSION < (1, 7):
+ orig_dim = self.coord_dim
+
+ # Depending on the input type, use the appropriate OGR routine
+ # to perform the transformation.
+ if isinstance(coord_trans, CoordTransform):
+ capi.geom_transform(self.ptr, coord_trans.ptr)
+ elif isinstance(coord_trans, SpatialReference):
+ capi.geom_transform_to(self.ptr, coord_trans.ptr)
+ elif isinstance(coord_trans, six.integer_types + six.string_types):
+ sr = SpatialReference(coord_trans)
+ capi.geom_transform_to(self.ptr, sr.ptr)
+ else:
+ raise TypeError('Transform only accepts CoordTransform, '
+ 'SpatialReference, string, and integer objects.')
+
+ # Setting with original dimension, see comment above.
+ if GDAL_VERSION < (1, 7):
+ if isinstance(self, GeometryCollection):
+ # With geometry collections have to set dimension on
+ # each internal geometry reference, as the collection
+ # dimension isn't affected.
+ for i in xrange(len(self)):
+ internal_ptr = capi.get_geom_ref(self.ptr, i)
+ if orig_dim != capi.get_coord_dim(internal_ptr):
+ capi.set_coord_dim(internal_ptr, orig_dim)
+ else:
+ if self.coord_dim != orig_dim:
+ self.coord_dim = orig_dim
+
+ def transform_to(self, srs):
+ "For backwards-compatibility."
+ self.transform(srs)
+
+ #### Topology Methods ####
+ def _topology(self, func, other):
+ """A generalized function for topology operations, takes a GDAL function and
+ the other geometry to perform the operation on."""
+ if not isinstance(other, OGRGeometry):
+ raise TypeError('Must use another OGRGeometry object for topology operations!')
+
+ # Returning the output of the given function with the other geometry's
+ # pointer.
+ return func(self.ptr, other.ptr)
+
+ def intersects(self, other):
+ "Returns True if this geometry intersects with the other."
+ return self._topology(capi.ogr_intersects, other)
+
+ def equals(self, other):
+ "Returns True if this geometry is equivalent to the other."
+ return self._topology(capi.ogr_equals, other)
+
+ def disjoint(self, other):
+ "Returns True if this geometry and the other are spatially disjoint."
+ return self._topology(capi.ogr_disjoint, other)
+
+ def touches(self, other):
+ "Returns True if this geometry touches the other."
+ return self._topology(capi.ogr_touches, other)
+
+ def crosses(self, other):
+ "Returns True if this geometry crosses the other."
+ return self._topology(capi.ogr_crosses, other)
+
+ def within(self, other):
+ "Returns True if this geometry is within the other."
+ return self._topology(capi.ogr_within, other)
+
+ def contains(self, other):
+ "Returns True if this geometry contains the other."
+ return self._topology(capi.ogr_contains, other)
+
+ def overlaps(self, other):
+ "Returns True if this geometry overlaps the other."
+ return self._topology(capi.ogr_overlaps, other)
+
+ #### Geometry-generation Methods ####
+ def _geomgen(self, gen_func, other=None):
+ "A helper routine for the OGR routines that generate geometries."
+ if isinstance(other, OGRGeometry):
+ return OGRGeometry(gen_func(self.ptr, other.ptr), self.srs)
+ else:
+ return OGRGeometry(gen_func(self.ptr), self.srs)
+
+ @property
+ def boundary(self):
+ "Returns the boundary of this geometry."
+ return self._geomgen(capi.get_boundary)
+
+ @property
+ def convex_hull(self):
+ """
+ Returns the smallest convex Polygon that contains all the points in
+ this Geometry.
+ """
+ return self._geomgen(capi.geom_convex_hull)
+
+ def difference(self, other):
+ """
+ Returns a new geometry consisting of the region which is the difference
+ of this geometry and the other.
+ """
+ return self._geomgen(capi.geom_diff, other)
+
+ def intersection(self, other):
+ """
+ Returns a new geometry consisting of the region of intersection of this
+ geometry and the other.
+ """
+ return self._geomgen(capi.geom_intersection, other)
+
+ def sym_difference(self, other):
+ """
+ Returns a new geometry which is the symmetric difference of this
+ geometry and the other.
+ """
+ return self._geomgen(capi.geom_sym_diff, other)
+
+ def union(self, other):
+ """
+ Returns a new geometry consisting of the region which is the union of
+ this geometry and the other.
+ """
+ return self._geomgen(capi.geom_union, other)
+
+# The subclasses for OGR Geometry.
+class Point(OGRGeometry):
+
+ @property
+ def x(self):
+ "Returns the X coordinate for this Point."
+ return capi.getx(self.ptr, 0)
+
+ @property
+ def y(self):
+ "Returns the Y coordinate for this Point."
+ return capi.gety(self.ptr, 0)
+
+ @property
+ def z(self):
+ "Returns the Z coordinate for this Point."
+ if self.coord_dim == 3:
+ return capi.getz(self.ptr, 0)
+
+ @property
+ def tuple(self):
+ "Returns the tuple of this point."
+ if self.coord_dim == 2:
+ return (self.x, self.y)
+ elif self.coord_dim == 3:
+ return (self.x, self.y, self.z)
+ coords = tuple
+
+class LineString(OGRGeometry):
+
+ def __getitem__(self, index):
+ "Returns the Point at the given index."
+ if index >= 0 and index < self.point_count:
+ x, y, z = c_double(), c_double(), c_double()
+ capi.get_point(self.ptr, index, byref(x), byref(y), byref(z))
+ dim = self.coord_dim
+ if dim == 1:
+ return (x.value,)
+ elif dim == 2:
+ return (x.value, y.value)
+ elif dim == 3:
+ return (x.value, y.value, z.value)
+ else:
+ raise OGRIndexError('index out of range: %s' % str(index))
+
+ def __iter__(self):
+ "Iterates over each point in the LineString."
+ for i in xrange(self.point_count):
+ yield self[i]
+
+ def __len__(self):
+ "The length returns the number of points in the LineString."
+ return self.point_count
+
+ @property
+ def tuple(self):
+ "Returns the tuple representation of this LineString."
+ return tuple([self[i] for i in xrange(len(self))])
+ coords = tuple
+
+ def _listarr(self, func):
+ """
+ Internal routine that returns a sequence (list) corresponding with
+ the given function.
+ """
+ return [func(self.ptr, i) for i in xrange(len(self))]
+
+ @property
+ def x(self):
+ "Returns the X coordinates in a list."
+ return self._listarr(capi.getx)
+
+ @property
+ def y(self):
+ "Returns the Y coordinates in a list."
+ return self._listarr(capi.gety)
+
+ @property
+ def z(self):
+ "Returns the Z coordinates in a list."
+ if self.coord_dim == 3:
+ return self._listarr(capi.getz)
+
+# LinearRings are used in Polygons.
+class LinearRing(LineString): pass
+
+class Polygon(OGRGeometry):
+
+ def __len__(self):
+ "The number of interior rings in this Polygon."
+ return self.geom_count
+
+ def __iter__(self):
+ "Iterates through each ring in the Polygon."
+ for i in xrange(self.geom_count):
+ yield self[i]
+
+ def __getitem__(self, index):
+ "Gets the ring at the specified index."
+ if index < 0 or index >= self.geom_count:
+ raise OGRIndexError('index out of range: %s' % index)
+ else:
+ return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs)
+
+ # Polygon Properties
+ @property
+ def shell(self):
+ "Returns the shell of this Polygon."
+ return self[0] # First ring is the shell
+ exterior_ring = shell
+
+ @property
+ def tuple(self):
+ "Returns a tuple of LinearRing coordinate tuples."
+ return tuple([self[i].tuple for i in xrange(self.geom_count)])
+ coords = tuple
+
+ @property
+ def point_count(self):
+ "The number of Points in this Polygon."
+ # Summing up the number of points in each ring of the Polygon.
+ return sum([self[i].point_count for i in xrange(self.geom_count)])
+
+ @property
+ def centroid(self):
+ "Returns the centroid (a Point) of this Polygon."
+ # The centroid is a Point, create a geometry for this.
+ p = OGRGeometry(OGRGeomType('Point'))
+ capi.get_centroid(self.ptr, p.ptr)
+ return p
+
+# Geometry Collection base class.
+class GeometryCollection(OGRGeometry):
+ "The Geometry Collection class."
+
+ def __getitem__(self, index):
+ "Gets the Geometry at the specified index."
+ if index < 0 or index >= self.geom_count:
+ raise OGRIndexError('index out of range: %s' % index)
+ else:
+ return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs)
+
+ def __iter__(self):
+ "Iterates over each Geometry."
+ for i in xrange(self.geom_count):
+ yield self[i]
+
+ def __len__(self):
+ "The number of geometries in this Geometry Collection."
+ return self.geom_count
+
+ def add(self, geom):
+ "Add the geometry to this Geometry Collection."
+ if isinstance(geom, OGRGeometry):
+ if isinstance(geom, self.__class__):
+ for g in geom: capi.add_geom(self.ptr, g.ptr)
+ else:
+ capi.add_geom(self.ptr, geom.ptr)
+ elif isinstance(geom, six.string_types):
+ tmp = OGRGeometry(geom)
+ capi.add_geom(self.ptr, tmp.ptr)
+ else:
+ raise OGRException('Must add an OGRGeometry.')
+
+ @property
+ def point_count(self):
+ "The number of Points in this Geometry Collection."
+ # Summing up the number of points in each geometry in this collection
+ return sum([self[i].point_count for i in xrange(self.geom_count)])
+
+ @property
+ def tuple(self):
+ "Returns a tuple representation of this Geometry Collection."
+ return tuple([self[i].tuple for i in xrange(self.geom_count)])
+ coords = tuple
+
+# Multiple Geometry types.
+class MultiPoint(GeometryCollection): pass
+class MultiLineString(GeometryCollection): pass
+class MultiPolygon(GeometryCollection): pass
+
+# Class mapping dictionary (using the OGRwkbGeometryType as the key)
+GEO_CLASSES = {1 : Point,
+ 2 : LineString,
+ 3 : Polygon,
+ 4 : MultiPoint,
+ 5 : MultiLineString,
+ 6 : MultiPolygon,
+ 7 : GeometryCollection,
+ 101: LinearRing,
+ 1 + OGRGeomType.wkb25bit : Point,
+ 2 + OGRGeomType.wkb25bit : LineString,
+ 3 + OGRGeomType.wkb25bit : Polygon,
+ 4 + OGRGeomType.wkb25bit : MultiPoint,
+ 5 + OGRGeomType.wkb25bit : MultiLineString,
+ 6 + OGRGeomType.wkb25bit : MultiPolygon,
+ 7 + OGRGeomType.wkb25bit : GeometryCollection,
+ }
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/geomtype.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/geomtype.py
new file mode 100644
index 0000000..fe4b89a
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/geomtype.py
@@ -0,0 +1,87 @@
+from django.contrib.gis.gdal.error import OGRException
+
+from django.utils import six
+
+#### OGRGeomType ####
+class OGRGeomType(object):
+ "Encapulates OGR Geometry Types."
+
+ wkb25bit = -2147483648
+
+ # Dictionary of acceptable OGRwkbGeometryType s and their string names.
+ _types = {0 : 'Unknown',
+ 1 : 'Point',
+ 2 : 'LineString',
+ 3 : 'Polygon',
+ 4 : 'MultiPoint',
+ 5 : 'MultiLineString',
+ 6 : 'MultiPolygon',
+ 7 : 'GeometryCollection',
+ 100 : 'None',
+ 101 : 'LinearRing',
+ 1 + wkb25bit: 'Point25D',
+ 2 + wkb25bit: 'LineString25D',
+ 3 + wkb25bit: 'Polygon25D',
+ 4 + wkb25bit: 'MultiPoint25D',
+ 5 + wkb25bit : 'MultiLineString25D',
+ 6 + wkb25bit : 'MultiPolygon25D',
+ 7 + wkb25bit : 'GeometryCollection25D',
+ }
+ # Reverse type dictionary, keyed by lower-case of the name.
+ _str_types = dict([(v.lower(), k) for k, v in _types.items()])
+
+ def __init__(self, type_input):
+ "Figures out the correct OGR Type based upon the input."
+ if isinstance(type_input, OGRGeomType):
+ num = type_input.num
+ elif isinstance(type_input, six.string_types):
+ type_input = type_input.lower()
+ if type_input == 'geometry': type_input='unknown'
+ num = self._str_types.get(type_input, None)
+ if num is None:
+ raise OGRException('Invalid OGR String Type "%s"' % type_input)
+ elif isinstance(type_input, int):
+ if not type_input in self._types:
+ raise OGRException('Invalid OGR Integer Type: %d' % type_input)
+ num = type_input
+ else:
+ raise TypeError('Invalid OGR input type given.')
+
+ # Setting the OGR geometry type number.
+ self.num = num
+
+ def __str__(self):
+ "Returns the value of the name property."
+ return self.name
+
+ def __eq__(self, other):
+ """
+ Does an equivalence test on the OGR type with the given
+ other OGRGeomType, the short-hand string, or the integer.
+ """
+ if isinstance(other, OGRGeomType):
+ return self.num == other.num
+ elif isinstance(other, six.string_types):
+ return self.name.lower() == other.lower()
+ elif isinstance(other, int):
+ return self.num == other
+ else:
+ return False
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ @property
+ def name(self):
+ "Returns a short-hand string form of the OGR Geometry type."
+ return self._types[self.num]
+
+ @property
+ def django(self):
+ "Returns the Django GeometryField for this OGR Type."
+ s = self.name.replace('25D', '')
+ if s in ('LinearRing', 'None'):
+ return None
+ elif s == 'Unknown':
+ s = 'Geometry'
+ return s + 'Field'
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/layer.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/layer.py
new file mode 100644
index 0000000..7f935cd
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/layer.py
@@ -0,0 +1,218 @@
+# Needed ctypes routines
+from ctypes import c_double, byref
+
+# Other GDAL imports.
+from django.contrib.gis.gdal.base import GDALBase
+from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
+from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException
+from django.contrib.gis.gdal.feature import Feature
+from django.contrib.gis.gdal.field import OGRFieldTypes
+from django.contrib.gis.gdal.geomtype import OGRGeomType
+from django.contrib.gis.gdal.geometries import OGRGeometry
+from django.contrib.gis.gdal.srs import SpatialReference
+
+# GDAL ctypes function prototypes.
+from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api, srs as srs_api
+
+from django.utils.encoding import force_bytes, force_text
+from django.utils import six
+from django.utils.six.moves import xrange
+
+# For more information, see the OGR C API source code:
+# http://www.gdal.org/ogr/ogr__api_8h.html
+#
+# The OGR_L_* routines are relevant here.
+class Layer(GDALBase):
+ "A class that wraps an OGR Layer, needs to be instantiated from a DataSource object."
+
+ #### Python 'magic' routines ####
+ def __init__(self, layer_ptr, ds):
+ """
+ Initializes on an OGR C pointer to the Layer and the `DataSource` object
+ that owns this layer. The `DataSource` object is required so that a
+ reference to it is kept with this Layer. This prevents garbage
+ collection of the `DataSource` while this Layer is still active.
+ """
+ if not layer_ptr:
+ raise OGRException('Cannot create Layer, invalid pointer given')
+ self.ptr = layer_ptr
+ self._ds = ds
+ self._ldefn = capi.get_layer_defn(self._ptr)
+ # Does the Layer support random reading?
+ self._random_read = self.test_capability(b'RandomRead')
+
+ def __getitem__(self, index):
+ "Gets the Feature at the specified index."
+ if isinstance(index, six.integer_types):
+ # An integer index was given -- we cannot do a check based on the
+ # number of features because the beginning and ending feature IDs
+ # are not guaranteed to be 0 and len(layer)-1, respectively.
+ if index < 0: raise OGRIndexError('Negative indices are not allowed on OGR Layers.')
+ return self._make_feature(index)
+ elif isinstance(index, slice):
+ # A slice was given
+ start, stop, stride = index.indices(self.num_feat)
+ return [self._make_feature(fid) for fid in xrange(start, stop, stride)]
+ else:
+ raise TypeError('Integers and slices may only be used when indexing OGR Layers.')
+
+ def __iter__(self):
+ "Iterates over each Feature in the Layer."
+ # ResetReading() must be called before iteration is to begin.
+ capi.reset_reading(self._ptr)
+ for i in xrange(self.num_feat):
+ yield Feature(capi.get_next_feature(self._ptr), self)
+
+ def __len__(self):
+ "The length is the number of features."
+ return self.num_feat
+
+ def __str__(self):
+ "The string name of the layer."
+ return self.name
+
+ def _make_feature(self, feat_id):
+ """
+ Helper routine for __getitem__ that constructs a Feature from the given
+ Feature ID. If the OGR Layer does not support random-access reading,
+ then each feature of the layer will be incremented through until the
+ a Feature is found matching the given feature ID.
+ """
+ if self._random_read:
+ # If the Layer supports random reading, return.
+ try:
+ return Feature(capi.get_feature(self.ptr, feat_id), self)
+ except OGRException:
+ pass
+ else:
+ # Random access isn't supported, have to increment through
+ # each feature until the given feature ID is encountered.
+ for feat in self:
+ if feat.fid == feat_id: return feat
+ # Should have returned a Feature, raise an OGRIndexError.
+ raise OGRIndexError('Invalid feature id: %s.' % feat_id)
+
+ #### Layer properties ####
+ @property
+ def extent(self):
+ "Returns the extent (an Envelope) of this layer."
+ env = OGREnvelope()
+ capi.get_extent(self.ptr, byref(env), 1)
+ return Envelope(env)
+
+ @property
+ def name(self):
+ "Returns the name of this layer in the Data Source."
+ name = capi.get_fd_name(self._ldefn)
+ return force_text(name, self._ds.encoding, strings_only=True)
+
+ @property
+ def num_feat(self, force=1):
+ "Returns the number of features in the Layer."
+ return capi.get_feature_count(self.ptr, force)
+
+ @property
+ def num_fields(self):
+ "Returns the number of fields in the Layer."
+ return capi.get_field_count(self._ldefn)
+
+ @property
+ def geom_type(self):
+ "Returns the geometry type (OGRGeomType) of the Layer."
+ return OGRGeomType(capi.get_fd_geom_type(self._ldefn))
+
+ @property
+ def srs(self):
+ "Returns the Spatial Reference used in this Layer."
+ try:
+ ptr = capi.get_layer_srs(self.ptr)
+ return SpatialReference(srs_api.clone_srs(ptr))
+ except SRSException:
+ return None
+
+ @property
+ def fields(self):
+ """
+ Returns a list of string names corresponding to each of the Fields
+ available in this Layer.
+ """
+ return [force_text(capi.get_field_name(capi.get_field_defn(self._ldefn, i)),
+ self._ds.encoding, strings_only=True)
+ for i in xrange(self.num_fields)]
+
+ @property
+ def field_types(self):
+ """
+ Returns a list of the types of fields in this Layer. For example,
+ the list [OFTInteger, OFTReal, OFTString] would be returned for
+ an OGR layer that had an integer, a floating-point, and string
+ fields.
+ """
+ return [OGRFieldTypes[capi.get_field_type(capi.get_field_defn(self._ldefn, i))]
+ for i in xrange(self.num_fields)]
+
+ @property
+ def field_widths(self):
+ "Returns a list of the maximum field widths for the features."
+ return [capi.get_field_width(capi.get_field_defn(self._ldefn, i))
+ for i in xrange(self.num_fields)]
+
+ @property
+ def field_precisions(self):
+ "Returns the field precisions for the features."
+ return [capi.get_field_precision(capi.get_field_defn(self._ldefn, i))
+ for i in xrange(self.num_fields)]
+
+ def _get_spatial_filter(self):
+ try:
+ return OGRGeometry(geom_api.clone_geom(capi.get_spatial_filter(self.ptr)))
+ except OGRException:
+ return None
+
+ def _set_spatial_filter(self, filter):
+ if isinstance(filter, OGRGeometry):
+ capi.set_spatial_filter(self.ptr, filter.ptr)
+ elif isinstance(filter, (tuple, list)):
+ if not len(filter) == 4:
+ raise ValueError('Spatial filter list/tuple must have 4 elements.')
+ # Map c_double onto params -- if a bad type is passed in it
+ # will be caught here.
+ xmin, ymin, xmax, ymax = map(c_double, filter)
+ capi.set_spatial_filter_rect(self.ptr, xmin, ymin, xmax, ymax)
+ elif filter is None:
+ capi.set_spatial_filter(self.ptr, None)
+ else:
+ raise TypeError('Spatial filter must be either an OGRGeometry instance, a 4-tuple, or None.')
+
+ spatial_filter = property(_get_spatial_filter, _set_spatial_filter)
+
+ #### Layer Methods ####
+ def get_fields(self, field_name):
+ """
+ Returns a list containing the given field name for every Feature
+ in the Layer.
+ """
+ if not field_name in self.fields:
+ raise OGRException('invalid field name: %s' % field_name)
+ return [feat.get(field_name) for feat in self]
+
+ def get_geoms(self, geos=False):
+ """
+ Returns a list containing the OGRGeometry for every Feature in
+ the Layer.
+ """
+ if geos:
+ from django.contrib.gis.geos import GEOSGeometry
+ return [GEOSGeometry(feat.geom.wkb) for feat in self]
+ else:
+ return [feat.geom for feat in self]
+
+ def test_capability(self, capability):
+ """
+ Returns a bool indicating whether the this Layer supports the given
+ capability (a string). Valid capability strings include:
+ 'RandomRead', 'SequentialWrite', 'RandomWrite', 'FastSpatialFilter',
+ 'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions',
+ 'DeleteFeature', and 'FastSetNextByIndex'.
+ """
+ return bool(capi.test_capability(self.ptr, force_bytes(capability)))
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/libgdal.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/libgdal.py
new file mode 100644
index 0000000..91f8d61
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/libgdal.py
@@ -0,0 +1,109 @@
+from __future__ import unicode_literals
+
+import logging
+import os
+import re
+from ctypes import c_char_p, c_int, CDLL, CFUNCTYPE
+from ctypes.util import find_library
+
+from django.contrib.gis.gdal.error import OGRException
+from django.core.exceptions import ImproperlyConfigured
+
+logger = logging.getLogger('django.contrib.gis')
+
+# Custom library path set?
+try:
+ from django.conf import settings
+ lib_path = settings.GDAL_LIBRARY_PATH
+except (AttributeError, EnvironmentError,
+ ImportError, ImproperlyConfigured):
+ lib_path = None
+
+if lib_path:
+ lib_names = None
+elif os.name == 'nt':
+ # Windows NT shared libraries
+ lib_names = ['gdal19', 'gdal18', 'gdal17', 'gdal16', 'gdal15']
+elif os.name == 'posix':
+ # *NIX library names.
+ lib_names = ['gdal', 'GDAL', 'gdal1.9.0', 'gdal1.8.0', 'gdal1.7.0',
+ 'gdal1.6.0', 'gdal1.5.0']
+else:
+ raise OGRException('Unsupported OS "%s"' % os.name)
+
+# Using the ctypes `find_library` utility to find the
+# path to the GDAL library from the list of library names.
+if lib_names:
+ for lib_name in lib_names:
+ lib_path = find_library(lib_name)
+ if not lib_path is None: break
+
+if lib_path is None:
+ raise OGRException('Could not find the GDAL library (tried "%s"). '
+ 'Try setting GDAL_LIBRARY_PATH in your settings.' %
+ '", "'.join(lib_names))
+
+# This loads the GDAL/OGR C library
+lgdal = CDLL(lib_path)
+
+# On Windows, the GDAL binaries have some OSR routines exported with
+# STDCALL, while others are not. Thus, the library will also need to
+# be loaded up as WinDLL for said OSR functions that require the
+# different calling convention.
+if os.name == 'nt':
+ from ctypes import WinDLL
+ lwingdal = WinDLL(lib_path)
+
+def std_call(func):
+ """
+ Returns the correct STDCALL function for certain OSR routines on Win32
+ platforms.
+ """
+ if os.name == 'nt':
+ return lwingdal[func]
+ else:
+ return lgdal[func]
+
+#### Version-information functions. ####
+
+# Returns GDAL library version information with the given key.
+_version_info = std_call('GDALVersionInfo')
+_version_info.argtypes = [c_char_p]
+_version_info.restype = c_char_p
+
+def gdal_version():
+ "Returns only the GDAL version number information."
+ return _version_info(b'RELEASE_NAME')
+
+def gdal_full_version():
+ "Returns the full GDAL version information."
+ return _version_info('')
+
+version_regex = re.compile(r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<subminor>\d+))?')
+def gdal_version_info():
+ ver = gdal_version().decode()
+ m = version_regex.match(ver)
+ if not m: raise OGRException('Could not parse GDAL version string "%s"' % ver)
+ return dict([(key, m.group(key)) for key in ('major', 'minor', 'subminor')])
+
+_verinfo = gdal_version_info()
+GDAL_MAJOR_VERSION = int(_verinfo['major'])
+GDAL_MINOR_VERSION = int(_verinfo['minor'])
+GDAL_SUBMINOR_VERSION = _verinfo['subminor'] and int(_verinfo['subminor'])
+GDAL_VERSION = (GDAL_MAJOR_VERSION, GDAL_MINOR_VERSION, GDAL_SUBMINOR_VERSION)
+del _verinfo
+
+# Set library error handling so as errors are logged
+CPLErrorHandler = CFUNCTYPE(None, c_int, c_int, c_char_p)
+def err_handler(error_class, error_number, message):
+ logger.error('GDAL_ERROR %d: %s' % (error_number, message))
+err_handler = CPLErrorHandler(err_handler)
+
+def function(name, args, restype):
+ func = std_call(name)
+ func.argtypes = args
+ func.restype = restype
+ return func
+
+set_error_handler = function('CPLSetErrorHandler', [CPLErrorHandler], CPLErrorHandler)
+set_error_handler(err_handler)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/__init__.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/__init__.py
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/ds.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/ds.py
new file mode 100644
index 0000000..f798069
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/ds.py
@@ -0,0 +1,70 @@
+"""
+ This module houses the ctypes function prototypes for OGR DataSource
+ related data structures. OGR_Dr_*, OGR_DS_*, OGR_L_*, OGR_F_*,
+ OGR_Fld_* routines are relevant here.
+"""
+from ctypes import c_char_p, c_double, c_int, c_long, c_void_p, POINTER
+from django.contrib.gis.gdal.envelope import OGREnvelope
+from django.contrib.gis.gdal.libgdal import lgdal
+from django.contrib.gis.gdal.prototypes.generation import (const_string_output,
+ double_output, geom_output, int_output, srs_output, void_output, voidptr_output)
+
+c_int_p = POINTER(c_int) # shortcut type
+
+### Driver Routines ###
+register_all = void_output(lgdal.OGRRegisterAll, [], errcheck=False)
+cleanup_all = void_output(lgdal.OGRCleanupAll, [], errcheck=False)
+get_driver = voidptr_output(lgdal.OGRGetDriver, [c_int])
+get_driver_by_name = voidptr_output(lgdal.OGRGetDriverByName, [c_char_p])
+get_driver_count = int_output(lgdal.OGRGetDriverCount, [])
+get_driver_name = const_string_output(lgdal.OGR_Dr_GetName, [c_void_p], decoding='ascii')
+
+### DataSource ###
+open_ds = voidptr_output(lgdal.OGROpen, [c_char_p, c_int, POINTER(c_void_p)])
+destroy_ds = void_output(lgdal.OGR_DS_Destroy, [c_void_p], errcheck=False)
+release_ds = void_output(lgdal.OGRReleaseDataSource, [c_void_p])
+get_ds_name = const_string_output(lgdal.OGR_DS_GetName, [c_void_p])
+get_layer = voidptr_output(lgdal.OGR_DS_GetLayer, [c_void_p, c_int])
+get_layer_by_name = voidptr_output(lgdal.OGR_DS_GetLayerByName, [c_void_p, c_char_p])
+get_layer_count = int_output(lgdal.OGR_DS_GetLayerCount, [c_void_p])
+
+### Layer Routines ###
+get_extent = void_output(lgdal.OGR_L_GetExtent, [c_void_p, POINTER(OGREnvelope), c_int])
+get_feature = voidptr_output(lgdal.OGR_L_GetFeature, [c_void_p, c_long])
+get_feature_count = int_output(lgdal.OGR_L_GetFeatureCount, [c_void_p, c_int])
+get_layer_defn = voidptr_output(lgdal.OGR_L_GetLayerDefn, [c_void_p])
+get_layer_srs = srs_output(lgdal.OGR_L_GetSpatialRef, [c_void_p])
+get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p])
+reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False)
+test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p])
+get_spatial_filter = geom_output(lgdal.OGR_L_GetSpatialFilter, [c_void_p])
+set_spatial_filter = void_output(lgdal.OGR_L_SetSpatialFilter, [c_void_p, c_void_p], errcheck=False)
+set_spatial_filter_rect = void_output(lgdal.OGR_L_SetSpatialFilterRect, [c_void_p, c_double, c_double, c_double, c_double], errcheck=False)
+
+### Feature Definition Routines ###
+get_fd_geom_type = int_output(lgdal.OGR_FD_GetGeomType, [c_void_p])
+get_fd_name = const_string_output(lgdal.OGR_FD_GetName, [c_void_p])
+get_feat_name = const_string_output(lgdal.OGR_FD_GetName, [c_void_p])
+get_field_count = int_output(lgdal.OGR_FD_GetFieldCount, [c_void_p])
+get_field_defn = voidptr_output(lgdal.OGR_FD_GetFieldDefn, [c_void_p, c_int])
+
+### Feature Routines ###
+clone_feature = voidptr_output(lgdal.OGR_F_Clone, [c_void_p])
+destroy_feature = void_output(lgdal.OGR_F_Destroy, [c_void_p], errcheck=False)
+feature_equal = int_output(lgdal.OGR_F_Equal, [c_void_p, c_void_p])
+get_feat_geom_ref = geom_output(lgdal.OGR_F_GetGeometryRef, [c_void_p])
+get_feat_field_count = int_output(lgdal.OGR_F_GetFieldCount, [c_void_p])
+get_feat_field_defn = voidptr_output(lgdal.OGR_F_GetFieldDefnRef, [c_void_p, c_int])
+get_fid = int_output(lgdal.OGR_F_GetFID, [c_void_p])
+get_field_as_datetime = int_output(lgdal.OGR_F_GetFieldAsDateTime, [c_void_p, c_int, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p, c_int_p])
+get_field_as_double = double_output(lgdal.OGR_F_GetFieldAsDouble, [c_void_p, c_int])
+get_field_as_integer = int_output(lgdal.OGR_F_GetFieldAsInteger, [c_void_p, c_int])
+get_field_as_string = const_string_output(lgdal.OGR_F_GetFieldAsString, [c_void_p, c_int])
+get_field_index = int_output(lgdal.OGR_F_GetFieldIndex, [c_void_p, c_char_p])
+
+### Field Routines ###
+get_field_name = const_string_output(lgdal.OGR_Fld_GetNameRef, [c_void_p])
+get_field_precision = int_output(lgdal.OGR_Fld_GetPrecision, [c_void_p])
+get_field_type = int_output(lgdal.OGR_Fld_GetType, [c_void_p])
+get_field_type_name = const_string_output(lgdal.OGR_GetFieldTypeName, [c_int])
+get_field_width = int_output(lgdal.OGR_Fld_GetWidth, [c_void_p])
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/errcheck.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/errcheck.py
new file mode 100644
index 0000000..2d27911
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/errcheck.py
@@ -0,0 +1,128 @@
+"""
+ This module houses the error-checking routines used by the GDAL
+ ctypes prototypes.
+"""
+from ctypes import c_void_p, string_at
+from django.contrib.gis.gdal.error import check_err, OGRException, SRSException
+from django.contrib.gis.gdal.libgdal import lgdal
+from django.utils import six
+
+# Helper routines for retrieving pointers and/or values from
+# arguments passed in by reference.
+def arg_byref(args, offset=-1):
+ "Returns the pointer argument's by-refernece value."
+ return args[offset]._obj.value
+
+def ptr_byref(args, offset=-1):
+ "Returns the pointer argument passed in by-reference."
+ return args[offset]._obj
+
+def check_bool(result, func, cargs):
+ "Returns the boolean evaluation of the value."
+ if bool(result): return True
+ else: return False
+
+### String checking Routines ###
+def check_const_string(result, func, cargs, offset=None):
+ """
+ Similar functionality to `check_string`, but does not free the pointer.
+ """
+ if offset:
+ check_err(result)
+ ptr = ptr_byref(cargs, offset)
+ return ptr.value
+ else:
+ return result
+
+def check_string(result, func, cargs, offset=-1, str_result=False):
+ """
+ Checks the string output returned from the given function, and frees
+ the string pointer allocated by OGR. The `str_result` keyword
+ may be used when the result is the string pointer, otherwise
+ the OGR error code is assumed. The `offset` keyword may be used
+ to extract the string pointer passed in by-reference at the given
+ slice offset in the function arguments.
+ """
+ if str_result:
+ # For routines that return a string.
+ ptr = result
+ if not ptr: s = None
+ else: s = string_at(result)
+ else:
+ # Error-code return specified.
+ check_err(result)
+ ptr = ptr_byref(cargs, offset)
+ # Getting the string value
+ s = ptr.value
+ # Correctly freeing the allocated memory beind GDAL pointer
+ # w/the VSIFree routine.
+ if ptr: lgdal.VSIFree(ptr)
+ return s
+
+### DataSource, Layer error-checking ###
+
+### Envelope checking ###
+def check_envelope(result, func, cargs, offset=-1):
+ "Checks a function that returns an OGR Envelope by reference."
+ env = ptr_byref(cargs, offset)
+ return env
+
+### Geometry error-checking routines ###
+def check_geom(result, func, cargs):
+ "Checks a function that returns a geometry."
+ # OGR_G_Clone may return an integer, even though the
+ # restype is set to c_void_p
+ if isinstance(result, six.integer_types):
+ result = c_void_p(result)
+ if not result:
+ raise OGRException('Invalid geometry pointer returned from "%s".' % func.__name__)
+ return result
+
+def check_geom_offset(result, func, cargs, offset=-1):
+ "Chcks the geometry at the given offset in the C parameter list."
+ check_err(result)
+ geom = ptr_byref(cargs, offset=offset)
+ return check_geom(geom, func, cargs)
+
+### Spatial Reference error-checking routines ###
+def check_srs(result, func, cargs):
+ if isinstance(result, six.integer_types):
+ result = c_void_p(result)
+ if not result:
+ raise SRSException('Invalid spatial reference pointer returned from "%s".' % func.__name__)
+ return result
+
+### Other error-checking routines ###
+def check_arg_errcode(result, func, cargs):
+ """
+ The error code is returned in the last argument, by reference.
+ Check its value with `check_err` before returning the result.
+ """
+ check_err(arg_byref(cargs))
+ return result
+
+def check_errcode(result, func, cargs):
+ """
+ Check the error code returned (c_int).
+ """
+ check_err(result)
+ return
+
+def check_pointer(result, func, cargs):
+ "Makes sure the result pointer is valid."
+ if isinstance(result, six.integer_types):
+ result = c_void_p(result)
+ if bool(result):
+ return result
+ else:
+ raise OGRException('Invalid pointer returned from "%s"' % func.__name__)
+
+def check_str_arg(result, func, cargs):
+ """
+ This is for the OSRGet[Angular|Linear]Units functions, which
+ require that the returned string pointer not be freed. This
+ returns both the double and tring values.
+ """
+ dbl = result
+ ptr = cargs[-1]._obj
+ return dbl, ptr.value.decode()
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/generation.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/generation.py
new file mode 100644
index 0000000..577d29b
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/generation.py
@@ -0,0 +1,125 @@
+"""
+ This module contains functions that generate ctypes prototypes for the
+ GDAL routines.
+"""
+
+from ctypes import c_char_p, c_double, c_int, c_void_p
+from django.contrib.gis.gdal.prototypes.errcheck import (
+ check_arg_errcode, check_errcode, check_geom, check_geom_offset,
+ check_pointer, check_srs, check_str_arg, check_string, check_const_string)
+
+class gdal_char_p(c_char_p):
+ pass
+
+def double_output(func, argtypes, errcheck=False, strarg=False):
+ "Generates a ctypes function that returns a double value."
+ func.argtypes = argtypes
+ func.restype = c_double
+ if errcheck: func.errcheck = check_arg_errcode
+ if strarg: func.errcheck = check_str_arg
+ return func
+
+def geom_output(func, argtypes, offset=None):
+ """
+ Generates a function that returns a Geometry either by reference
+ or directly (if the return_geom keyword is set to True).
+ """
+ # Setting the argument types
+ func.argtypes = argtypes
+
+ if not offset:
+ # When a geometry pointer is directly returned.
+ func.restype = c_void_p
+ func.errcheck = check_geom
+ else:
+ # Error code returned, geometry is returned by-reference.
+ func.restype = c_int
+ def geomerrcheck(result, func, cargs):
+ return check_geom_offset(result, func, cargs, offset)
+ func.errcheck = geomerrcheck
+
+ return func
+
+def int_output(func, argtypes):
+ "Generates a ctypes function that returns an integer value."
+ func.argtypes = argtypes
+ func.restype = c_int
+ return func
+
+def srs_output(func, argtypes):
+ """
+ Generates a ctypes prototype for the given function with
+ the given C arguments that returns a pointer to an OGR
+ Spatial Reference System.
+ """
+ func.argtypes = argtypes
+ func.restype = c_void_p
+ func.errcheck = check_srs
+ return func
+
+def const_string_output(func, argtypes, offset=None, decoding=None):
+ func.argtypes = argtypes
+ if offset:
+ func.restype = c_int
+ else:
+ func.restype = c_char_p
+
+ def _check_const(result, func, cargs):
+ res = check_const_string(result, func, cargs, offset=offset)
+ if res and decoding:
+ res = res.decode(decoding)
+ return res
+ func.errcheck = _check_const
+
+ return func
+
+def string_output(func, argtypes, offset=-1, str_result=False, decoding=None):
+ """
+ Generates a ctypes prototype for the given function with the
+ given argument types that returns a string from a GDAL pointer.
+ The `const` flag indicates whether the allocated pointer should
+ be freed via the GDAL library routine VSIFree -- but only applies
+ only when `str_result` is True.
+ """
+ func.argtypes = argtypes
+ if str_result:
+ # Use subclass of c_char_p so the error checking routine
+ # can free the memory at the pointer's address.
+ func.restype = gdal_char_p
+ else:
+ # Error code is returned
+ func.restype = c_int
+
+ # Dynamically defining our error-checking function with the
+ # given offset.
+ def _check_str(result, func, cargs):
+ res = check_string(result, func, cargs,
+ offset=offset, str_result=str_result)
+ if res and decoding:
+ res = res.decode(decoding)
+ return res
+ func.errcheck = _check_str
+ return func
+
+def void_output(func, argtypes, errcheck=True):
+ """
+ For functions that don't only return an error code that needs to
+ be examined.
+ """
+ if argtypes: func.argtypes = argtypes
+ if errcheck:
+ # `errcheck` keyword may be set to False for routines that
+ # return void, rather than a status code.
+ func.restype = c_int
+ func.errcheck = check_errcode
+ else:
+ func.restype = None
+
+ return func
+
+def voidptr_output(func, argtypes):
+ "For functions that return c_void_p."
+ func.argtypes = argtypes
+ func.restype = c_void_p
+ func.errcheck = check_pointer
+ return func
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/geom.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/geom.py
new file mode 100644
index 0000000..fa0b503
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/geom.py
@@ -0,0 +1,98 @@
+from ctypes import c_char_p, c_double, c_int, c_void_p, POINTER
+from django.contrib.gis.gdal.envelope import OGREnvelope
+from django.contrib.gis.gdal.libgdal import lgdal
+from django.contrib.gis.gdal.prototypes.errcheck import check_bool, check_envelope
+from django.contrib.gis.gdal.prototypes.generation import (const_string_output,
+ double_output, geom_output, int_output, srs_output, string_output, void_output)
+
+### Generation routines specific to this module ###
+def env_func(f, argtypes):
+ "For getting OGREnvelopes."
+ f.argtypes = argtypes
+ f.restype = None
+ f.errcheck = check_envelope
+ return f
+
+def pnt_func(f):
+ "For accessing point information."
+ return double_output(f, [c_void_p, c_int])
+
+def topology_func(f):
+ f.argtypes = [c_void_p, c_void_p]
+ f.restype = c_int
+ f.errchck = check_bool
+ return f
+
+### OGR_G ctypes function prototypes ###
+
+# GeoJSON routines.
+from_json = geom_output(lgdal.OGR_G_CreateGeometryFromJson, [c_char_p])
+to_json = string_output(lgdal.OGR_G_ExportToJson, [c_void_p], str_result=True, decoding='ascii')
+to_kml = string_output(lgdal.OGR_G_ExportToKML, [c_void_p, c_char_p], str_result=True, decoding='ascii')
+
+# GetX, GetY, GetZ all return doubles.
+getx = pnt_func(lgdal.OGR_G_GetX)
+gety = pnt_func(lgdal.OGR_G_GetY)
+getz = pnt_func(lgdal.OGR_G_GetZ)
+
+# Geometry creation routines.
+from_wkb = geom_output(lgdal.OGR_G_CreateFromWkb, [c_char_p, c_void_p, POINTER(c_void_p), c_int], offset=-2)
+from_wkt = geom_output(lgdal.OGR_G_CreateFromWkt, [POINTER(c_char_p), c_void_p, POINTER(c_void_p)], offset=-1)
+create_geom = geom_output(lgdal.OGR_G_CreateGeometry, [c_int])
+clone_geom = geom_output(lgdal.OGR_G_Clone, [c_void_p])
+get_geom_ref = geom_output(lgdal.OGR_G_GetGeometryRef, [c_void_p, c_int])
+get_boundary = geom_output(lgdal.OGR_G_GetBoundary, [c_void_p])
+geom_convex_hull = geom_output(lgdal.OGR_G_ConvexHull, [c_void_p])
+geom_diff = geom_output(lgdal.OGR_G_Difference, [c_void_p, c_void_p])
+geom_intersection = geom_output(lgdal.OGR_G_Intersection, [c_void_p, c_void_p])
+geom_sym_diff = geom_output(lgdal.OGR_G_SymmetricDifference, [c_void_p, c_void_p])
+geom_union = geom_output(lgdal.OGR_G_Union, [c_void_p, c_void_p])
+
+# Geometry modification routines.
+add_geom = void_output(lgdal.OGR_G_AddGeometry, [c_void_p, c_void_p])
+import_wkt = void_output(lgdal.OGR_G_ImportFromWkt, [c_void_p, POINTER(c_char_p)])
+
+# Destroys a geometry
+destroy_geom = void_output(lgdal.OGR_G_DestroyGeometry, [c_void_p], errcheck=False)
+
+# Geometry export routines.
+to_wkb = void_output(lgdal.OGR_G_ExportToWkb, None, errcheck=True) # special handling for WKB.
+to_wkt = string_output(lgdal.OGR_G_ExportToWkt, [c_void_p, POINTER(c_char_p)], decoding='ascii')
+to_gml = string_output(lgdal.OGR_G_ExportToGML, [c_void_p], str_result=True, decoding='ascii')
+get_wkbsize = int_output(lgdal.OGR_G_WkbSize, [c_void_p])
+
+# Geometry spatial-reference related routines.
+assign_srs = void_output(lgdal.OGR_G_AssignSpatialReference, [c_void_p, c_void_p], errcheck=False)
+get_geom_srs = srs_output(lgdal.OGR_G_GetSpatialReference, [c_void_p])
+
+# Geometry properties
+get_area = double_output(lgdal.OGR_G_GetArea, [c_void_p])
+get_centroid = void_output(lgdal.OGR_G_Centroid, [c_void_p, c_void_p])
+get_dims = int_output(lgdal.OGR_G_GetDimension, [c_void_p])
+get_coord_dim = int_output(lgdal.OGR_G_GetCoordinateDimension, [c_void_p])
+set_coord_dim = void_output(lgdal.OGR_G_SetCoordinateDimension, [c_void_p, c_int], errcheck=False)
+
+get_geom_count = int_output(lgdal.OGR_G_GetGeometryCount, [c_void_p])
+get_geom_name = const_string_output(lgdal.OGR_G_GetGeometryName, [c_void_p], decoding='ascii')
+get_geom_type = int_output(lgdal.OGR_G_GetGeometryType, [c_void_p])
+get_point_count = int_output(lgdal.OGR_G_GetPointCount, [c_void_p])
+get_point = void_output(lgdal.OGR_G_GetPoint, [c_void_p, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)], errcheck=False)
+geom_close_rings = void_output(lgdal.OGR_G_CloseRings, [c_void_p], errcheck=False)
+
+# Topology routines.
+ogr_contains = topology_func(lgdal.OGR_G_Contains)
+ogr_crosses = topology_func(lgdal.OGR_G_Crosses)
+ogr_disjoint = topology_func(lgdal.OGR_G_Disjoint)
+ogr_equals = topology_func(lgdal.OGR_G_Equals)
+ogr_intersects = topology_func(lgdal.OGR_G_Intersects)
+ogr_overlaps = topology_func(lgdal.OGR_G_Overlaps)
+ogr_touches = topology_func(lgdal.OGR_G_Touches)
+ogr_within = topology_func(lgdal.OGR_G_Within)
+
+# Transformation routines.
+geom_transform = void_output(lgdal.OGR_G_Transform, [c_void_p, c_void_p])
+geom_transform_to = void_output(lgdal.OGR_G_TransformTo, [c_void_p, c_void_p])
+
+# For retrieving the envelope of the geometry.
+get_envelope = env_func(lgdal.OGR_G_GetEnvelope, [c_void_p, POINTER(OGREnvelope)])
+
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/srs.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/srs.py
new file mode 100644
index 0000000..58ceb75
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/prototypes/srs.py
@@ -0,0 +1,71 @@
+from ctypes import c_char_p, c_int, c_void_p, POINTER
+from django.contrib.gis.gdal.libgdal import lgdal, std_call
+from django.contrib.gis.gdal.prototypes.generation import (const_string_output,
+ double_output, int_output, srs_output, string_output, void_output)
+
+## Shortcut generation for routines with known parameters.
+def srs_double(f):
+ """
+ Creates a function prototype for the OSR routines that take
+ the OSRSpatialReference object and
+ """
+ return double_output(f, [c_void_p, POINTER(c_int)], errcheck=True)
+
+def units_func(f):
+ """
+ Creates a ctypes function prototype for OSR units functions, e.g.,
+ OSRGetAngularUnits, OSRGetLinearUnits.
+ """
+ return double_output(f, [c_void_p, POINTER(c_char_p)], strarg=True)
+
+# Creation & destruction.
+clone_srs = srs_output(std_call('OSRClone'), [c_void_p])
+new_srs = srs_output(std_call('OSRNewSpatialReference'), [c_char_p])
+release_srs = void_output(lgdal.OSRRelease, [c_void_p], errcheck=False)
+destroy_srs = void_output(std_call('OSRDestroySpatialReference'), [c_void_p], errcheck=False)
+srs_validate = void_output(lgdal.OSRValidate, [c_void_p])
+
+# Getting the semi_major, semi_minor, and flattening functions.
+semi_major = srs_double(lgdal.OSRGetSemiMajor)
+semi_minor = srs_double(lgdal.OSRGetSemiMinor)
+invflattening = srs_double(lgdal.OSRGetInvFlattening)
+
+# WKT, PROJ, EPSG, XML importation routines.
+from_wkt = void_output(lgdal.OSRImportFromWkt, [c_void_p, POINTER(c_char_p)])
+from_proj = void_output(lgdal.OSRImportFromProj4, [c_void_p, c_char_p])
+from_epsg = void_output(std_call('OSRImportFromEPSG'), [c_void_p, c_int])
+from_xml = void_output(lgdal.OSRImportFromXML, [c_void_p, c_char_p])
+from_user_input = void_output(std_call('OSRSetFromUserInput'), [c_void_p, c_char_p])
+
+# Morphing to/from ESRI WKT.
+morph_to_esri = void_output(lgdal.OSRMorphToESRI, [c_void_p])
+morph_from_esri = void_output(lgdal.OSRMorphFromESRI, [c_void_p])
+
+# Identifying the EPSG
+identify_epsg = void_output(lgdal.OSRAutoIdentifyEPSG, [c_void_p])
+
+# Getting the angular_units, linear_units functions
+linear_units = units_func(lgdal.OSRGetLinearUnits)
+angular_units = units_func(lgdal.OSRGetAngularUnits)
+
+# For exporting to WKT, PROJ.4, "Pretty" WKT, and XML.
+to_wkt = string_output(std_call('OSRExportToWkt'), [c_void_p, POINTER(c_char_p)], decoding='ascii')
+to_proj = string_output(std_call('OSRExportToProj4'), [c_void_p, POINTER(c_char_p)], decoding='ascii')
+to_pretty_wkt = string_output(std_call('OSRExportToPrettyWkt'), [c_void_p, POINTER(c_char_p), c_int], offset=-2, decoding='ascii')
+
+# Memory leak fixed in GDAL 1.5; still exists in 1.4.
+to_xml = string_output(lgdal.OSRExportToXML, [c_void_p, POINTER(c_char_p), c_char_p], offset=-2, decoding='ascii')
+
+# String attribute retrival routines.
+get_attr_value = const_string_output(std_call('OSRGetAttrValue'), [c_void_p, c_char_p, c_int], decoding='ascii')
+get_auth_name = const_string_output(lgdal.OSRGetAuthorityName, [c_void_p, c_char_p], decoding='ascii')
+get_auth_code = const_string_output(lgdal.OSRGetAuthorityCode, [c_void_p, c_char_p], decoding='ascii')
+
+# SRS Properties
+isgeographic = int_output(lgdal.OSRIsGeographic, [c_void_p])
+islocal = int_output(lgdal.OSRIsLocal, [c_void_p])
+isprojected = int_output(lgdal.OSRIsProjected, [c_void_p])
+
+# Coordinate transformation
+new_ct= srs_output(std_call('OCTNewCoordinateTransformation'), [c_void_p, c_void_p])
+destroy_ct = void_output(std_call('OCTDestroyCoordinateTransformation'), [c_void_p], errcheck=False)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/srs.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/srs.py
new file mode 100644
index 0000000..66a8d4e
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/srs.py
@@ -0,0 +1,342 @@
+"""
+ The Spatial Reference class, represensents 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
+
+# Getting the error checking routine and exceptions
+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 import six
+from django.utils.encoding import force_bytes
+
+
+#### Spatial Reference class. ####
+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."
+ """
+
+ #### Python 'magic' routines ####
+ def __init__(self, srs_input=''):
+ """
+ Creates 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').
+ """
+ srs_type = 'user'
+
+ if isinstance(srs_input, six.string_types):
+ # Encoding to ASCII if unicode passed in.
+ if isinstance(srs_input, six.text_type):
+ srs_input = srs_input.encode('ascii')
+ 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, six.integer_types):
+ # 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 __del__(self):
+ "Destroys this spatial reference."
+ if self._ptr: capi.release_srs(self._ptr)
+
+ def __getitem__(self, target):
+ """
+ Returns 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 untis
+ 9122
+ """
+ if isinstance(target, tuple):
+ return self.attr_value(*target)
+ else:
+ return self.attr_value(target)
+
+ def __str__(self):
+ "The string representation uses '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, six.string_types) or not isinstance(index, int):
+ raise TypeError
+ return capi.get_attr_value(self.ptr, force_bytes(target), index)
+
+ def auth_name(self, target):
+ "Returns the authority name for the given string target node."
+ return capi.get_auth_name(self.ptr, force_bytes(target))
+
+ def auth_code(self, target):
+ "Returns the authority code for the given string target node."
+ return capi.get_auth_code(self.ptr, force_bytes(target))
+
+ def clone(self):
+ "Returns a clone of this SpatialReference object."
+ return SpatialReference(capi.clone_srs(self.ptr))
+
+ def from_esri(self):
+ "Morphs 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):
+ "Morphs this SpatialReference to ESRI's format."
+ capi.morph_to_esri(self.ptr)
+
+ def validate(self):
+ "Checks to see if the given spatial reference is valid."
+ capi.srs_validate(self.ptr)
+
+ #### Name & SRID properties ####
+ @property
+ def name(self):
+ "Returns 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):
+ "Returns 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):
+ "Returns the name of the linear units."
+ units, name = capi.linear_units(self.ptr, byref(c_char_p()))
+ return name
+
+ @property
+ def linear_units(self):
+ "Returns the value of the linear units."
+ units, name = capi.linear_units(self.ptr, byref(c_char_p()))
+ return units
+
+ @property
+ def angular_name(self):
+ "Returns the name of the angular units."
+ units, name = capi.angular_units(self.ptr, byref(c_char_p()))
+ return name
+
+ @property
+ def angular_units(self):
+ "Returns the value of the angular units."
+ units, name = capi.angular_units(self.ptr, byref(c_char_p()))
+ return units
+
+ @property
+ def units(self):
+ """
+ Returns a 2-tuple of the units value and the units name,
+ and will automatically determines 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.decode()
+ return (units, name)
+
+ #### Spheroid/Ellipsoid Properties ####
+ @property
+ def ellipsoid(self):
+ """
+ Returns 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):
+ "Returns the Semi Major Axis for this Spatial Reference."
+ return capi.semi_major(self.ptr, byref(c_int()))
+
+ @property
+ def semi_minor(self):
+ "Returns the Semi Minor Axis for this Spatial Reference."
+ return capi.semi_minor(self.ptr, byref(c_int()))
+
+ @property
+ def inverse_flattening(self):
+ "Returns the Inverse Flattening for this Spatial Reference."
+ return capi.invflattening(self.ptr, byref(c_int()))
+
+ #### Boolean Properties ####
+ @property
+ def geographic(self):
+ """
+ Returns True if this SpatialReference is geographic
+ (root node is GEOGCS).
+ """
+ return bool(capi.isgeographic(self.ptr))
+
+ @property
+ def local(self):
+ "Returns True if this SpatialReference is local (root node is LOCAL_CS)."
+ return bool(capi.islocal(self.ptr))
+
+ @property
+ def projected(self):
+ """
+ Returns 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):
+ "Imports the Spatial Reference from the EPSG code (an integer)."
+ capi.from_epsg(self.ptr, epsg)
+
+ def import_proj(self, proj):
+ "Imports the Spatial Reference from a PROJ.4 string."
+ capi.from_proj(self.ptr, proj)
+
+ def import_user_input(self, user_input):
+ "Imports the Spatial Reference from the given user input string."
+ capi.from_user_input(self.ptr, force_bytes(user_input))
+
+ def import_wkt(self, wkt):
+ "Imports the Spatial Reference from OGC WKT (string)"
+ capi.from_wkt(self.ptr, byref(c_char_p(wkt)))
+
+ def import_xml(self, xml):
+ "Imports the Spatial Reference from an XML string."
+ capi.from_xml(self.ptr, xml)
+
+ #### Export Properties ####
+ @property
+ def wkt(self):
+ "Returns the WKT representation of this Spatial Reference."
+ return capi.to_wkt(self.ptr, byref(c_char_p()))
+
+ @property
+ def pretty_wkt(self, simplify=0):
+ "Returns the 'pretty' representation of the WKT."
+ return capi.to_pretty_wkt(self.ptr, byref(c_char_p()), simplify)
+
+ @property
+ def proj(self):
+ "Returns 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=''):
+ "Returns the XML representation of this Spatial Reference."
+ return capi.to_xml(self.ptr, byref(c_char_p()), dialect)
+
+class CoordTransform(GDALBase):
+ "The coordinate system transformation object."
+
+ def __init__(self, source, target):
+ "Initializes 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 __del__(self):
+ "Deletes this Coordinate Transformation object."
+ if self._ptr: capi.destroy_ct(self._ptr)
+
+ def __str__(self):
+ return 'Transform from "%s" to "%s"' % (self._srs1_name, self._srs2_name)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/__init__.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/__init__.py
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_driver.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_driver.py
new file mode 100644
index 0000000..c27302d
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_driver.py
@@ -0,0 +1,39 @@
+from django.contrib.gis.gdal import HAS_GDAL
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import Driver, OGRException
+
+
+valid_drivers = ('ESRI Shapefile', 'MapInfo File', 'TIGER', 'S57', 'DGN',
+ 'Memory', 'CSV', 'GML', 'KML')
+
+invalid_drivers = ('Foo baz', 'clucka', 'ESRI Shp')
+
+aliases = {'eSrI' : 'ESRI Shapefile',
+ 'TigER/linE' : 'TIGER',
+ 'SHAPE' : 'ESRI Shapefile',
+ 'sHp' : 'ESRI Shapefile',
+ }
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
+class DriverTest(unittest.TestCase):
+
+ def test01_valid_driver(self):
+ "Testing valid OGR Data Source Drivers."
+ for d in valid_drivers:
+ dr = Driver(d)
+ self.assertEqual(d, str(dr))
+
+ def test02_invalid_driver(self):
+ "Testing invalid OGR Data Source Drivers."
+ for i in invalid_drivers:
+ self.assertRaises(OGRException, Driver, i)
+
+ def test03_aliases(self):
+ "Testing driver aliases."
+ for alias, full_name in aliases.items():
+ dr = Driver(alias)
+ self.assertEqual(full_name, str(dr))
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_ds.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_ds.py
new file mode 100644
index 0000000..3664f05
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_ds.py
@@ -0,0 +1,244 @@
+import os
+
+from django.contrib.gis.gdal import HAS_GDAL
+from django.contrib.gis.geometry.test_data import get_ds_file, TestDS, TEST_DATA
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import DataSource, Envelope, OGRGeometry, OGRException, OGRIndexError, GDAL_VERSION
+ from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
+
+ # List of acceptable data sources.
+ ds_list = (
+ TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile',
+ fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
+ extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS
+ srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]',
+ field_values={'dbl' : [float(i) for i in range(1, 6)], 'int' : list(range(1, 6)), 'str' : [str(i) for i in range(1, 6)]},
+ fids=range(5)),
+ TestDS('test_vrt', ext='vrt', nfeat=3, nfld=3, geom='POINT', gtype='Point25D', driver='VRT',
+ fields={'POINT_X' : OFTString, 'POINT_Y' : OFTString, 'NUM' : OFTString}, # VRT uses CSV, which all types are OFTString.
+ extent=(1.0, 2.0, 100.0, 523.5), # Min/Max from CSV
+ field_values={'POINT_X' : ['1.0', '5.0', '100.0'], 'POINT_Y' : ['2.0', '23.0', '523.5'], 'NUM' : ['5', '17', '23']},
+ fids=range(1,4)),
+ TestDS('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3,
+ driver='ESRI Shapefile',
+ fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
+ extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
+ srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
+ )
+
+bad_ds = (TestDS('foo'),)
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
+class DataSourceTest(unittest.TestCase):
+
+ def test01_valid_shp(self):
+ "Testing valid SHP Data Source files."
+
+ for source in ds_list:
+ # Loading up the data source
+ ds = DataSource(source.ds)
+
+ # Making sure the layer count is what's expected (only 1 layer in a SHP file)
+ self.assertEqual(1, len(ds))
+
+ # Making sure GetName works
+ self.assertEqual(source.ds, ds.name)
+
+ # Making sure the driver name matches up
+ self.assertEqual(source.driver, str(ds.driver))
+
+ # Making sure indexing works
+ try:
+ ds[len(ds)]
+ except OGRIndexError:
+ pass
+ else:
+ self.fail('Expected an IndexError!')
+
+ def test02_invalid_shp(self):
+ "Testing invalid SHP files for the Data Source."
+ for source in bad_ds:
+ self.assertRaises(OGRException, DataSource, source.ds)
+
+ def test03a_layers(self):
+ "Testing Data Source Layers."
+ for source in ds_list:
+ ds = DataSource(source.ds)
+
+ # Incrementing through each layer, this tests DataSource.__iter__
+ for layer in ds:
+ # Making sure we get the number of features we expect
+ self.assertEqual(len(layer), source.nfeat)
+
+ # Making sure we get the number of fields we expect
+ self.assertEqual(source.nfld, layer.num_fields)
+ self.assertEqual(source.nfld, len(layer.fields))
+
+ # Testing the layer's extent (an Envelope), and it's properties
+ if source.driver == 'VRT' and (GDAL_VERSION >= (1, 7, 0) and GDAL_VERSION < (1, 7, 3)):
+ # There's a known GDAL regression with retrieving the extent
+ # of a VRT layer in versions 1.7.0-1.7.2:
+ # http://trac.osgeo.org/gdal/ticket/3783
+ pass
+ else:
+ self.assertEqual(True, isinstance(layer.extent, Envelope))
+ self.assertAlmostEqual(source.extent[0], layer.extent.min_x, 5)
+ self.assertAlmostEqual(source.extent[1], layer.extent.min_y, 5)
+ self.assertAlmostEqual(source.extent[2], layer.extent.max_x, 5)
+ self.assertAlmostEqual(source.extent[3], layer.extent.max_y, 5)
+
+ # Now checking the field names.
+ flds = layer.fields
+ for f in flds: self.assertEqual(True, f in source.fields)
+
+ # Negative FIDs are not allowed.
+ self.assertRaises(OGRIndexError, layer.__getitem__, -1)
+ self.assertRaises(OGRIndexError, layer.__getitem__, 50000)
+
+ if hasattr(source, 'field_values'):
+ fld_names = source.field_values.keys()
+
+ # Testing `Layer.get_fields` (which uses Layer.__iter__)
+ for fld_name in fld_names:
+ self.assertEqual(source.field_values[fld_name], layer.get_fields(fld_name))
+
+ # Testing `Layer.__getitem__`.
+ for i, fid in enumerate(source.fids):
+ feat = layer[fid]
+ self.assertEqual(fid, feat.fid)
+ # Maybe this should be in the test below, but we might as well test
+ # the feature values here while in this loop.
+ for fld_name in fld_names:
+ self.assertEqual(source.field_values[fld_name][i], feat.get(fld_name))
+
+ def test03b_layer_slice(self):
+ "Test indexing and slicing on Layers."
+ # Using the first data-source because the same slice
+ # can be used for both the layer and the control values.
+ source = ds_list[0]
+ ds = DataSource(source.ds)
+
+ sl = slice(1, 3)
+ feats = ds[0][sl]
+
+ for fld_name in ds[0].fields:
+ test_vals = [feat.get(fld_name) for feat in feats]
+ control_vals = source.field_values[fld_name][sl]
+ self.assertEqual(control_vals, test_vals)
+
+ def test03c_layer_references(self):
+ """
+ Ensure OGR objects keep references to the objects they belong to.
+ """
+ source = ds_list[0]
+
+ # See ticket #9448.
+ def get_layer():
+ # This DataSource object is not accessible outside this
+ # scope. However, a reference should still be kept alive
+ # on the `Layer` returned.
+ ds = DataSource(source.ds)
+ return ds[0]
+
+ # Making sure we can call OGR routines on the Layer returned.
+ lyr = get_layer()
+ self.assertEqual(source.nfeat, len(lyr))
+ self.assertEqual(source.gtype, lyr.geom_type.num)
+
+ # Same issue for Feature/Field objects, see #18640
+ self.assertEqual(str(lyr[0]['str']), "1")
+
+ def test04_features(self):
+ "Testing Data Source Features."
+ for source in ds_list:
+ ds = DataSource(source.ds)
+
+ # Incrementing through each layer
+ for layer in ds:
+ # Incrementing through each feature in the layer
+ for feat in layer:
+ # Making sure the number of fields, and the geometry type
+ # are what's expected.
+ self.assertEqual(source.nfld, len(list(feat)))
+ self.assertEqual(source.gtype, feat.geom_type)
+
+ # Making sure the fields match to an appropriate OFT type.
+ for k, v in source.fields.items():
+ # Making sure we get the proper OGR Field instance, using
+ # a string value index for the feature.
+ self.assertEqual(True, isinstance(feat[k], v))
+
+ # Testing Feature.__iter__
+ for fld in feat:
+ self.assertEqual(True, fld.name in source.fields.keys())
+
+ def test05_geometries(self):
+ "Testing Geometries from Data Source Features."
+ for source in ds_list:
+ ds = DataSource(source.ds)
+
+ # Incrementing through each layer and feature.
+ for layer in ds:
+ for feat in layer:
+ g = feat.geom
+
+ # Making sure we get the right Geometry name & type
+ self.assertEqual(source.geom, g.geom_name)
+ self.assertEqual(source.gtype, g.geom_type)
+
+ # Making sure the SpatialReference is as expected.
+ if hasattr(source, 'srs_wkt'):
+ self.assertEqual(
+ source.srs_wkt,
+ # Depending on lib versions, WGS_84 might be WGS_1984
+ g.srs.wkt.replace('SPHEROID["WGS_84"', 'SPHEROID["WGS_1984"')
+ )
+
+ def test06_spatial_filter(self):
+ "Testing the Layer.spatial_filter property."
+ ds = DataSource(get_ds_file('cities', 'shp'))
+ lyr = ds[0]
+
+ # When not set, it should be None.
+ self.assertEqual(None, lyr.spatial_filter)
+
+ # Must be set a/an OGRGeometry or 4-tuple.
+ self.assertRaises(TypeError, lyr._set_spatial_filter, 'foo')
+
+ # Setting the spatial filter with a tuple/list with the extent of
+ # a buffer centering around Pueblo.
+ self.assertRaises(ValueError, lyr._set_spatial_filter, list(range(5)))
+ filter_extent = (-105.609252, 37.255001, -103.609252, 39.255001)
+ lyr.spatial_filter = (-105.609252, 37.255001, -103.609252, 39.255001)
+ self.assertEqual(OGRGeometry.from_bbox(filter_extent), lyr.spatial_filter)
+ feats = [feat for feat in lyr]
+ self.assertEqual(1, len(feats))
+ self.assertEqual('Pueblo', feats[0].get('Name'))
+
+ # Setting the spatial filter with an OGRGeometry for buffer centering
+ # around Houston.
+ filter_geom = OGRGeometry('POLYGON((-96.363151 28.763374,-94.363151 28.763374,-94.363151 30.763374,-96.363151 30.763374,-96.363151 28.763374))')
+ lyr.spatial_filter = filter_geom
+ self.assertEqual(filter_geom, lyr.spatial_filter)
+ feats = [feat for feat in lyr]
+ self.assertEqual(1, len(feats))
+ self.assertEqual('Houston', feats[0].get('Name'))
+
+ # Clearing the spatial filter by setting it to None. Now
+ # should indicate that there are 3 features in the Layer.
+ lyr.spatial_filter = None
+ self.assertEqual(3, len(lyr))
+
+ def test07_integer_overflow(self):
+ "Testing that OFTReal fields, treated as OFTInteger, do not overflow."
+ # Using *.dbf from Census 2010 TIGER Shapefile for Texas,
+ # which has land area ('ALAND10') stored in a Real field
+ # with no precision.
+ ds = DataSource(os.path.join(TEST_DATA, 'texas.dbf'))
+ feat = ds[0][0]
+ # Reference value obtained using `ogrinfo`.
+ self.assertEqual(676586997978, feat.get('ALAND10'))
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_envelope.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_envelope.py
new file mode 100644
index 0000000..7518dc6
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_envelope.py
@@ -0,0 +1,93 @@
+from django.contrib.gis.gdal import HAS_GDAL
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import Envelope, OGRException
+
+
+class TestPoint(object):
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
+class EnvelopeTest(unittest.TestCase):
+
+ def setUp(self):
+ self.e = Envelope(0, 0, 5, 5)
+
+ def test01_init(self):
+ "Testing Envelope initilization."
+ e1 = Envelope((0, 0, 5, 5))
+ e2 = Envelope(0, 0, 5, 5)
+ e3 = Envelope(0, '0', '5', 5) # Thanks to ww for this
+ e4 = Envelope(e1._envelope)
+ self.assertRaises(OGRException, Envelope, (5, 5, 0, 0))
+ self.assertRaises(OGRException, Envelope, 5, 5, 0, 0)
+ self.assertRaises(OGRException, Envelope, (0, 0, 5, 5, 3))
+ self.assertRaises(OGRException, Envelope, ())
+ self.assertRaises(ValueError, Envelope, 0, 'a', 5, 5)
+ self.assertRaises(TypeError, Envelope, 'foo')
+ self.assertRaises(OGRException, Envelope, (1, 1, 0, 0))
+ try:
+ Envelope(0, 0, 0, 0)
+ except OGRException:
+ self.fail("shouldn't raise an exception for min_x == max_x or min_y == max_y")
+
+ def test02_properties(self):
+ "Testing Envelope properties."
+ e = Envelope(0, 0, 2, 3)
+ self.assertEqual(0, e.min_x)
+ self.assertEqual(0, e.min_y)
+ self.assertEqual(2, e.max_x)
+ self.assertEqual(3, e.max_y)
+ self.assertEqual((0, 0), e.ll)
+ self.assertEqual((2, 3), e.ur)
+ self.assertEqual((0, 0, 2, 3), e.tuple)
+ self.assertEqual('POLYGON((0.0 0.0,0.0 3.0,2.0 3.0,2.0 0.0,0.0 0.0))', e.wkt)
+ self.assertEqual('(0.0, 0.0, 2.0, 3.0)', str(e))
+
+ def test03_equivalence(self):
+ "Testing Envelope equivalence."
+ e1 = Envelope(0.523, 0.217, 253.23, 523.69)
+ e2 = Envelope((0.523, 0.217, 253.23, 523.69))
+ self.assertEqual(e1, e2)
+ self.assertEqual((0.523, 0.217, 253.23, 523.69), e1)
+
+ def test04_expand_to_include_pt_2_params(self):
+ "Testing Envelope expand_to_include -- point as two parameters."
+ self.e.expand_to_include(2, 6)
+ self.assertEqual((0, 0, 5, 6), self.e)
+ self.e.expand_to_include(-1, -1)
+ self.assertEqual((-1, -1, 5, 6), self.e)
+
+ def test05_expand_to_include_pt_2_tuple(self):
+ "Testing Envelope expand_to_include -- point as a single 2-tuple parameter."
+ self.e.expand_to_include((10, 10))
+ self.assertEqual((0, 0, 10, 10), self.e)
+ self.e.expand_to_include((-10, -10))
+ self.assertEqual((-10, -10, 10, 10), self.e)
+
+ def test06_expand_to_include_extent_4_params(self):
+ "Testing Envelope expand_to_include -- extent as 4 parameters."
+ self.e.expand_to_include(-1, 1, 3, 7)
+ self.assertEqual((-1, 0, 5, 7), self.e)
+
+ def test06_expand_to_include_extent_4_tuple(self):
+ "Testing Envelope expand_to_include -- extent as a single 4-tuple parameter."
+ self.e.expand_to_include((-1, 1, 3, 7))
+ self.assertEqual((-1, 0, 5, 7), self.e)
+
+ def test07_expand_to_include_envelope(self):
+ "Testing Envelope expand_to_include with Envelope as parameter."
+ self.e.expand_to_include(Envelope(-1, 1, 3, 7))
+ self.assertEqual((-1, 0, 5, 7), self.e)
+
+ def test08_expand_to_include_point(self):
+ "Testing Envelope expand_to_include with Point as parameter."
+ self.e.expand_to_include(TestPoint(-1, 1))
+ self.assertEqual((-1, 0, 5, 5), self.e)
+ self.e.expand_to_include(TestPoint(10, 10))
+ self.assertEqual((-1, 0, 10, 10), self.e)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_geom.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_geom.py
new file mode 100644
index 0000000..c048d2b
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_geom.py
@@ -0,0 +1,485 @@
+import json
+from binascii import b2a_hex
+try:
+ from django.utils.six.moves import cPickle as pickle
+except ImportError:
+ import pickle
+
+from django.contrib.gis.gdal import HAS_GDAL
+from django.contrib.gis.geometry.test_data import TestDataMixin
+from django.utils.six.moves import xrange
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import (OGRGeometry, OGRGeomType,
+ OGRException, OGRIndexError, SpatialReference, CoordTransform,
+ GDAL_VERSION)
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
+class OGRGeomTest(unittest.TestCase, TestDataMixin):
+ "This tests the OGR Geometry."
+
+ def test00a_geomtype(self):
+ "Testing OGRGeomType object."
+
+ # OGRGeomType should initialize on all these inputs.
+ try:
+ g = OGRGeomType(1)
+ g = OGRGeomType(7)
+ g = OGRGeomType('point')
+ g = OGRGeomType('GeometrycollectioN')
+ g = OGRGeomType('LINearrING')
+ g = OGRGeomType('Unknown')
+ except:
+ self.fail('Could not create an OGRGeomType object!')
+
+ # Should throw TypeError on this input
+ self.assertRaises(OGRException, OGRGeomType, 23)
+ self.assertRaises(OGRException, OGRGeomType, 'fooD')
+ self.assertRaises(OGRException, OGRGeomType, 9)
+
+ # Equivalence can take strings, ints, and other OGRGeomTypes
+ self.assertEqual(True, OGRGeomType(1) == OGRGeomType(1))
+ self.assertEqual(True, OGRGeomType(7) == 'GeometryCollection')
+ self.assertEqual(True, OGRGeomType('point') == 'POINT')
+ self.assertEqual(False, OGRGeomType('point') == 2)
+ self.assertEqual(True, OGRGeomType('unknown') == 0)
+ self.assertEqual(True, OGRGeomType(6) == 'MULtiPolyGON')
+ self.assertEqual(False, OGRGeomType(1) != OGRGeomType('point'))
+ self.assertEqual(True, OGRGeomType('POINT') != OGRGeomType(6))
+
+ # Testing the Django field name equivalent property.
+ self.assertEqual('PointField', OGRGeomType('Point').django)
+ self.assertEqual('GeometryField', OGRGeomType('Unknown').django)
+ self.assertEqual(None, OGRGeomType('none').django)
+
+ # 'Geometry' initialization implies an unknown geometry type.
+ gt = OGRGeomType('Geometry')
+ self.assertEqual(0, gt.num)
+ self.assertEqual('Unknown', gt.name)
+
+ def test00b_geomtype_25d(self):
+ "Testing OGRGeomType object with 25D types."
+ wkb25bit = OGRGeomType.wkb25bit
+ self.assertTrue(OGRGeomType(wkb25bit + 1) == 'Point25D')
+ self.assertTrue(OGRGeomType('MultiLineString25D') == (5 + wkb25bit))
+ self.assertEqual('GeometryCollectionField', OGRGeomType('GeometryCollection25D').django)
+
+ def test01a_wkt(self):
+ "Testing WKT output."
+ for g in self.geometries.wkt_out:
+ geom = OGRGeometry(g.wkt)
+ self.assertEqual(g.wkt, geom.wkt)
+
+ def test01a_ewkt(self):
+ "Testing EWKT input/output."
+ for ewkt_val in ('POINT (1 2 3)', 'LINEARRING (0 0,1 1,2 1,0 0)'):
+ # First with ewkt output when no SRID in EWKT
+ self.assertEqual(ewkt_val, OGRGeometry(ewkt_val).ewkt)
+ # No test consumption with an SRID specified.
+ ewkt_val = 'SRID=4326;%s' % ewkt_val
+ geom = OGRGeometry(ewkt_val)
+ self.assertEqual(ewkt_val, geom.ewkt)
+ self.assertEqual(4326, geom.srs.srid)
+
+ def test01b_gml(self):
+ "Testing GML output."
+ for g in self.geometries.wkt_out:
+ geom = OGRGeometry(g.wkt)
+ exp_gml = g.gml
+ if GDAL_VERSION >= (1, 8):
+ # In GDAL 1.8, the non-conformant GML tag <gml:GeometryCollection> was
+ # replaced with <gml:MultiGeometry>.
+ exp_gml = exp_gml.replace('GeometryCollection', 'MultiGeometry')
+ self.assertEqual(exp_gml, geom.gml)
+
+ def test01c_hex(self):
+ "Testing HEX input/output."
+ for g in self.geometries.hex_wkt:
+ geom1 = OGRGeometry(g.wkt)
+ self.assertEqual(g.hex.encode(), geom1.hex)
+ # Constructing w/HEX
+ geom2 = OGRGeometry(g.hex)
+ self.assertEqual(geom1, geom2)
+
+ def test01d_wkb(self):
+ "Testing WKB input/output."
+ for g in self.geometries.hex_wkt:
+ geom1 = OGRGeometry(g.wkt)
+ wkb = geom1.wkb
+ self.assertEqual(b2a_hex(wkb).upper(), g.hex.encode())
+ # Constructing w/WKB.
+ geom2 = OGRGeometry(wkb)
+ self.assertEqual(geom1, geom2)
+
+ def test01e_json(self):
+ "Testing GeoJSON input/output."
+ for g in self.geometries.json_geoms:
+ geom = OGRGeometry(g.wkt)
+ if not hasattr(g, 'not_equal'):
+ # Loading jsons to prevent decimal differences
+ self.assertEqual(json.loads(g.json), json.loads(geom.json))
+ self.assertEqual(json.loads(g.json), json.loads(geom.geojson))
+ self.assertEqual(OGRGeometry(g.wkt), OGRGeometry(geom.json))
+
+ def test02_points(self):
+ "Testing Point objects."
+
+ prev = OGRGeometry('POINT(0 0)')
+ for p in self.geometries.points:
+ if not hasattr(p, 'z'): # No 3D
+ pnt = OGRGeometry(p.wkt)
+ self.assertEqual(1, pnt.geom_type)
+ self.assertEqual('POINT', pnt.geom_name)
+ self.assertEqual(p.x, pnt.x)
+ self.assertEqual(p.y, pnt.y)
+ self.assertEqual((p.x, p.y), pnt.tuple)
+
+ def test03_multipoints(self):
+ "Testing MultiPoint objects."
+ for mp in self.geometries.multipoints:
+ mgeom1 = OGRGeometry(mp.wkt) # First one from WKT
+ self.assertEqual(4, mgeom1.geom_type)
+ self.assertEqual('MULTIPOINT', mgeom1.geom_name)
+ mgeom2 = OGRGeometry('MULTIPOINT') # Creating empty multipoint
+ mgeom3 = OGRGeometry('MULTIPOINT')
+ for g in mgeom1:
+ mgeom2.add(g) # adding each point from the multipoints
+ mgeom3.add(g.wkt) # should take WKT as well
+ self.assertEqual(mgeom1, mgeom2) # they should equal
+ self.assertEqual(mgeom1, mgeom3)
+ self.assertEqual(mp.coords, mgeom2.coords)
+ self.assertEqual(mp.n_p, mgeom2.point_count)
+
+ def test04_linestring(self):
+ "Testing LineString objects."
+ prev = OGRGeometry('POINT(0 0)')
+ for ls in self.geometries.linestrings:
+ linestr = OGRGeometry(ls.wkt)
+ self.assertEqual(2, linestr.geom_type)
+ self.assertEqual('LINESTRING', linestr.geom_name)
+ self.assertEqual(ls.n_p, linestr.point_count)
+ self.assertEqual(ls.coords, linestr.tuple)
+ self.assertEqual(True, linestr == OGRGeometry(ls.wkt))
+ self.assertEqual(True, linestr != prev)
+ self.assertRaises(OGRIndexError, linestr.__getitem__, len(linestr))
+ prev = linestr
+
+ # Testing the x, y properties.
+ x = [tmpx for tmpx, tmpy in ls.coords]
+ y = [tmpy for tmpx, tmpy in ls.coords]
+ self.assertEqual(x, linestr.x)
+ self.assertEqual(y, linestr.y)
+
+ def test05_multilinestring(self):
+ "Testing MultiLineString objects."
+ prev = OGRGeometry('POINT(0 0)')
+ for mls in self.geometries.multilinestrings:
+ mlinestr = OGRGeometry(mls.wkt)
+ self.assertEqual(5, mlinestr.geom_type)
+ self.assertEqual('MULTILINESTRING', mlinestr.geom_name)
+ self.assertEqual(mls.n_p, mlinestr.point_count)
+ self.assertEqual(mls.coords, mlinestr.tuple)
+ self.assertEqual(True, mlinestr == OGRGeometry(mls.wkt))
+ self.assertEqual(True, mlinestr != prev)
+ prev = mlinestr
+ for ls in mlinestr:
+ self.assertEqual(2, ls.geom_type)
+ self.assertEqual('LINESTRING', ls.geom_name)
+ self.assertRaises(OGRIndexError, mlinestr.__getitem__, len(mlinestr))
+
+ def test06_linearring(self):
+ "Testing LinearRing objects."
+ prev = OGRGeometry('POINT(0 0)')
+ for rr in self.geometries.linearrings:
+ lr = OGRGeometry(rr.wkt)
+ #self.assertEqual(101, lr.geom_type.num)
+ self.assertEqual('LINEARRING', lr.geom_name)
+ self.assertEqual(rr.n_p, len(lr))
+ self.assertEqual(True, lr == OGRGeometry(rr.wkt))
+ self.assertEqual(True, lr != prev)
+ prev = lr
+
+ def test07a_polygons(self):
+ "Testing Polygon objects."
+
+ # Testing `from_bbox` class method
+ bbox = (-180,-90,180,90)
+ p = OGRGeometry.from_bbox( bbox )
+ self.assertEqual(bbox, p.extent)
+
+ prev = OGRGeometry('POINT(0 0)')
+ for p in self.geometries.polygons:
+ poly = OGRGeometry(p.wkt)
+ self.assertEqual(3, poly.geom_type)
+ self.assertEqual('POLYGON', poly.geom_name)
+ self.assertEqual(p.n_p, poly.point_count)
+ self.assertEqual(p.n_i + 1, len(poly))
+
+ # Testing area & centroid.
+ self.assertAlmostEqual(p.area, poly.area, 9)
+ x, y = poly.centroid.tuple
+ self.assertAlmostEqual(p.centroid[0], x, 9)
+ self.assertAlmostEqual(p.centroid[1], y, 9)
+
+ # Testing equivalence
+ self.assertEqual(True, poly == OGRGeometry(p.wkt))
+ self.assertEqual(True, poly != prev)
+
+ if p.ext_ring_cs:
+ ring = poly[0]
+ self.assertEqual(p.ext_ring_cs, ring.tuple)
+ self.assertEqual(p.ext_ring_cs, poly[0].tuple)
+ self.assertEqual(len(p.ext_ring_cs), ring.point_count)
+
+ for r in poly:
+ self.assertEqual('LINEARRING', r.geom_name)
+
+ def test07b_closepolygons(self):
+ "Testing closing Polygon objects."
+ # Both rings in this geometry are not closed.
+ poly = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5), (1 1, 2 1, 2 2, 2 1))')
+ self.assertEqual(8, poly.point_count)
+ with self.assertRaises(OGRException):
+ _ = poly.centroid
+
+ poly.close_rings()
+ self.assertEqual(10, poly.point_count) # Two closing points should've been added
+ self.assertEqual(OGRGeometry('POINT(2.5 2.5)'), poly.centroid)
+
+ def test08_multipolygons(self):
+ "Testing MultiPolygon objects."
+ prev = OGRGeometry('POINT(0 0)')
+ for mp in self.geometries.multipolygons:
+ mpoly = OGRGeometry(mp.wkt)
+ self.assertEqual(6, mpoly.geom_type)
+ self.assertEqual('MULTIPOLYGON', mpoly.geom_name)
+ if mp.valid:
+ self.assertEqual(mp.n_p, mpoly.point_count)
+ self.assertEqual(mp.num_geom, len(mpoly))
+ self.assertRaises(OGRIndexError, mpoly.__getitem__, len(mpoly))
+ for p in mpoly:
+ self.assertEqual('POLYGON', p.geom_name)
+ self.assertEqual(3, p.geom_type)
+ self.assertEqual(mpoly.wkt, OGRGeometry(mp.wkt).wkt)
+
+ def test09a_srs(self):
+ "Testing OGR Geometries with Spatial Reference objects."
+ for mp in self.geometries.multipolygons:
+ # Creating a geometry w/spatial reference
+ sr = SpatialReference('WGS84')
+ mpoly = OGRGeometry(mp.wkt, sr)
+ self.assertEqual(sr.wkt, mpoly.srs.wkt)
+
+ # Ensuring that SRS is propagated to clones.
+ klone = mpoly.clone()
+ self.assertEqual(sr.wkt, klone.srs.wkt)
+
+ # Ensuring all children geometries (polygons and their rings) all
+ # return the assigned spatial reference as well.
+ for poly in mpoly:
+ self.assertEqual(sr.wkt, poly.srs.wkt)
+ for ring in poly:
+ self.assertEqual(sr.wkt, ring.srs.wkt)
+
+ # Ensuring SRS propagate in topological ops.
+ a = OGRGeometry(self.geometries.topology_geoms[0].wkt_a, sr)
+ b = OGRGeometry(self.geometries.topology_geoms[0].wkt_b, sr)
+ diff = a.difference(b)
+ union = a.union(b)
+ self.assertEqual(sr.wkt, diff.srs.wkt)
+ self.assertEqual(sr.srid, union.srs.srid)
+
+ # Instantiating w/an integer SRID
+ mpoly = OGRGeometry(mp.wkt, 4326)
+ self.assertEqual(4326, mpoly.srid)
+ mpoly.srs = SpatialReference(4269)
+ self.assertEqual(4269, mpoly.srid)
+ self.assertEqual('NAD83', mpoly.srs.name)
+
+ # Incrementing through the multipolyogn after the spatial reference
+ # has been re-assigned.
+ for poly in mpoly:
+ self.assertEqual(mpoly.srs.wkt, poly.srs.wkt)
+ poly.srs = 32140
+ for ring in poly:
+ # Changing each ring in the polygon
+ self.assertEqual(32140, ring.srs.srid)
+ self.assertEqual('NAD83 / Texas South Central', ring.srs.name)
+ ring.srs = str(SpatialReference(4326)) # back to WGS84
+ self.assertEqual(4326, ring.srs.srid)
+
+ # Using the `srid` property.
+ ring.srid = 4322
+ self.assertEqual('WGS 72', ring.srs.name)
+ self.assertEqual(4322, ring.srid)
+
+ def test09b_srs_transform(self):
+ "Testing transform()."
+ orig = OGRGeometry('POINT (-104.609 38.255)', 4326)
+ trans = OGRGeometry('POINT (992385.4472045 481455.4944650)', 2774)
+
+ # Using an srid, a SpatialReference object, and a CoordTransform object
+ # or transformations.
+ t1, t2, t3 = orig.clone(), orig.clone(), orig.clone()
+ t1.transform(trans.srid)
+ t2.transform(SpatialReference('EPSG:2774'))
+ ct = CoordTransform(SpatialReference('WGS84'), SpatialReference(2774))
+ t3.transform(ct)
+
+ # Testing use of the `clone` keyword.
+ k1 = orig.clone()
+ k2 = k1.transform(trans.srid, clone=True)
+ self.assertEqual(k1, orig)
+ self.assertNotEqual(k1, k2)
+
+ prec = 3
+ for p in (t1, t2, t3, k2):
+ self.assertAlmostEqual(trans.x, p.x, prec)
+ self.assertAlmostEqual(trans.y, p.y, prec)
+
+ def test09c_transform_dim(self):
+ "Testing coordinate dimension is the same on transformed geometries."
+ ls_orig = OGRGeometry('LINESTRING(-104.609 38.255)', 4326)
+ ls_trans = OGRGeometry('LINESTRING(992385.4472045 481455.4944650)', 2774)
+
+ prec = 3
+ ls_orig.transform(ls_trans.srs)
+ # Making sure the coordinate dimension is still 2D.
+ self.assertEqual(2, ls_orig.coord_dim)
+ self.assertAlmostEqual(ls_trans.x[0], ls_orig.x[0], prec)
+ self.assertAlmostEqual(ls_trans.y[0], ls_orig.y[0], prec)
+
+ def test10_difference(self):
+ "Testing difference()."
+ for i in xrange(len(self.geometries.topology_geoms)):
+ a = OGRGeometry(self.geometries.topology_geoms[i].wkt_a)
+ b = OGRGeometry(self.geometries.topology_geoms[i].wkt_b)
+ d1 = OGRGeometry(self.geometries.diff_geoms[i].wkt)
+ d2 = a.difference(b)
+ self.assertEqual(d1, d2)
+ self.assertEqual(d1, a - b) # __sub__ is difference operator
+ a -= b # testing __isub__
+ self.assertEqual(d1, a)
+
+ def test11_intersection(self):
+ "Testing intersects() and intersection()."
+ for i in xrange(len(self.geometries.topology_geoms)):
+ a = OGRGeometry(self.geometries.topology_geoms[i].wkt_a)
+ b = OGRGeometry(self.geometries.topology_geoms[i].wkt_b)
+ i1 = OGRGeometry(self.geometries.intersect_geoms[i].wkt)
+ self.assertEqual(True, a.intersects(b))
+ i2 = a.intersection(b)
+ self.assertEqual(i1, i2)
+ self.assertEqual(i1, a & b) # __and__ is intersection operator
+ a &= b # testing __iand__
+ self.assertEqual(i1, a)
+
+ def test12_symdifference(self):
+ "Testing sym_difference()."
+ for i in xrange(len(self.geometries.topology_geoms)):
+ a = OGRGeometry(self.geometries.topology_geoms[i].wkt_a)
+ b = OGRGeometry(self.geometries.topology_geoms[i].wkt_b)
+ d1 = OGRGeometry(self.geometries.sdiff_geoms[i].wkt)
+ d2 = a.sym_difference(b)
+ self.assertEqual(d1, d2)
+ self.assertEqual(d1, a ^ b) # __xor__ is symmetric difference operator
+ a ^= b # testing __ixor__
+ self.assertEqual(d1, a)
+
+ def test13_union(self):
+ "Testing union()."
+ for i in xrange(len(self.geometries.topology_geoms)):
+ a = OGRGeometry(self.geometries.topology_geoms[i].wkt_a)
+ b = OGRGeometry(self.geometries.topology_geoms[i].wkt_b)
+ u1 = OGRGeometry(self.geometries.union_geoms[i].wkt)
+ u2 = a.union(b)
+ self.assertEqual(u1, u2)
+ self.assertEqual(u1, a | b) # __or__ is union operator
+ a |= b # testing __ior__
+ self.assertEqual(u1, a)
+
+ def test14_add(self):
+ "Testing GeometryCollection.add()."
+ # Can't insert a Point into a MultiPolygon.
+ mp = OGRGeometry('MultiPolygon')
+ pnt = OGRGeometry('POINT(5 23)')
+ self.assertRaises(OGRException, mp.add, pnt)
+
+ # GeometryCollection.add may take an OGRGeometry (if another collection
+ # of the same type all child geoms will be added individually) or WKT.
+ for mp in self.geometries.multipolygons:
+ mpoly = OGRGeometry(mp.wkt)
+ mp1 = OGRGeometry('MultiPolygon')
+ mp2 = OGRGeometry('MultiPolygon')
+ mp3 = OGRGeometry('MultiPolygon')
+
+ for poly in mpoly:
+ mp1.add(poly) # Adding a geometry at a time
+ mp2.add(poly.wkt) # Adding WKT
+ mp3.add(mpoly) # Adding a MultiPolygon's entire contents at once.
+ for tmp in (mp1, mp2, mp3): self.assertEqual(mpoly, tmp)
+
+ def test15_extent(self):
+ "Testing `extent` property."
+ # The xmin, ymin, xmax, ymax of the MultiPoint should be returned.
+ mp = OGRGeometry('MULTIPOINT(5 23, 0 0, 10 50)')
+ self.assertEqual((0.0, 0.0, 10.0, 50.0), mp.extent)
+ # Testing on the 'real world' Polygon.
+ poly = OGRGeometry(self.geometries.polygons[3].wkt)
+ ring = poly.shell
+ x, y = ring.x, ring.y
+ xmin, ymin = min(x), min(y)
+ xmax, ymax = max(x), max(y)
+ self.assertEqual((xmin, ymin, xmax, ymax), poly.extent)
+
+ def test16_25D(self):
+ "Testing 2.5D geometries."
+ pnt_25d = OGRGeometry('POINT(1 2 3)')
+ self.assertEqual('Point25D', pnt_25d.geom_type.name)
+ self.assertEqual(3.0, pnt_25d.z)
+ self.assertEqual(3, pnt_25d.coord_dim)
+ ls_25d = OGRGeometry('LINESTRING(1 1 1,2 2 2,3 3 3)')
+ self.assertEqual('LineString25D', ls_25d.geom_type.name)
+ self.assertEqual([1.0, 2.0, 3.0], ls_25d.z)
+ self.assertEqual(3, ls_25d.coord_dim)
+
+ def test17_pickle(self):
+ "Testing pickle support."
+ g1 = OGRGeometry('LINESTRING(1 1 1,2 2 2,3 3 3)', 'WGS84')
+ g2 = pickle.loads(pickle.dumps(g1))
+ self.assertEqual(g1, g2)
+ self.assertEqual(4326, g2.srs.srid)
+ self.assertEqual(g1.srs.wkt, g2.srs.wkt)
+
+ def test18_ogrgeometry_transform_workaround(self):
+ "Testing coordinate dimensions on geometries after transformation."
+ # A bug in GDAL versions prior to 1.7 changes the coordinate
+ # dimension of a geometry after it has been transformed.
+ # This test ensures that the bug workarounds employed within
+ # `OGRGeometry.transform` indeed work.
+ wkt_2d = "MULTILINESTRING ((0 0,1 1,2 2))"
+ wkt_3d = "MULTILINESTRING ((0 0 0,1 1 1,2 2 2))"
+ srid = 4326
+
+ # For both the 2D and 3D MultiLineString, ensure _both_ the dimension
+ # of the collection and the component LineString have the expected
+ # coordinate dimension after transform.
+ geom = OGRGeometry(wkt_2d, srid)
+ geom.transform(srid)
+ self.assertEqual(2, geom.coord_dim)
+ self.assertEqual(2, geom[0].coord_dim)
+ self.assertEqual(wkt_2d, geom.wkt)
+
+ geom = OGRGeometry(wkt_3d, srid)
+ geom.transform(srid)
+ self.assertEqual(3, geom.coord_dim)
+ self.assertEqual(3, geom[0].coord_dim)
+ self.assertEqual(wkt_3d, geom.wkt)
+
+ def test19_equivalence_regression(self):
+ "Testing equivalence methods with non-OGRGeometry instances."
+ self.assertNotEqual(None, OGRGeometry('POINT(0 0)'))
+ self.assertEqual(False, OGRGeometry('LINESTRING(0 0, 1 1)') == 3)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_srs.py b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_srs.py
new file mode 100644
index 0000000..363b597
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/gdal/tests/test_srs.py
@@ -0,0 +1,163 @@
+from django.contrib.gis.gdal import HAS_GDAL
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import SpatialReference, CoordTransform, OGRException, SRSException
+
+
+class TestSRS:
+ def __init__(self, wkt, **kwargs):
+ self.wkt = wkt
+ for key, value in kwargs.items():
+ setattr(self, key, value)
+
+# Some Spatial Reference examples
+srlist = (TestSRS('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"]]',
+ proj='+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ',
+ epsg=4326, projected=False, geographic=True, local=False,
+ lin_name='unknown', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
+ auth={'GEOGCS' : ('EPSG', '4326'), 'spheroid' : ('EPSG', '7030')},
+ attr=(('DATUM', 'WGS_1984'), (('SPHEROID', 1), '6378137'),('primem|authority', 'EPSG'),),
+ ),
+ TestSRS('PROJCS["NAD83 / Texas South Central",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",30.28333333333333],PARAMETER["standard_parallel_2",28.38333333333333],PARAMETER["latitude_of_origin",27.83333333333333],PARAMETER["central_meridian",-99],PARAMETER["false_easting",600000],PARAMETER["false_northing",4000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32140"]]',
+ proj=None, epsg=32140, projected=True, geographic=False, local=False,
+ lin_name='metre', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
+ auth={'PROJCS' : ('EPSG', '32140'), 'spheroid' : ('EPSG', '7019'), 'unit' : ('EPSG', '9001'),},
+ attr=(('DATUM', 'North_American_Datum_1983'),(('SPHEROID', 2), '298.257222101'),('PROJECTION','Lambert_Conformal_Conic_2SP'),),
+ ),
+ TestSRS('PROJCS["NAD_1983_StatePlane_Texas_South_Central_FIPS_4204_Feet",GEOGCS["GCS_North_American_1983",DATUM["North_American_Datum_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["False_Easting",1968500.0],PARAMETER["False_Northing",13123333.33333333],PARAMETER["Central_Meridian",-99.0],PARAMETER["Standard_Parallel_1",28.38333333333333],PARAMETER["Standard_Parallel_2",30.28333333333334],PARAMETER["Latitude_Of_Origin",27.83333333333333],UNIT["Foot_US",0.3048006096012192]]',
+ proj=None, epsg=None, projected=True, geographic=False, local=False,
+ lin_name='Foot_US', ang_name='Degree', lin_units=0.3048006096012192, ang_units=0.0174532925199,
+ auth={'PROJCS' : (None, None),},
+ attr=(('PROJCS|GeOgCs|spheroid', 'GRS_1980'),(('projcs', 9), 'UNIT'), (('projcs', 11), None),),
+ ),
+ # This is really ESRI format, not WKT -- but the import should work the same
+ TestSRS('LOCAL_CS["Non-Earth (Meter)",LOCAL_DATUM["Local Datum",0],UNIT["Meter",1.0],AXIS["X",EAST],AXIS["Y",NORTH]]',
+ esri=True, proj=None, epsg=None, projected=False, geographic=False, local=True,
+ lin_name='Meter', ang_name='degree', lin_units=1.0, ang_units=0.0174532925199,
+ attr=(('LOCAL_DATUM', 'Local Datum'), ('unit', 'Meter')),
+ ),
+ )
+
+# Well-Known Names
+well_known = (TestSRS('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"]]', wk='WGS84', name='WGS 84', attrs=(('GEOGCS|AUTHORITY', 1, '4326'), ('SPHEROID', 'WGS 84'))),
+ TestSRS('GEOGCS["WGS 72",DATUM["WGS_1972",SPHEROID["WGS 72",6378135,298.26,AUTHORITY["EPSG","7043"]],AUTHORITY["EPSG","6322"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4322"]]', wk='WGS72', name='WGS 72', attrs=(('GEOGCS|AUTHORITY', 1, '4322'), ('SPHEROID', 'WGS 72'))),
+ TestSRS('GEOGCS["NAD27",DATUM["North_American_Datum_1927",SPHEROID["Clarke 1866",6378206.4,294.9786982138982,AUTHORITY["EPSG","7008"]],AUTHORITY["EPSG","6267"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4267"]]', wk='NAD27', name='NAD27', attrs=(('GEOGCS|AUTHORITY', 1, '4267'), ('SPHEROID', 'Clarke 1866'))),
+ TestSRS('GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]]', wk='NAD83', name='NAD83', attrs=(('GEOGCS|AUTHORITY', 1, '4269'), ('SPHEROID', 'GRS 1980'))),
+ TestSRS('PROJCS["NZGD49 / Karamea Circuit",GEOGCS["NZGD49",DATUM["New_Zealand_Geodetic_Datum_1949",SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]],TOWGS84[59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993],AUTHORITY["EPSG","6272"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4272"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",-41.28991152777778],PARAMETER["central_meridian",172.1090281944444],PARAMETER["scale_factor",1],PARAMETER["false_easting",300000],PARAMETER["false_northing",700000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","27216"]]', wk='EPSG:27216', name='NZGD49 / Karamea Circuit', attrs=(('PROJECTION','Transverse_Mercator'), ('SPHEROID', 'International 1924'))),
+ )
+
+bad_srlist = ('Foobar', 'OOJCS["NAD83 / Texas South Central",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",30.28333333333333],PARAMETER["standard_parallel_2",28.38333333333333],PARAMETER["latitude_of_origin",27.83333333333333],PARAMETER["central_meridian",-99],PARAMETER["false_easting",600000],PARAMETER["false_northing",4000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32140"]]',)
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
+class SpatialRefTest(unittest.TestCase):
+
+ def test01_wkt(self):
+ "Testing initialization on valid OGC WKT."
+ for s in srlist:
+ srs = SpatialReference(s.wkt)
+
+ def test02_bad_wkt(self):
+ "Testing initialization on invalid WKT."
+ for bad in bad_srlist:
+ try:
+ srs = SpatialReference(bad)
+ srs.validate()
+ except (SRSException, OGRException):
+ pass
+ else:
+ self.fail('Should not have initialized on bad WKT "%s"!')
+
+ def test03_get_wkt(self):
+ "Testing getting the WKT."
+ for s in srlist:
+ srs = SpatialReference(s.wkt)
+ self.assertEqual(s.wkt, srs.wkt)
+
+ def test04_proj(self):
+ "Test PROJ.4 import and export."
+ for s in srlist:
+ if s.proj:
+ srs1 = SpatialReference(s.wkt)
+ srs2 = SpatialReference(s.proj)
+ self.assertEqual(srs1.proj, srs2.proj)
+
+ def test05_epsg(self):
+ "Test EPSG import."
+ for s in srlist:
+ if s.epsg:
+ srs1 = SpatialReference(s.wkt)
+ srs2 = SpatialReference(s.epsg)
+ srs3 = SpatialReference(str(s.epsg))
+ srs4 = SpatialReference('EPSG:%d' % s.epsg)
+ for srs in (srs1, srs2, srs3, srs4):
+ for attr, expected in s.attr:
+ self.assertEqual(expected, srs[attr])
+
+ def test07_boolean_props(self):
+ "Testing the boolean properties."
+ for s in srlist:
+ srs = SpatialReference(s.wkt)
+ self.assertEqual(s.projected, srs.projected)
+ self.assertEqual(s.geographic, srs.geographic)
+
+ def test08_angular_linear(self):
+ "Testing the linear and angular units routines."
+ for s in srlist:
+ srs = SpatialReference(s.wkt)
+ self.assertEqual(s.ang_name, srs.angular_name)
+ self.assertEqual(s.lin_name, srs.linear_name)
+ self.assertAlmostEqual(s.ang_units, srs.angular_units, 9)
+ self.assertAlmostEqual(s.lin_units, srs.linear_units, 9)
+
+ def test09_authority(self):
+ "Testing the authority name & code routines."
+ for s in srlist:
+ if hasattr(s, 'auth'):
+ srs = SpatialReference(s.wkt)
+ for target, tup in s.auth.items():
+ self.assertEqual(tup[0], srs.auth_name(target))
+ self.assertEqual(tup[1], srs.auth_code(target))
+
+ def test10_attributes(self):
+ "Testing the attribute retrieval routines."
+ for s in srlist:
+ srs = SpatialReference(s.wkt)
+ for tup in s.attr:
+ att = tup[0] # Attribute to test
+ exp = tup[1] # Expected result
+ self.assertEqual(exp, srs[att])
+
+ def test11_wellknown(self):
+ "Testing Well Known Names of Spatial References."
+ for s in well_known:
+ srs = SpatialReference(s.wk)
+ self.assertEqual(s.name, srs.name)
+ for tup in s.attrs:
+ if len(tup) == 2:
+ key = tup[0]
+ exp = tup[1]
+ elif len(tup) == 3:
+ key = tup[:2]
+ exp = tup[2]
+ self.assertEqual(srs[key], exp)
+
+ def test12_coordtransform(self):
+ "Testing initialization of a CoordTransform."
+ target = SpatialReference('WGS84')
+ for s in srlist:
+ if s.proj:
+ ct = CoordTransform(SpatialReference(s.wkt), target)
+
+ def test13_attr_value(self):
+ "Testing the attr_value() method."
+ s1 = SpatialReference('WGS84')
+ self.assertRaises(TypeError, s1.__getitem__, 0)
+ self.assertRaises(TypeError, s1.__getitem__, ('GEOGCS', 'foo'))
+ self.assertEqual('WGS 84', s1['GEOGCS'])
+ self.assertEqual('WGS_1984', s1['DATUM'])
+ self.assertEqual('EPSG', s1['AUTHORITY'])
+ self.assertEqual(4326, int(s1['AUTHORITY', 1]))
+ self.assertEqual(None, s1['FOOBAR'])