mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
gis: gdal: OSGeo sprint -- cleaned up spatial references associated with geometries (fixed a segfault); cleaned up Envelope module (thanks to ww for help), and added tests; added a test module for invoking all gdal tests; changed exception style.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6436 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
cfb807a1fb
commit
9eb115e304
@ -1,12 +1,39 @@
|
|||||||
|
"""
|
||||||
|
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: Layer for accessing OGR Geometry objects.
|
||||||
|
|
||||||
|
OGRGeomType: A class for representing the different OGR Geometry
|
||||||
|
types (GDAL library not required).
|
||||||
|
|
||||||
|
SpatialReference: Represents OSR Spatial Reference objects.
|
||||||
|
"""
|
||||||
|
# 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:
|
try:
|
||||||
from django.contrib.gis.gdal.driver import Driver
|
from django.contrib.gis.gdal.driver import Driver
|
||||||
from django.contrib.gis.gdal.envelope import Envelope
|
|
||||||
from django.contrib.gis.gdal.datasource import DataSource
|
from django.contrib.gis.gdal.datasource import DataSource
|
||||||
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
||||||
from django.contrib.gis.gdal.geometries import OGRGeometry
|
from django.contrib.gis.gdal.geometries import OGRGeometry
|
||||||
from django.contrib.gis.gdal.geomtype import OGRGeomType
|
|
||||||
from django.contrib.gis.gdal.error import check_err, OGRException, SRSException
|
|
||||||
HAS_GDAL = True
|
HAS_GDAL = True
|
||||||
except:
|
except:
|
||||||
HAS_GDAL = False
|
HAS_GDAL = False
|
||||||
|
|
||||||
|
# The envelope, error, and geomtype modules do not actually require the
|
||||||
|
# GDAL library.
|
||||||
|
from django.contrib.gis.gdal.envelope import Envelope
|
||||||
|
from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError, SRSException
|
||||||
|
from django.contrib.gis.gdal.geomtype import OGRGeomType
|
||||||
|
@ -4,7 +4,7 @@ from ctypes import c_char_p, c_int, c_void_p, byref, string_at
|
|||||||
|
|
||||||
# The GDAL C library, OGR exceptions, and the Layer object.
|
# The GDAL C library, OGR exceptions, and the Layer object.
|
||||||
from django.contrib.gis.gdal.libgdal import lgdal
|
from django.contrib.gis.gdal.libgdal import lgdal
|
||||||
from django.contrib.gis.gdal.error import OGRException, check_err
|
from django.contrib.gis.gdal.error import OGRException, OGRIndexError, check_err
|
||||||
from django.contrib.gis.gdal.layer import Layer
|
from django.contrib.gis.gdal.layer import Layer
|
||||||
from django.contrib.gis.gdal.driver import Driver
|
from django.contrib.gis.gdal.driver import Driver
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class DataSource(object):
|
|||||||
# Registering all the drivers, this needs to be done
|
# Registering all the drivers, this needs to be done
|
||||||
# _before_ we try to open up a data source.
|
# _before_ we try to open up a data source.
|
||||||
if not lgdal.OGRGetDriverCount() and not lgdal.OGRRegisterAll():
|
if not lgdal.OGRGetDriverCount() and not lgdal.OGRRegisterAll():
|
||||||
raise OGRException, 'Could not register all the OGR data source drivers!'
|
raise OGRException('Could not register all the OGR data source drivers!')
|
||||||
|
|
||||||
if isinstance(ds_input, StringType):
|
if isinstance(ds_input, StringType):
|
||||||
|
|
||||||
@ -72,12 +72,12 @@ class DataSource(object):
|
|||||||
elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p):
|
elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p):
|
||||||
ds = ds_input
|
ds = ds_input
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Invalid data source input type: %s' % str(type(ds_input))
|
raise OGRException('Invalid data source input type: %s' % str(type(ds_input)))
|
||||||
|
|
||||||
# Raise an exception if the returned pointer is NULL
|
# Raise an exception if the returned pointer is NULL
|
||||||
if not ds:
|
if not ds:
|
||||||
self._ds = False
|
self._ds = False
|
||||||
raise OGRException, 'Invalid data source file "%s"' % ds_input
|
raise OGRException('Invalid data source file "%s"' % ds_input)
|
||||||
else:
|
else:
|
||||||
self._ds = ds
|
self._ds = ds
|
||||||
self._driver = Driver(ds_driver)
|
self._driver = Driver(ds_driver)
|
||||||
@ -95,10 +95,10 @@ class DataSource(object):
|
|||||||
"Allows use of the index [] operator to get a layer at the index."
|
"Allows use of the index [] operator to get a layer at the index."
|
||||||
if isinstance(index, StringType):
|
if isinstance(index, StringType):
|
||||||
l = lgdal.OGR_DS_GetLayerByName(self._ds, c_char_p(index))
|
l = lgdal.OGR_DS_GetLayerByName(self._ds, c_char_p(index))
|
||||||
if not l: raise IndexError, 'invalid OGR Layer name given: "%s"' % index
|
if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index)
|
||||||
else:
|
else:
|
||||||
if index < 0 or index >= self.layer_count:
|
if index < 0 or index >= self.layer_count:
|
||||||
raise IndexError, 'index out of range'
|
raise OGRIndexError('index out of range')
|
||||||
l = lgdal.OGR_DS_GetLayer(self._ds, c_int(index))
|
l = lgdal.OGR_DS_GetLayer(self._ds, c_int(index))
|
||||||
return Layer(l)
|
return Layer(l)
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ class Driver(object):
|
|||||||
elif isinstance(input, c_void_p):
|
elif isinstance(input, c_void_p):
|
||||||
dr = input
|
dr = input
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Unrecognized input type for OGR Driver: %s' % str(type(input))
|
raise OGRException('Unrecognized input type for OGR Driver: %s' % str(type(input)))
|
||||||
|
|
||||||
# Making sure we get a valid pointer to the OGR Driver
|
# Making sure we get a valid pointer to the OGR Driver
|
||||||
if not dr:
|
if not dr:
|
||||||
raise OGRException, 'Could not initialize OGR Driver on input: %s' % str(input)
|
raise OGRException('Could not initialize OGR Driver on input: %s' % str(input))
|
||||||
self._dr = dr
|
self._dr = dr
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -61,7 +61,7 @@ class Driver(object):
|
|||||||
# Only register all if the driver count is 0 (or else all drivers
|
# Only register all if the driver count is 0 (or else all drivers
|
||||||
# will be registered over and over again)
|
# will be registered over and over again)
|
||||||
if not self.driver_count and not lgdal.OGRRegisterAll():
|
if not self.driver_count and not lgdal.OGRRegisterAll():
|
||||||
raise OGRException, 'Could not register all the OGR data source drivers!'
|
raise OGRException('Could not register all the OGR data source drivers!')
|
||||||
|
|
||||||
# Driver properties
|
# Driver properties
|
||||||
@property
|
@property
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
from ctypes import Structure, c_double
|
|
||||||
from types import TupleType
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The GDAL/OGR library uses an Envelope structure to hold the bounding
|
The GDAL/OGR library uses an Envelope structure to hold the bounding
|
||||||
box information for a geometry. The envelope (bounding box) contains
|
box information for a geometry. The envelope (bounding box) contains
|
||||||
@ -14,6 +11,9 @@ from types import TupleType
|
|||||||
Lower left (min_x, min_y) o----------+
|
Lower left (min_x, min_y) o----------+
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from ctypes import Structure, c_double
|
||||||
|
from types import TupleType, ListType
|
||||||
|
from django.contrib.gis.gdal.error import OGRException
|
||||||
|
|
||||||
# The OGR definition of an Envelope is a C structure containing four doubles.
|
# The OGR definition of an Envelope is a C structure containing four doubles.
|
||||||
# See the 'ogr_core.h' source file for more information:
|
# See the 'ogr_core.h' source file for more information:
|
||||||
@ -27,25 +27,48 @@ class OGREnvelope(Structure):
|
|||||||
]
|
]
|
||||||
|
|
||||||
class Envelope(object):
|
class Envelope(object):
|
||||||
"A class that will wrap an OGR Envelope structure."
|
"""
|
||||||
|
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):
|
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 len(args) == 1:
|
||||||
if isinstance(args[0], OGREnvelope):
|
if isinstance(args[0], OGREnvelope):
|
||||||
# OGREnvelope (a ctypes Structure) was passed in.
|
# OGREnvelope (a ctypes Structure) was passed in.
|
||||||
self._envelope = args[0]
|
self._envelope = args[0]
|
||||||
elif isinstance(args[0], TupleType) and len(args[0]) == 4:
|
elif isinstance(args[0], (TupleType, ListType)):
|
||||||
# A Tuple was passed in
|
# A tuple was passed in.
|
||||||
self._from_tuple(args[0])
|
if len(args[0]) != 4:
|
||||||
|
raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0]))
|
||||||
|
else:
|
||||||
|
self._from_sequence(args[0])
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Incorrect type of argument: %s' % str(type(args[0]))
|
raise TypeError('Incorrect type of argument: %s' % str(type(args[0])))
|
||||||
elif len(args) == 4:
|
elif len(args) == 4:
|
||||||
self._from_tuple(args)
|
# Individiual parameters passed in.
|
||||||
|
# Thanks to ww for the help
|
||||||
|
self._from_sequence(map(float, args))
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Incorrect number of arguments!'
|
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):
|
def __eq__(self, other):
|
||||||
"Returns true if the envelopes are equivalent; can compare against other Envelopes and 4-tuples."
|
"""
|
||||||
|
Returns True if the envelopes are equivalent; can compare against
|
||||||
|
other Envelopes and 4-tuples.
|
||||||
|
"""
|
||||||
if isinstance(other, Envelope):
|
if isinstance(other, Envelope):
|
||||||
return (self.min_x == other.min_x) and (self.min_y == other.min_y) and \
|
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)
|
(self.max_x == other.max_x) and (self.max_y == other.max_y)
|
||||||
@ -53,19 +76,19 @@ class Envelope(object):
|
|||||||
return (self.min_x == other[0]) and (self.min_y == other[1]) and \
|
return (self.min_x == other[0]) and (self.min_y == other[1]) and \
|
||||||
(self.max_x == other[2]) and (self.max_y == other[3])
|
(self.max_x == other[2]) and (self.max_y == other[3])
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Equivalence testing only works with other Envelopes.'
|
raise OGRException('Equivalence testing only works with other Envelopes.')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"Returns a string representation of the tuple."
|
"Returns a string representation of the tuple."
|
||||||
return str(self.tuple)
|
return str(self.tuple)
|
||||||
|
|
||||||
def _from_tuple(self, tup):
|
def _from_sequence(self, seq):
|
||||||
"Initializes the C OGR Envelope structure from the given tuple."
|
"Initializes the C OGR Envelope structure from the given sequence."
|
||||||
self._envelope = OGREnvelope()
|
self._envelope = OGREnvelope()
|
||||||
self._envelope.MinX = tup[0]
|
self._envelope.MinX = seq[0]
|
||||||
self._envelope.MinY = tup[1]
|
self._envelope.MinY = seq[1]
|
||||||
self._envelope.MaxX = tup[2]
|
self._envelope.MaxX = seq[2]
|
||||||
self._envelope.MaxY = tup[3]
|
self._envelope.MaxY = seq[3]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def min_x(self):
|
def min_x(self):
|
||||||
@ -106,7 +129,7 @@ class Envelope(object):
|
|||||||
def wkt(self):
|
def wkt(self):
|
||||||
"Returns WKT representing a Polygon for this envelope."
|
"Returns WKT representing a Polygon for this envelope."
|
||||||
# TODO: Fix significant figures.
|
# 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,
|
return 'POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))' % \
|
||||||
self.max_x, self.max_y, self.max_x, self.min_y,
|
(self.min_x, self.min_y, self.min_x, self.max_y,
|
||||||
self.min_x, self.min_y)
|
self.max_x, self.max_y, self.max_x, self.min_y,
|
||||||
|
self.min_x, self.min_y)
|
||||||
|
@ -7,6 +7,7 @@ from django.contrib.gis.gdal.libgdal import lgdal
|
|||||||
from django.contrib.gis.gdal.error import OGRException, OGRIndexError
|
from django.contrib.gis.gdal.error import OGRException, OGRIndexError
|
||||||
from django.contrib.gis.gdal.field import Field
|
from django.contrib.gis.gdal.field import Field
|
||||||
from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType
|
from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType
|
||||||
|
from django.contrib.gis.gdal.srs import SpatialReference
|
||||||
|
|
||||||
# For more information, see the OGR C API source code:
|
# For more information, see the OGR C API source code:
|
||||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||||
@ -21,7 +22,7 @@ class Feature(object):
|
|||||||
self._feat = 0 # Initially NULL
|
self._feat = 0 # Initially NULL
|
||||||
self._fdefn = 0
|
self._fdefn = 0
|
||||||
if not f:
|
if not f:
|
||||||
raise OGRException, 'Cannot create OGR Feature, invalid pointer given.'
|
raise OGRException('Cannot create OGR Feature, invalid pointer given.')
|
||||||
self._feat = f
|
self._feat = f
|
||||||
self._fdefn = lgdal.OGR_F_GetDefnRef(f)
|
self._fdefn = lgdal.OGR_F_GetDefnRef(f)
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ class Feature(object):
|
|||||||
i = self.index(index)
|
i = self.index(index)
|
||||||
else:
|
else:
|
||||||
if index < 0 or index > self.num_fields:
|
if index < 0 or index > self.num_fields:
|
||||||
raise OGRIndexError, 'index out of range'
|
raise OGRIndexError('index out of range')
|
||||||
i = index
|
i = index
|
||||||
return Field(lgdal.OGR_F_GetFieldDefnRef(self._feat, c_int(i)),
|
return Field(lgdal.OGR_F_GetFieldDefnRef(self._feat, c_int(i)),
|
||||||
string_at(lgdal.OGR_F_GetFieldAsString(self._feat, c_int(i))))
|
string_at(lgdal.OGR_F_GetFieldAsString(self._feat, c_int(i))))
|
||||||
@ -84,8 +85,20 @@ class Feature(object):
|
|||||||
@property
|
@property
|
||||||
def geom(self):
|
def geom(self):
|
||||||
"Returns the OGR Geometry for this Feature."
|
"Returns the OGR Geometry for this Feature."
|
||||||
# A clone is used, so destruction of the Geometry won't bork the Feature.
|
# Retrieving the geometry pointer for the feature.
|
||||||
return OGRGeometry(lgdal.OGR_G_Clone(lgdal.OGR_F_GetGeometryRef(self._feat)))
|
geom_ptr = lgdal.OGR_F_GetGeometryRef(self._feat)
|
||||||
|
if not geom_ptr:
|
||||||
|
raise OGRException('Cannot retrieve Geometry from the feature.')
|
||||||
|
|
||||||
|
# Attempting to retrieve the Spatial Reference for the geometry.
|
||||||
|
srs_ptr = lgdal.OGR_G_GetSpatialReference(geom_ptr)
|
||||||
|
if srs_ptr:
|
||||||
|
srs = SpatialReference(srs_ptr, 'ogr')
|
||||||
|
else:
|
||||||
|
srs = None
|
||||||
|
|
||||||
|
# Geometry is cloned so the feature isn't invalidated.
|
||||||
|
return OGRGeometry(lgdal.OGR_G_Clone(geom_ptr), srs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geom_type(self):
|
def geom_type(self):
|
||||||
@ -105,7 +118,7 @@ class Feature(object):
|
|||||||
def index(self, field_name):
|
def index(self, field_name):
|
||||||
"Returns the index of the given field name."
|
"Returns the index of the given field name."
|
||||||
i = lgdal.OGR_F_GetFieldIndex(self._feat, c_char_p(field_name))
|
i = lgdal.OGR_F_GetFieldIndex(self._feat, c_char_p(field_name))
|
||||||
if i < 0: raise OGRIndexError, 'invalid OFT field name given: "%s"' % field_name
|
if i < 0: raise OGRIndexError('invalid OFT field name given: "%s"' % field_name)
|
||||||
return i
|
return i
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from ctypes import string_at
|
from ctypes import string_at
|
||||||
|
|
||||||
from django.contrib.gis.gdal.libgdal import lgdal
|
from django.contrib.gis.gdal.libgdal import lgdal
|
||||||
from django.contrib.gis.gdal.error import OGRException
|
from django.contrib.gis.gdal.error import OGRException
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ class Field(object):
|
|||||||
self._fld = 0 # Initially NULL
|
self._fld = 0 # Initially NULL
|
||||||
|
|
||||||
if not fld:
|
if not fld:
|
||||||
raise OGRException, 'Cannot create OGR Field, invalid pointer given.'
|
raise OGRException('Cannot create OGR Field, invalid pointer given.')
|
||||||
self._fld = fld
|
self._fld = fld
|
||||||
self._val = val
|
self._val = val
|
||||||
|
|
||||||
@ -64,7 +63,10 @@ class OFTReal(Field):
|
|||||||
return None
|
return None
|
||||||
class OFTRealList(Field): pass
|
class OFTRealList(Field): pass
|
||||||
|
|
||||||
class OFTString(Field): pass
|
class OFTString(Field):
|
||||||
|
def __str__(self):
|
||||||
|
return '%s ("%s")' % (self.name, self.value)
|
||||||
|
|
||||||
class OFTStringList(Field): pass
|
class OFTStringList(Field): pass
|
||||||
class OFTWideString(Field): pass
|
class OFTWideString(Field): pass
|
||||||
class OFTWideStringList(Field): pass
|
class OFTWideStringList(Field): pass
|
||||||
|
@ -1,24 +1,13 @@
|
|||||||
# types & ctypes
|
|
||||||
from types import IntType, StringType
|
|
||||||
from ctypes import byref, string_at, c_char_p, c_double, c_int, c_void_p
|
|
||||||
|
|
||||||
# Getting geodjango gdal prerequisites
|
|
||||||
from django.contrib.gis.gdal.libgdal import lgdal
|
|
||||||
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
|
|
||||||
from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError
|
|
||||||
from django.contrib.gis.gdal.geomtype import OGRGeomType
|
|
||||||
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The OGRGeometry is a wrapper for using the OGR Geometry class
|
The OGRGeometry is a wrapper for using the OGR Geometry class
|
||||||
(see http://www.gdal.org/ogr/classOGRGeometry.html). OGRGeometry
|
(see http://www.gdal.org/ogr/classOGRGeometry.html). OGRGeometry
|
||||||
may be instantiated when reading geometries from OGR Data Sources
|
may be instantiated when reading geometries from OGR Data Sources
|
||||||
(e.g. SHP files), or when given OGC WKT (a string).
|
(e.g. SHP files), or when given OGC WKT (a string).
|
||||||
|
|
||||||
While the 'full' API is not present yet, the API is "pythonic" unlike
|
While the 'full' API is not present yet, the API is "pythonic" unlike
|
||||||
the traditional and "next-generation" OGR Python bindings. One major
|
the traditional and "next-generation" OGR Python bindings. One major
|
||||||
advantage OGR Geometries have over their GEOS counterparts is support
|
advantage OGR Geometries have over their GEOS counterparts is support
|
||||||
for spatial reference systems and their transformation.
|
for spatial reference systems and their transformation.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
>>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference
|
>>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference
|
||||||
@ -49,6 +38,16 @@ from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
|||||||
>>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects
|
>>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects
|
||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
|
# types & ctypes
|
||||||
|
from types import IntType, StringType
|
||||||
|
from ctypes import byref, string_at, c_char_p, c_double, c_int, c_void_p
|
||||||
|
|
||||||
|
# Getting GDAL prerequisites
|
||||||
|
from django.contrib.gis.gdal.libgdal import lgdal
|
||||||
|
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
|
||||||
|
from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError
|
||||||
|
from django.contrib.gis.gdal.geomtype import OGRGeomType
|
||||||
|
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
||||||
|
|
||||||
# For more information, see the OGR C API source code:
|
# For more information, see the OGR C API source code:
|
||||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||||
@ -75,37 +74,45 @@ get_area.argtypes = [c_void_p]
|
|||||||
class OGRGeometry(object):
|
class OGRGeometry(object):
|
||||||
"Generally encapsulates an OGR geometry."
|
"Generally encapsulates an OGR geometry."
|
||||||
|
|
||||||
def __init__(self, input, srs=False):
|
def __init__(self, geom_input, srs=None):
|
||||||
"Initializes Geometry on either WKT or an OGR pointer as input."
|
"Initializes Geometry on either WKT or an OGR pointer as input."
|
||||||
|
|
||||||
self._g = 0 # Initially NULL
|
self._g = 0 # Initially NULL
|
||||||
self._init_srs(srs)
|
|
||||||
|
|
||||||
if isinstance(input, StringType):
|
if isinstance(geom_input, StringType):
|
||||||
# First, trying the input as WKT
|
# First, trying the input as WKT
|
||||||
buf = c_char_p(input)
|
buf = c_char_p(geom_input)
|
||||||
g = c_void_p()
|
g = c_void_p()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
check_err(lgdal.OGR_G_CreateFromWkt(byref(buf), self._s._srs, byref(g)))
|
check_err(lgdal.OGR_G_CreateFromWkt(byref(buf), c_void_p(), byref(g)))
|
||||||
except OGRException, msg:
|
except OGRException:
|
||||||
try:
|
try:
|
||||||
ogr_t = OGRGeomType(input) # Seeing if the input is a valid short-hand string
|
# Seeing if the input is a valid short-hand string
|
||||||
|
ogr_t = OGRGeomType(geom_input)
|
||||||
g = lgdal.OGR_G_CreateGeometry(ogr_t.num)
|
g = lgdal.OGR_G_CreateGeometry(ogr_t.num)
|
||||||
except:
|
except:
|
||||||
raise OGRException, 'Could not initialize on WKT "%s"' % input
|
raise OGRException('Could not initialize OGR Geometry from: %s' % geom_input)
|
||||||
elif isinstance(input, OGRGeomType):
|
elif isinstance(geom_input, OGRGeomType):
|
||||||
g = lgdal.OGR_G_CreateGeometry(input.num)
|
g = lgdal.OGR_G_CreateGeometry(geom_input.num)
|
||||||
lgdal.OGR_G_AssignSpatialReference(g, self._s._srs)
|
elif isinstance(geom_input, IntType):
|
||||||
elif isinstance(input, IntType):
|
|
||||||
# OGR Pointer (integer) was the input
|
# OGR Pointer (integer) was the input
|
||||||
g = input
|
g = geom_input
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Type of input cannot be determined!'
|
raise OGRException('Type of input cannot be determined!')
|
||||||
|
|
||||||
|
# Assigning the SpatialReference object to the geometry, if valid.
|
||||||
|
if bool(srs):
|
||||||
|
if isinstance(srs, SpatialReference):
|
||||||
|
srs_ptr = srs._srs
|
||||||
|
else:
|
||||||
|
sr = SpatialReference(srs)
|
||||||
|
srs_ptr = sr._srs
|
||||||
|
lgdal.OGR_G_AssignSpatialReference(g, srs_ptr)
|
||||||
|
|
||||||
# Now checking the Geometry pointer before finishing initialization
|
# Now checking the Geometry pointer before finishing initialization
|
||||||
if not g:
|
if not g:
|
||||||
raise OGRException, 'Cannot create OGR Geometry from input: %s' % str(input)
|
raise OGRException('Cannot create OGR Geometry from input: %s' % str(geom_input))
|
||||||
self._g = g
|
self._g = g
|
||||||
|
|
||||||
# Setting the class depending upon the OGR Geometry Type
|
# Setting the class depending upon the OGR Geometry Type
|
||||||
@ -115,13 +122,6 @@ class OGRGeometry(object):
|
|||||||
"Deletes this Geometry."
|
"Deletes this Geometry."
|
||||||
if self._g: lgdal.OGR_G_DestroyGeometry(self._g)
|
if self._g: lgdal.OGR_G_DestroyGeometry(self._g)
|
||||||
|
|
||||||
def _init_srs(self, srs):
|
|
||||||
# Getting the spatial
|
|
||||||
if not isinstance(srs, SpatialReference):
|
|
||||||
self._s = SpatialReference() # creating an empty spatial reference
|
|
||||||
else:
|
|
||||||
self._s = srs.clone() # cloning the given spatial reference
|
|
||||||
|
|
||||||
### Geometry set-like operations ###
|
### Geometry set-like operations ###
|
||||||
# g = g1 | g2
|
# g = g1 | g2
|
||||||
def __or__(self, other):
|
def __or__(self, other):
|
||||||
@ -184,7 +184,11 @@ class OGRGeometry(object):
|
|||||||
@property
|
@property
|
||||||
def srs(self):
|
def srs(self):
|
||||||
"Returns the Spatial Reference for this Geometry."
|
"Returns the Spatial Reference for this Geometry."
|
||||||
return SpatialReference(lgdal.OSRClone(lgdal.OGR_G_GetSpatialReference(self._g)), 'ogr')
|
srs_ptr = lgdal.OGR_G_GetSpatialReference(self._g)
|
||||||
|
if srs_ptr:
|
||||||
|
return SpatialReference(lgdal.OSRClone(srs_ptr), 'ogr')
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geom_type(self):
|
def geom_type(self):
|
||||||
@ -196,13 +200,6 @@ class OGRGeometry(object):
|
|||||||
"Returns the Name of this Geometry."
|
"Returns the Name of this Geometry."
|
||||||
return string_at(lgdal.OGR_G_GetGeometryName(self._g))
|
return string_at(lgdal.OGR_G_GetGeometryName(self._g))
|
||||||
|
|
||||||
@property
|
|
||||||
def wkt(self):
|
|
||||||
"Returns the WKT form of the Geometry."
|
|
||||||
buf = c_char_p()
|
|
||||||
check_err(lgdal.OGR_G_ExportToWkt(self._g, byref(buf)))
|
|
||||||
return string_at(buf)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def area(self):
|
def area(self):
|
||||||
"Returns the area for a LinearRing, Polygon, or MultiPolygon; 0 otherwise."
|
"Returns the area for a LinearRing, Polygon, or MultiPolygon; 0 otherwise."
|
||||||
@ -215,6 +212,21 @@ class OGRGeometry(object):
|
|||||||
lgdal.OGR_G_GetEnvelope(self._g, byref(env))
|
lgdal.OGR_G_GetEnvelope(self._g, byref(env))
|
||||||
return Envelope(env)
|
return Envelope(env)
|
||||||
|
|
||||||
|
#### Output Methods ####
|
||||||
|
@property
|
||||||
|
def gml(self):
|
||||||
|
"Returns the GML representation of the Geometry."
|
||||||
|
buf = c_char_p()
|
||||||
|
check_err(lgdal.OGR_G_ExportToGML(self._g, byref(buf)))
|
||||||
|
return string_at(buf)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wkt(self):
|
||||||
|
"Returns the WKT representation of the Geometry."
|
||||||
|
buf = c_char_p()
|
||||||
|
check_err(lgdal.OGR_G_ExportToWkt(self._g, byref(buf)))
|
||||||
|
return string_at(buf)
|
||||||
|
|
||||||
#### Geometry Methods ####
|
#### Geometry Methods ####
|
||||||
def clone(self):
|
def clone(self):
|
||||||
"Clones this OGR Geometry."
|
"Clones this OGR Geometry."
|
||||||
@ -230,13 +242,13 @@ class OGRGeometry(object):
|
|||||||
def transform(self, coord_trans):
|
def transform(self, coord_trans):
|
||||||
"Transforms this Geometry with the given CoordTransform object."
|
"Transforms this Geometry with the given CoordTransform object."
|
||||||
if not isinstance(coord_trans, CoordTransform):
|
if not isinstance(coord_trans, CoordTransform):
|
||||||
raise OGRException, 'CoordTransform object required for transform.'
|
raise OGRException('CoordTransform object required for transform.')
|
||||||
check_err(lgdal.OGR_G_Transform(self._g, coord_trans._ct))
|
check_err(lgdal.OGR_G_Transform(self._g, coord_trans._ct))
|
||||||
|
|
||||||
def transform_to(self, srs):
|
def transform_to(self, srs):
|
||||||
"Transforms this Geometry with the given SpatialReference."
|
"Transforms this Geometry with the given SpatialReference."
|
||||||
if not isinstance(srs, SpatialReference):
|
if not isinstance(srs, SpatialReference):
|
||||||
raise OGRException, 'SpatialReference object required for transform_to.'
|
raise OGRException('SpatialReference object required for transform_to.')
|
||||||
check_err(lgdal.OGR_G_TransformTo(self._g, srs._srs))
|
check_err(lgdal.OGR_G_TransformTo(self._g, srs._srs))
|
||||||
|
|
||||||
#### Topology Methods ####
|
#### Topology Methods ####
|
||||||
@ -244,7 +256,7 @@ class OGRGeometry(object):
|
|||||||
"""A generalized function for topology operations, takes a GDAL function and
|
"""A generalized function for topology operations, takes a GDAL function and
|
||||||
the other geometry to perform the operation on."""
|
the other geometry to perform the operation on."""
|
||||||
if not isinstance(other, OGRGeometry):
|
if not isinstance(other, OGRGeometry):
|
||||||
raise OGRException, 'Must use another OGRGeometry object for topology operations!'
|
raise OGRException('Must use another OGRGeometry object for topology operations!')
|
||||||
|
|
||||||
# Calling the passed-in topology function with the other geometry
|
# Calling the passed-in topology function with the other geometry
|
||||||
status = topo_func(self._g, other._g)
|
status = topo_func(self._g, other._g)
|
||||||
@ -368,7 +380,7 @@ class LineString(OGRGeometry):
|
|||||||
elif self.coord_dim == 3:
|
elif self.coord_dim == 3:
|
||||||
return (x.value, y.value, z.value)
|
return (x.value, y.value, z.value)
|
||||||
else:
|
else:
|
||||||
raise OGRIndexError, 'index out of range: %s' % str(index)
|
raise OGRIndexError('index out of range: %s' % str(index))
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"Iterates over each point in the LineString."
|
"Iterates over each point in the LineString."
|
||||||
@ -401,9 +413,9 @@ class Polygon(OGRGeometry):
|
|||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
"Gets the ring at the specified index."
|
"Gets the ring at the specified index."
|
||||||
if index < 0 or index >= self.geom_count:
|
if index < 0 or index >= self.geom_count:
|
||||||
raise OGRIndexError, 'index out of range: %s' % str(index)
|
raise OGRIndexError('index out of range: %s' % str(index))
|
||||||
else:
|
else:
|
||||||
return OGRGeometry(lgdal.OGR_G_Clone(lgdal.OGR_G_GetGeometryRef(self._g, c_int(index))))
|
return OGRGeometry(lgdal.OGR_G_Clone(lgdal.OGR_G_GetGeometryRef(self._g, c_int(index))), self.srs)
|
||||||
|
|
||||||
# Polygon Properties
|
# Polygon Properties
|
||||||
@property
|
@property
|
||||||
@ -437,9 +449,9 @@ class GeometryCollection(OGRGeometry):
|
|||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
"Gets the Geometry at the specified index."
|
"Gets the Geometry at the specified index."
|
||||||
if index < 0 or index >= self.geom_count:
|
if index < 0 or index >= self.geom_count:
|
||||||
raise OGRIndexError, 'index out of range: %s' % str(index)
|
raise OGRIndexError('index out of range: %s' % str(index))
|
||||||
else:
|
else:
|
||||||
return OGRGeometry(lgdal.OGR_G_Clone(lgdal.OGR_G_GetGeometryRef(self._g, c_int(index))))
|
return OGRGeometry(lgdal.OGR_G_Clone(lgdal.OGR_G_GetGeometryRef(self._g, c_int(index))), self.srs)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"Iterates over each Geometry."
|
"Iterates over each Geometry."
|
||||||
@ -458,7 +470,7 @@ class GeometryCollection(OGRGeometry):
|
|||||||
tmp = OGRGeometry(geom)
|
tmp = OGRGeometry(geom)
|
||||||
ptr = tmp._g
|
ptr = tmp._g
|
||||||
else:
|
else:
|
||||||
raise OGRException, 'Must add an OGRGeometry.'
|
raise OGRException('Must add an OGRGeometry.')
|
||||||
lgdal.OGR_G_AddGeometry(self._g, ptr)
|
lgdal.OGR_G_AddGeometry(self._g, ptr)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -11,21 +11,21 @@ class OGRGeomType(object):
|
|||||||
'LinearRing']
|
'LinearRing']
|
||||||
__ogr_int = [1, 2, 3, 4, 5, 6, 7, 101]
|
__ogr_int = [1, 2, 3, 4, 5, 6, 7, 101]
|
||||||
|
|
||||||
def __init__(self, input):
|
def __init__(self, type_input):
|
||||||
"Figures out the correct OGR Type based upon the input."
|
"Figures out the correct OGR Type based upon the input."
|
||||||
if isinstance(input, OGRGeomType):
|
if isinstance(type_input, OGRGeomType):
|
||||||
self._index = input._index
|
self._index = type_input._index
|
||||||
elif isinstance(input, StringType):
|
elif isinstance(type_input, StringType):
|
||||||
idx = self._has_str(self.__ogr_str, input)
|
idx = self._has_str(self.__ogr_str, type_input)
|
||||||
if idx == None:
|
if idx == None:
|
||||||
raise OGRException, 'Invalid OGR String Type "%s"' % input
|
raise OGRException('Invalid OGR String Type "%s"' % type_input)
|
||||||
self._index = idx
|
self._index = idx
|
||||||
elif isinstance(input, int):
|
elif isinstance(type_input, int):
|
||||||
if not input in self.__ogr_int:
|
if not type_input in self.__ogr_int:
|
||||||
raise OGRException, 'Invalid OGR Integer Type: %d' % input
|
raise OGRException('Invalid OGR Integer Type: %d' % type_input)
|
||||||
self._index = self.__ogr_int.index(input)
|
self._index = self.__ogr_int.index(type_input)
|
||||||
else:
|
else:
|
||||||
raise TypeError, 'Invalid OGR Input type given!'
|
raise TypeError('Invalid OGR Input type given!')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"Returns a short-hand string form of the OGR Geometry type."
|
"Returns a short-hand string form of the OGR Geometry type."
|
||||||
@ -44,7 +44,7 @@ class OGRGeomType(object):
|
|||||||
if not other in self.__ogr_int: return False
|
if not other in self.__ogr_int: return False
|
||||||
return self.__ogr_int.index(other) == self._index
|
return self.__ogr_int.index(other) == self._index
|
||||||
else:
|
else:
|
||||||
raise TypeError, 'Cannot compare with type: %s' % str(type(other))
|
raise TypeError('Cannot compare with type: %s' % str(type(other)))
|
||||||
|
|
||||||
def _has_str(self, arr, s):
|
def _has_str(self, arr, s):
|
||||||
"Case-insensitive search of the string array for the given pattern."
|
"Case-insensitive search of the string array for the given pattern."
|
||||||
|
@ -79,7 +79,7 @@ class SpatialReference(object):
|
|||||||
_epsg_regex = re.compile('^EPSG:(?P<epsg>\d+)$', re.I)
|
_epsg_regex = re.compile('^EPSG:(?P<epsg>\d+)$', re.I)
|
||||||
|
|
||||||
#### Python 'magic' routines ####
|
#### Python 'magic' routines ####
|
||||||
def __init__(self, input='', srs_type='wkt'):
|
def __init__(self, srs_input='', srs_type='wkt'):
|
||||||
"Creates a spatial reference object from the given OGC Well Known Text (WKT)."
|
"Creates a spatial reference object from the given OGC Well Known Text (WKT)."
|
||||||
|
|
||||||
self._srs = 0 # Initially NULL
|
self._srs = 0 # Initially NULL
|
||||||
@ -87,45 +87,46 @@ class SpatialReference(object):
|
|||||||
# Creating an initial empty string buffer.
|
# Creating an initial empty string buffer.
|
||||||
buf = c_char_p('')
|
buf = c_char_p('')
|
||||||
|
|
||||||
if isinstance(input, UnicodeType):
|
# Encoding to ASCII if unicode passed in.
|
||||||
input = input.encode('ascii')
|
if isinstance(srs_input, UnicodeType):
|
||||||
|
srs_input = srs_input.encode('ascii')
|
||||||
|
|
||||||
if isinstance(input, StringType):
|
if isinstance(srs_input, StringType):
|
||||||
# Is this an EPSG well known name?
|
# Is this an EPSG well known name?
|
||||||
m = self._epsg_regex.match(input)
|
m = self._epsg_regex.match(srs_input)
|
||||||
if m:
|
if m:
|
||||||
srs_type = 'epsg'
|
srs_type = 'epsg'
|
||||||
input = int(m.group('epsg'))
|
srs_input = int(m.group('epsg'))
|
||||||
# Is this a short-hand well known name?
|
# Is this a short-hand well known name?
|
||||||
elif input in self._well_known:
|
elif srs_input in self._well_known:
|
||||||
srs_type = 'epsg'
|
srs_type = 'epsg'
|
||||||
input = self._well_known[input]
|
srs_input = self._well_known[srs_input]
|
||||||
elif srs_type == 'proj':
|
elif srs_type == 'proj':
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
buf = c_char_p(input)
|
buf = c_char_p(srs_input)
|
||||||
elif isinstance(input, int):
|
elif isinstance(srs_input, int):
|
||||||
if srs_type == 'wkt': srs_type = 'epsg' # want to try epsg if only integer provided
|
if srs_type == 'wkt': srs_type = 'epsg' # want to try epsg if only integer provided
|
||||||
if srs_type not in ('epsg', 'ogr'):
|
if srs_type not in ('epsg', 'ogr'):
|
||||||
raise SRSException, 'Integer input requires SRS type of "ogr" or "epsg".'
|
raise SRSException('Integer input requires SRS type of "ogr" or "epsg".')
|
||||||
else:
|
else:
|
||||||
raise TypeError, 'Invalid SRS type "%s"' % srs_type
|
raise TypeError('Invalid SRS type "%s"' % srs_type)
|
||||||
|
|
||||||
# Calling OSRNewSpatialReference with the string buffer.
|
# Calling OSRNewSpatialReference with the string buffer.
|
||||||
if srs_type == 'ogr':
|
if srs_type == 'ogr':
|
||||||
srs = input # Input is OGR pointer
|
srs = srs_input # SRS input is OGR pointer
|
||||||
else:
|
else:
|
||||||
srs = lgdal.OSRNewSpatialReference(buf)
|
srs = lgdal.OSRNewSpatialReference(buf)
|
||||||
|
|
||||||
# If the pointer is NULL, throw an exception.
|
# If the pointer is NULL, throw an exception.
|
||||||
if not srs:
|
if not srs:
|
||||||
raise SRSException, 'Could not create spatial reference from WKT! (%s)' % input
|
raise SRSException('Could not create spatial reference from: %s' % srs_input)
|
||||||
else:
|
else:
|
||||||
self._srs = srs
|
self._srs = srs
|
||||||
|
|
||||||
# Post-processing if in PROJ.4 or EPSG formats.
|
# Post-processing if in PROJ.4 or EPSG formats.
|
||||||
if srs_type == 'proj': self.import_proj(input)
|
if srs_type == 'proj': self.import_proj(srs_input)
|
||||||
elif srs_type == 'epsg': self.import_epsg(input)
|
elif srs_type == 'epsg': self.import_epsg(srs_input)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"Destroys this spatial reference."
|
"Destroys this spatial reference."
|
||||||
@ -142,6 +143,14 @@ class SpatialReference(object):
|
|||||||
else:
|
else:
|
||||||
return self.attr_value(target)
|
return self.attr_value(target)
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
"Returns True if this SpatialReference object is valid."
|
||||||
|
try:
|
||||||
|
self.validate()
|
||||||
|
return True
|
||||||
|
except OGRException:
|
||||||
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"The string representation uses 'pretty' WKT."
|
"The string representation uses 'pretty' WKT."
|
||||||
return self.pretty_wkt
|
return self.pretty_wkt
|
||||||
@ -189,6 +198,14 @@ class SpatialReference(object):
|
|||||||
elif self.local: return self.attr_value('LOCAL_CS')
|
elif self.local: return self.attr_value('LOCAL_CS')
|
||||||
else: return None
|
else: return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def srid(self):
|
||||||
|
"""
|
||||||
|
Returns the EPSG SRID of this Spatial Reference, will be None if
|
||||||
|
if undefined.
|
||||||
|
"""
|
||||||
|
return self.srs['AUTHORITY', 1]
|
||||||
|
|
||||||
#### Unit Properties ####
|
#### Unit Properties ####
|
||||||
def _cache_linear(self):
|
def _cache_linear(self):
|
||||||
"Caches the linear units value and name."
|
"Caches the linear units value and name."
|
||||||
@ -345,10 +362,10 @@ class CoordTransform(object):
|
|||||||
"Initializes on a source and target SpatialReference objects."
|
"Initializes on a source and target SpatialReference objects."
|
||||||
self._ct = 0 # Initially NULL
|
self._ct = 0 # Initially NULL
|
||||||
if not isinstance(source, SpatialReference) or not isinstance(target, SpatialReference):
|
if not isinstance(source, SpatialReference) or not isinstance(target, SpatialReference):
|
||||||
raise SRSException, 'source and target must be of type SpatialReference'
|
raise SRSException('source and target must be of type SpatialReference')
|
||||||
ct = lgdal.OCTNewCoordinateTransformation(source._srs, target._srs)
|
ct = lgdal.OCTNewCoordinateTransformation(source._srs, target._srs)
|
||||||
if not ct:
|
if not ct:
|
||||||
raise SRSException, 'could not intialize CoordTransform object'
|
raise SRSException('could not intialize CoordTransform object')
|
||||||
self._ct = ct
|
self._ct = ct
|
||||||
self._srs1_name = source.name
|
self._srs1_name = source.name
|
||||||
self._srs2_name = target.name
|
self._srs2_name = target.name
|
||||||
|
@ -13,6 +13,7 @@ if HAS_GDAL:
|
|||||||
test_suite_names += [
|
test_suite_names += [
|
||||||
'test_gdal_driver',
|
'test_gdal_driver',
|
||||||
'test_gdal_ds',
|
'test_gdal_ds',
|
||||||
|
'test_gdal_envelope',
|
||||||
'test_gdal_geom',
|
'test_gdal_geom',
|
||||||
'test_gdal_srs',
|
'test_gdal_srs',
|
||||||
'test_spatialrefsys',
|
'test_spatialrefsys',
|
||||||
|
24
django/contrib/gis/tests/test_gdal.py
Normal file
24
django/contrib/gis/tests/test_gdal.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from unittest import TestSuite, TextTestRunner
|
||||||
|
|
||||||
|
# Importing the GDAL test modules.
|
||||||
|
from django.contrib.gis.tests import \
|
||||||
|
test_gdal_driver, test_gdal_ds, test_gdal_envelope, \
|
||||||
|
test_gdal_geom, test_gdal_srs
|
||||||
|
|
||||||
|
|
||||||
|
test_suites = [test_gdal_driver.suite(),
|
||||||
|
test_gdal_ds.suite(),
|
||||||
|
test_gdal_envelope.suite(),
|
||||||
|
test_gdal_geom.suite(),
|
||||||
|
test_gdal_srs.suite(),
|
||||||
|
]
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
"Builds a test suite for the GDAL tests."
|
||||||
|
s = TestSuite()
|
||||||
|
map(s.addTest, test_suites)
|
||||||
|
return s
|
||||||
|
|
||||||
|
def run(verbosity=1):
|
||||||
|
"Runs the tests that do not require geographic (GEOS, GDAL, etc.) models."
|
||||||
|
TextTestRunner(verbosity=verbosity).run(suite())
|
@ -1,6 +1,5 @@
|
|||||||
import os, os.path, unittest
|
import os, os.path, unittest
|
||||||
from django.contrib.gis.gdal import DataSource, OGRException
|
from django.contrib.gis.gdal import DataSource, Envelope, OGRException, OGRIndexError
|
||||||
from django.contrib.gis.gdal.envelope import Envelope
|
|
||||||
from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
|
from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
|
||||||
|
|
||||||
# Path for SHP files
|
# Path for SHP files
|
||||||
@ -48,7 +47,7 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
# Making sure indexing works
|
# Making sure indexing works
|
||||||
try:
|
try:
|
||||||
ds[len(ds)]
|
ds[len(ds)]
|
||||||
except IndexError:
|
except OGRIndexError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
self.fail('Expected an IndexError!')
|
self.fail('Expected an IndexError!')
|
||||||
@ -106,7 +105,9 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
|
|
||||||
# Asserting the string representation, and making sure we get
|
# Asserting the string representation, and making sure we get
|
||||||
# the proper OGR Field instance.
|
# the proper OGR Field instance.
|
||||||
self.assertEqual('%s (%s)' % (k, fld.value), str(fld))
|
if isinstance(fld, OFTString): fmt = '%s ("%s")'
|
||||||
|
else: fmt = '%s (%s)'
|
||||||
|
self.assertEqual(fmt % (k, fld.value), str(fld))
|
||||||
self.assertEqual(True, isinstance(fld, v))
|
self.assertEqual(True, isinstance(fld, v))
|
||||||
|
|
||||||
# Testing __iter__ on the Feature
|
# Testing __iter__ on the Feature
|
||||||
@ -136,5 +137,3 @@ def suite():
|
|||||||
|
|
||||||
def run(verbosity=2):
|
def run(verbosity=2):
|
||||||
unittest.TextTestRunner(verbosity=verbosity).run(suite())
|
unittest.TextTestRunner(verbosity=verbosity).run(suite())
|
||||||
|
|
||||||
|
|
||||||
|
45
django/contrib/gis/tests/test_gdal_envelope.py
Normal file
45
django/contrib/gis/tests/test_gdal_envelope.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import unittest
|
||||||
|
from django.contrib.gis.gdal import Envelope, OGRException
|
||||||
|
|
||||||
|
class EnvelopeTest(unittest.TestCase):
|
||||||
|
|
||||||
|
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, u'foo')
|
||||||
|
|
||||||
|
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 suite():
|
||||||
|
s = unittest.TestSuite()
|
||||||
|
s.addTest(unittest.makeSuite(EnvelopeTest))
|
||||||
|
return s
|
||||||
|
|
||||||
|
def run(verbosity=2):
|
||||||
|
unittest.TextTestRunner(verbosity=verbosity).run(suite())
|
@ -1,5 +1,5 @@
|
|||||||
import unittest
|
import unittest
|
||||||
from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, OGRException
|
from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, OGRException, SpatialReference
|
||||||
from geometries import *
|
from geometries import *
|
||||||
|
|
||||||
class OGRGeomTest(unittest.TestCase):
|
class OGRGeomTest(unittest.TestCase):
|
||||||
@ -130,6 +130,18 @@ class OGRGeomTest(unittest.TestCase):
|
|||||||
self.assertEqual(mp.n_p, mpoly.point_count)
|
self.assertEqual(mp.n_p, mpoly.point_count)
|
||||||
self.assertEqual(mp.num_geom, len(mpoly))
|
self.assertEqual(mp.num_geom, len(mpoly))
|
||||||
|
|
||||||
|
def test09_srs(self):
|
||||||
|
"Testing OGR Geometries with Spatial Reference objects."
|
||||||
|
for mp in multipolygons:
|
||||||
|
sr = SpatialReference('WGS84')
|
||||||
|
mpoly = OGRGeometry(mp.wkt, sr)
|
||||||
|
self.assertEqual(sr.wkt, mpoly.srs.wkt)
|
||||||
|
for poly in mpoly:
|
||||||
|
self.assertEqual(sr.wkt, poly.srs.wkt)
|
||||||
|
for ring in poly:
|
||||||
|
self.assertEqual(sr.wkt, ring.srs.wkt)
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
s = unittest.TestSuite()
|
s = unittest.TestSuite()
|
||||||
s.addTest(unittest.makeSuite(OGRGeomTest))
|
s.addTest(unittest.makeSuite(OGRGeomTest))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user