diff --git a/django/contrib/gis/gdal/__init__.py b/django/contrib/gis/gdal/__init__.py index 180dc558ac..255f781ddb 100644 --- a/django/contrib/gis/gdal/__init__.py +++ b/django/contrib/gis/gdal/__init__.py @@ -1,7 +1,8 @@ -from Driver import Driver -from Envelope import Envelope -from DataSource import DataSource -from SpatialReference import SpatialReference, CoordTransform -from OGRGeometry import OGRGeometry, OGRGeomType -from OGRError import check_err, OGRException, SRSException +from driver import Driver +from envelope import Envelope +from datasource import DataSource +from srs import SpatialReference, CoordTransform +from geometries import OGRGeometry +from geomtype import OGRGeomType +from error import check_err, OGRException, SRSException diff --git a/django/contrib/gis/gdal/DataSource.py b/django/contrib/gis/gdal/datasource.py similarity index 95% rename from django/contrib/gis/gdal/DataSource.py rename to django/contrib/gis/gdal/datasource.py index 5ad434348b..1776b34185 100644 --- a/django/contrib/gis/gdal/DataSource.py +++ b/django/contrib/gis/gdal/datasource.py @@ -4,9 +4,9 @@ from ctypes import c_char_p, c_int, c_void_p, byref, string_at # The GDAL C library, OGR exceptions, and the Layer object. from django.contrib.gis.gdal.libgdal import lgdal -from django.contrib.gis.gdal.OGRError import OGRException, check_err -from django.contrib.gis.gdal.Layer import Layer -from django.contrib.gis.gdal.Driver import Driver +from django.contrib.gis.gdal.error import OGRException, check_err +from django.contrib.gis.gdal.layer import Layer +from django.contrib.gis.gdal.driver import Driver """ DataSource is a wrapper for the OGR Data Source object, which provides @@ -52,11 +52,11 @@ from django.contrib.gis.gdal.Driver import Driver class DataSource(object): "Wraps an OGR Data Source object." - _ds = 0 # Initially NULL - #### Python 'magic' routines #### def __init__(self, ds_input, ds_driver=False): + self._ds = 0 # Initially NULL + # Registering all the drivers, this needs to be done # _before_ we try to open up a data source. if not lgdal.OGRGetDriverCount() and not lgdal.OGRRegisterAll(): diff --git a/django/contrib/gis/gdal/Driver.py b/django/contrib/gis/gdal/driver.py similarity index 96% rename from django/contrib/gis/gdal/Driver.py rename to django/contrib/gis/gdal/driver.py index 977dbe5358..404bf7facf 100644 --- a/django/contrib/gis/gdal/Driver.py +++ b/django/contrib/gis/gdal/driver.py @@ -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. from django.contrib.gis.gdal.libgdal import lgdal -from django.contrib.gis.gdal.OGRError import OGRException +from django.contrib.gis.gdal.error import OGRException # For more information, see the OGR C API source code: # http://www.gdal.org/ogr/ogr__api_8h.html @@ -14,8 +14,6 @@ from django.contrib.gis.gdal.OGRError import OGRException class Driver(object): "Wraps an OGR Data Source Driver." - _dr = 0 # Initially NULL - # Case-insensitive aliases for OGR Drivers. _alias = {'esri' : 'ESRI Shapefile', 'shp' : 'ESRI Shapefile', @@ -29,6 +27,7 @@ class Driver(object): if isinstance(input, StringType): # If a string name of the driver was passed in + self._dr = 0 # Initially NULL self._register() # Checking the alias dictionary (case-insensitive) to see if an alias diff --git a/django/contrib/gis/gdal/Envelope.py b/django/contrib/gis/gdal/envelope.py similarity index 98% rename from django/contrib/gis/gdal/Envelope.py rename to django/contrib/gis/gdal/envelope.py index 1a7ff80529..88d9895dbe 100644 --- a/django/contrib/gis/gdal/Envelope.py +++ b/django/contrib/gis/gdal/envelope.py @@ -106,7 +106,7 @@ class Envelope(object): def wkt(self): "Returns WKT representing a Polygon for this envelope." # TODO: Fix significant figures. - return 'POLYGON((%f %f,%f %f,%f %f,%f %f,%f %f))' % (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.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/django/contrib/gis/gdal/OGRError.py b/django/contrib/gis/gdal/error.py similarity index 100% rename from django/contrib/gis/gdal/OGRError.py rename to django/contrib/gis/gdal/error.py diff --git a/django/contrib/gis/gdal/Feature.py b/django/contrib/gis/gdal/feature.py similarity index 93% rename from django/contrib/gis/gdal/Feature.py rename to django/contrib/gis/gdal/feature.py index 1c37feac8a..e487565519 100644 --- a/django/contrib/gis/gdal/Feature.py +++ b/django/contrib/gis/gdal/feature.py @@ -4,9 +4,9 @@ from ctypes import c_char_p, c_int, string_at # The GDAL C library, OGR exception, and the Field object from django.contrib.gis.gdal.libgdal import lgdal -from django.contrib.gis.gdal.OGRError import OGRException -from django.contrib.gis.gdal.Field import Field -from django.contrib.gis.gdal.OGRGeometry import OGRGeometry, OGRGeomType +from django.contrib.gis.gdal.error import OGRException +from django.contrib.gis.gdal.field import Field +from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType # For more information, see the OGR C API source code: # http://www.gdal.org/ogr/ogr__api_8h.html @@ -15,11 +15,11 @@ from django.contrib.gis.gdal.OGRGeometry import OGRGeometry, OGRGeomType class Feature(object): "A class that wraps an OGR Feature, needs to be instantiated from a Layer object." - _feat = 0 # Initially NULL - #### Python 'magic' routines #### def __init__(self, f): "Needs a C pointer (Python integer in ctypes) in order to initialize." + self._feat = 0 # Initially NULL + self._fdefn = 0 if not f: raise OGRException, 'Cannot create OGR Feature, invalid pointer given.' self._feat = f diff --git a/django/contrib/gis/gdal/Field.py b/django/contrib/gis/gdal/field.py similarity index 97% rename from django/contrib/gis/gdal/Field.py rename to django/contrib/gis/gdal/field.py index 858d7512ff..338a886b03 100644 --- a/django/contrib/gis/gdal/Field.py +++ b/django/contrib/gis/gdal/field.py @@ -1,7 +1,7 @@ from ctypes import string_at from django.contrib.gis.gdal.libgdal import lgdal -from django.contrib.gis.gdal.OGRError import OGRException +from django.contrib.gis.gdal.error import OGRException # For more information, see the OGR C API source code: # http://www.gdal.org/ogr/ogr__api_8h.html diff --git a/django/contrib/gis/gdal/OGRGeometry.py b/django/contrib/gis/gdal/geometries.py similarity index 85% rename from django/contrib/gis/gdal/OGRGeometry.py rename to django/contrib/gis/gdal/geometries.py index 5a7b0b2480..355ba4580a 100644 --- a/django/contrib/gis/gdal/OGRGeometry.py +++ b/django/contrib/gis/gdal/geometries.py @@ -2,11 +2,12 @@ from types import IntType, StringType from ctypes import byref, string_at, c_char_p, c_double, c_int, c_void_p -# Getting the GDAL C library and error checking facilities +# 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.OGRError import check_err, OGRException -from django.contrib.gis.gdal.SpatialReference import SpatialReference, CoordTransform +from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope +from django.contrib.gis.gdal.error import check_err, OGRException +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 @@ -64,72 +65,6 @@ getx = pnt_func(lgdal.OGR_G_GetX) gety = pnt_func(lgdal.OGR_G_GetY) getz = pnt_func(lgdal.OGR_G_GetZ) -#### OGRGeomType #### -class OGRGeomType(object): - "Encapulates OGR Geometry Types." - - # Ordered array of acceptable strings and their corresponding OGRwkbGeometryType - __ogr_str = ['Point', 'LineString', 'Polygon', 'MultiPoint', - 'MultiLineString', 'MultiPolygon', 'GeometryCollection', - 'LinearRing'] - __ogr_int = [1, 2, 3, 4, 5, 6, 7, 101] - - def __init__(self, input): - "Figures out the correct OGR Type based upon the input." - if isinstance(input, OGRGeomType): - self._index = input._index - elif isinstance(input, StringType): - idx = self._has_str(self.__ogr_str, input) - if idx == None: - raise OGRException, 'Invalid OGR String Type "%s"' % input - self._index = idx - elif isinstance(input, int): - if not input in self.__ogr_int: - raise OGRException, 'Invalid OGR Integer Type: %d' % input - self._index = self.__ogr_int.index(input) - else: - raise TypeError, 'Invalid OGR Input type given!' - - def __str__(self): - "Returns a short-hand string form of the OGR Geometry type." - return self.__ogr_str[self._index] - - 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._index == other._index - elif isinstance(other, StringType): - idx = self._has_str(self.__ogr_str, other) - if not (idx == None): return self._index == idx - return False - elif isinstance(other, int): - if not other in self.__ogr_int: return False - return self.__ogr_int.index(other) == self._index - else: - raise TypeError, 'Cannot compare with type: %s' % str(type(other)) - - def _has_str(self, arr, s): - "Case-insensitive search of the string array for the given pattern." - s_low = s.lower() - for i in xrange(len(arr)): - if s_low == arr[i].lower(): return i - return None - - @property - def django(self): - "Returns the Django GeometryField for this OGR Type." - s = self.__ogr_str[self._index] - if s in ('Unknown', 'LinearRing'): - return None - else: - return s + 'Field' - - @property - def num(self): - "Returns the OGRwkbGeometryType number for the OGR Type." - return self.__ogr_int[self._index] - #### OGRGeometry Class #### class OGRGeometryIndexError(OGRException, KeyError): """This exception is raised when an invalid index is encountered, and has @@ -142,11 +77,11 @@ class OGRGeometryIndexError(OGRException, KeyError): class OGRGeometry(object): "Generally encapsulates an OGR geometry." - _g = 0 # Initially NULL - def __init__(self, input, srs=False): "Initializes Geometry on either WKT or an OGR pointer as input." + self._g = 0 # Initially NULL + if isinstance(input, StringType): # Getting the spatial reference self._init_srs(srs) @@ -181,6 +116,10 @@ class OGRGeometry(object): # 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._g: lgdal.OGR_G_DestroyGeometry(self._g) + def _init_srs(self, srs): # Getting the spatial if not isinstance(srs, SpatialReference): @@ -188,18 +127,35 @@ class OGRGeometry(object): else: self._s = srs.clone() # cloning the given spatial reference - def __add__(self, other): + ### Geometry set-like operations ### + # g = g1 | g2 + def __or__(self, other): "Returns the union of the two geometries." return self.union(other) - def __del__(self): - "Deletes this Geometry." - if self._g: lgdal.OGR_G_DestroyGeometry(self._g) + # 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?" return self.equals(other) + def __ne__(self, other): + "Tests for inequality." + return not self.equals(other) + def __str__(self): "WKT is used for the string representation." return self.wkt diff --git a/django/contrib/gis/gdal/geomtype.py b/django/contrib/gis/gdal/geomtype.py new file mode 100644 index 0000000000..1f2fb28c28 --- /dev/null +++ b/django/contrib/gis/gdal/geomtype.py @@ -0,0 +1,67 @@ +from types import StringType + +#### OGRGeomType #### +class OGRGeomType(object): + "Encapulates OGR Geometry Types." + + # Ordered array of acceptable strings and their corresponding OGRwkbGeometryType + __ogr_str = ['Point', 'LineString', 'Polygon', 'MultiPoint', + 'MultiLineString', 'MultiPolygon', 'GeometryCollection', + 'LinearRing'] + __ogr_int = [1, 2, 3, 4, 5, 6, 7, 101] + + def __init__(self, input): + "Figures out the correct OGR Type based upon the input." + if isinstance(input, OGRGeomType): + self._index = input._index + elif isinstance(input, StringType): + idx = self._has_str(self.__ogr_str, input) + if idx == None: + raise OGRException, 'Invalid OGR String Type "%s"' % input + self._index = idx + elif isinstance(input, int): + if not input in self.__ogr_int: + raise OGRException, 'Invalid OGR Integer Type: %d' % input + self._index = self.__ogr_int.index(input) + else: + raise TypeError, 'Invalid OGR Input type given!' + + def __str__(self): + "Returns a short-hand string form of the OGR Geometry type." + return self.__ogr_str[self._index] + + 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._index == other._index + elif isinstance(other, StringType): + idx = self._has_str(self.__ogr_str, other) + if not (idx == None): return self._index == idx + return False + elif isinstance(other, int): + if not other in self.__ogr_int: return False + return self.__ogr_int.index(other) == self._index + else: + raise TypeError, 'Cannot compare with type: %s' % str(type(other)) + + def _has_str(self, arr, s): + "Case-insensitive search of the string array for the given pattern." + s_low = s.lower() + for i in xrange(len(arr)): + if s_low == arr[i].lower(): return i + return None + + @property + def django(self): + "Returns the Django GeometryField for this OGR Type." + s = self.__ogr_str[self._index] + if s in ('Unknown', 'LinearRing'): + return None + else: + return s + 'Field' + + @property + def num(self): + "Returns the OGRwkbGeometryType number for the OGR Type." + return self.__ogr_int[self._index] diff --git a/django/contrib/gis/gdal/Layer.py b/django/contrib/gis/gdal/layer.py similarity index 89% rename from django/contrib/gis/gdal/Layer.py rename to django/contrib/gis/gdal/layer.py index 77bc9191d8..1d343ef363 100644 --- a/django/contrib/gis/gdal/Layer.py +++ b/django/contrib/gis/gdal/layer.py @@ -5,17 +5,18 @@ from ctypes import c_int, c_long, c_void_p, byref, string_at from django.contrib.gis.gdal.libgdal import lgdal # Other GDAL imports. -from django.contrib.gis.gdal.Envelope import Envelope, OGREnvelope -from django.contrib.gis.gdal.Feature import Feature -from django.contrib.gis.gdal.OGRGeometry import OGRGeomType -from django.contrib.gis.gdal.OGRError import OGRException, check_err -from django.contrib.gis.gdal.SpatialReference import SpatialReference +from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope +from django.contrib.gis.gdal.feature import Feature +from django.contrib.gis.gdal.geometries import OGRGeomType +from django.contrib.gis.gdal.error import OGRException, check_err +from django.contrib.gis.gdal.srs import SpatialReference # 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. +# function prototype for obtaining the spatial reference system get_srs = lgdal.OGR_L_GetSpatialRef get_srs.restype = c_void_p get_srs.argtypes = [c_void_p] @@ -23,11 +24,11 @@ get_srs.argtypes = [c_void_p] class Layer(object): "A class that wraps an OGR Layer, needs to be instantiated from a DataSource object." - _layer = 0 # Initially NULL - #### Python 'magic' routines #### def __init__(self, l): "Needs a C pointer (Python/ctypes integer) in order to initialize." + self._layer = 0 # Initially NULL + self._ldefn = 0 if not l: raise OGRException, 'Cannot create Layer, invalid pointer given' self._layer = l diff --git a/django/contrib/gis/gdal/libgdal.py b/django/contrib/gis/gdal/libgdal.py index 76cca40de9..e40f9138d1 100644 --- a/django/contrib/gis/gdal/libgdal.py +++ b/django/contrib/gis/gdal/libgdal.py @@ -1,6 +1,6 @@ import os, sys from ctypes import CDLL -from django.contrib.gis.gdal.OGRError import OGRException +from django.contrib.gis.gdal.error import OGRException if os.name == 'nt': # Windows NT shared library @@ -20,4 +20,4 @@ else: # This loads the GDAL/OGR C library lgdal = CDLL(lib_name) - + diff --git a/django/contrib/gis/gdal/SpatialReference.py b/django/contrib/gis/gdal/srs.py similarity index 97% rename from django/contrib/gis/gdal/SpatialReference.py rename to django/contrib/gis/gdal/srs.py index 54e338e854..d5639f1b0a 100644 --- a/django/contrib/gis/gdal/SpatialReference.py +++ b/django/contrib/gis/gdal/srs.py @@ -9,7 +9,7 @@ from ctypes import \ from django.contrib.gis.gdal.libgdal import lgdal # Getting the error checking routine and exceptions -from django.contrib.gis.gdal.OGRError import check_err, OGRException, SRSException +from django.contrib.gis.gdal.error import check_err, OGRException, SRSException """ The Spatial Reference class, represensents OGR Spatial Reference objects. @@ -71,8 +71,6 @@ class SpatialReference(object): the SpatialReference object 'provide[s] services to represent coordinate systems (projections and datums) and to transform between them.'""" - _srs = 0 # Initially NULL - # Well-Known Geographical Coordinate System Name _well_known = {'WGS84':4326, 'WGS72':4322, 'NAD27':4267, 'NAD83':4269} _epsg_regex = re.compile('^EPSG:(?P\d+)$', re.I) @@ -81,6 +79,8 @@ class SpatialReference(object): def __init__(self, input='', srs_type='wkt'): "Creates a spatial reference object from the given OGC Well Known Text (WKT)." + self._srs = 0 # Initially NULL + # Creating an initial empty string buffer. buf = c_char_p('') @@ -99,6 +99,7 @@ class SpatialReference(object): else: buf = c_char_p(input) elif isinstance(input, int): + if srs_type == 'wkt': srs_type = 'epsg' # want to try epsg if only integer provided if srs_type not in ('epsg', 'ogr'): raise SRSException, 'Integer input requires SRS type of "ogr" or "epsg".' else: @@ -317,10 +318,9 @@ class SpatialReference(object): class CoordTransform(object): "A coordinate system transformation object." - _ct = 0 # Initially NULL - def __init__(self, source, target): "Initializes on a source and target SpatialReference objects." + self._ct = 0 # Initially NULL if not isinstance(source, SpatialReference) or not isinstance(target, SpatialReference): raise SRSException, 'source and target must be of type SpatialReference' ct = lgdal.OCTNewCoordinateTransformation(source._srs, target._srs) diff --git a/django/contrib/gis/geos/base.py b/django/contrib/gis/geos/base.py index 10213a63c0..274d4c146b 100644 --- a/django/contrib/gis/geos/base.py +++ b/django/contrib/gis/geos/base.py @@ -281,8 +281,7 @@ class GEOSGeometry(object): return self._binary_predicate(lgeos.GEOSEqualsExact, other, tol) #### SRID Routines #### - @property - def srid(self): + def get_srid(self): "Gets the SRID for the geometry, returns None if no SRID is set." s = lgeos.GEOSGetSRID(self._ptr()) if s == 0: @@ -293,7 +292,8 @@ class GEOSGeometry(object): def set_srid(self, srid): "Sets the SRID for the geometry." lgeos.GEOSSetSRID(self._ptr(), c_int(srid)) - + srid = property(get_srid, set_srid) + #### Output Routines #### @property def wkt(self): diff --git a/django/contrib/gis/tests/test_gdal_ds.py b/django/contrib/gis/tests/test_gdal_ds.py index 19dc74534a..799442cf70 100644 --- a/django/contrib/gis/tests/test_gdal_ds.py +++ b/django/contrib/gis/tests/test_gdal_ds.py @@ -1,7 +1,7 @@ import os, os.path, unittest from django.contrib.gis.gdal import DataSource, OGRException -from django.contrib.gis.gdal.Envelope import Envelope -from django.contrib.gis.gdal.Field import OFTReal, OFTInteger, OFTString +from django.contrib.gis.gdal.envelope import Envelope +from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString # Path for SHP files shp_path = os.path.dirname(__file__)