mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Maintenance refactor of the GDAL (OGR) ctypes interface. Changes include:
* All C API method explictly called from their prototype module, no longer imported via *. * Applied DRY to C pointer management, classes that do so subclass from `GDALBase`. * `OGRGeometry`: Added `from_bbox` class method (patch from Christopher Schmidt) and `kml` property. * `SpatialReference`: Now initialize with `SetFromUserInput` (initialization is now more simple and flexible); removed duplicate methods. * `Envelope`: Added `expand_to_include` method and now allow same coordinates for lower left and upper right points. Thanks to Paul Smith for tickets and patches. * `OGRGeomType`: Now treat OGC 'Geometry' type as 'Unknown'. Fixed #9855, #10368, #10380. Refs #9806. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9985 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -1,4 +1,4 @@ | |||||||
| Copyright (c) 2007, Justin Bronn | Copyright (c) 2007-2009, Justin Bronn | ||||||
| All rights reserved. | All rights reserved. | ||||||
|  |  | ||||||
| Redistribution and use in source and binary forms, with or without modification, | Redistribution and use in source and binary forms, with or without modification, | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								django/contrib/gis/gdal/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								django/contrib/gis/gdal/base.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | from ctypes import c_void_p | ||||||
|  | from types import NoneType | ||||||
|  | from django.contrib.gis.gdal.error import GDALException | ||||||
|  |  | ||||||
|  | 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, int): | ||||||
|  |             self._ptr = self.ptr_type(ptr) | ||||||
|  |         elif isinstance(ptr, (self.ptr_type, NoneType)): | ||||||
|  |             self._ptr = ptr | ||||||
|  |         else: | ||||||
|  |             raise TypeError('Incompatible pointer type') | ||||||
|  |  | ||||||
|  |     ptr = property(_get_ptr, _set_ptr) | ||||||
|  |  | ||||||
| @@ -37,28 +37,23 @@ | |||||||
| from ctypes import byref, c_void_p | from ctypes import byref, c_void_p | ||||||
|  |  | ||||||
| # 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.base import GDALBase | ||||||
| from django.contrib.gis.gdal.driver import Driver | from django.contrib.gis.gdal.driver import Driver | ||||||
| from django.contrib.gis.gdal.error import OGRException, OGRIndexError | from django.contrib.gis.gdal.error import OGRException, OGRIndexError | ||||||
| from django.contrib.gis.gdal.layer import Layer | from django.contrib.gis.gdal.layer import Layer | ||||||
|  |  | ||||||
| # Getting the ctypes prototypes for the DataSource. | # Getting the ctypes prototypes for the DataSource. | ||||||
| from django.contrib.gis.gdal.prototypes.ds import \ | from django.contrib.gis.gdal.prototypes import ds as capi | ||||||
|     destroy_ds, get_driver_count, register_all, open_ds, release_ds, \ |  | ||||||
|     get_ds_name, get_layer, get_layer_count, get_layer_by_name |  | ||||||
|  |  | ||||||
| # 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 | ||||||
| # | # | ||||||
| # The OGR_DS_* routines are relevant here. | # The OGR_DS_* routines are relevant here. | ||||||
| class DataSource(object): | class DataSource(GDALBase): | ||||||
|     "Wraps an OGR Data Source object." |     "Wraps an OGR Data Source object." | ||||||
|  |  | ||||||
|     #### Python 'magic' routines #### |     #### Python 'magic' routines #### | ||||||
|     def __init__(self, ds_input, ds_driver=False, write=False): |     def __init__(self, ds_input, ds_driver=False, write=False): | ||||||
|  |  | ||||||
|         # DataSource pointer is initially NULL. |  | ||||||
|         self._ptr = None |  | ||||||
|  |  | ||||||
|         # The write flag. |         # The write flag. | ||||||
|         if write: |         if write: | ||||||
|             self._write = 1 |             self._write = 1 | ||||||
| @@ -67,33 +62,34 @@ 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 get_driver_count(): register_all() |         if not capi.get_driver_count(): | ||||||
|  |             capi.register_all() | ||||||
|  |  | ||||||
|         if isinstance(ds_input, basestring): |         if isinstance(ds_input, basestring): | ||||||
|             # The data source driver is a void pointer. |             # The data source driver is a void pointer. | ||||||
|             ds_driver = c_void_p() |             ds_driver = Driver.ptr_type() | ||||||
|             try: |             try: | ||||||
|                 # OGROpen will auto-detect the data source type. |                 # OGROpen will auto-detect the data source type. | ||||||
|                 ds = open_ds(ds_input, self._write, byref(ds_driver)) |                 ds = capi.open_ds(ds_input, self._write, byref(ds_driver)) | ||||||
|             except OGRException: |             except OGRException: | ||||||
|                 # Making the error message more clear rather than something |                 # Making the error message more clear rather than something | ||||||
|                 # like "Invalid pointer returned from OGROpen". |                 # like "Invalid pointer returned from OGROpen". | ||||||
|                 raise OGRException('Could not open the datasource at "%s"' % ds_input) |                 raise OGRException('Could not open the datasource at "%s"' % ds_input) | ||||||
|         elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p): |         elif isinstance(ds_input, self.ptr_type) and isinstance(ds_driver, Driver.ptr_type): | ||||||
|             ds = ds_input |             ds = ds_input | ||||||
|         else: |         else: | ||||||
|             raise OGRException('Invalid data source input type: %s' % type(ds_input)) |             raise OGRException('Invalid data source input type: %s' % type(ds_input)) | ||||||
|  |  | ||||||
|         if bool(ds): |         if bool(ds): | ||||||
|             self._ptr = ds |             self.ptr = ds | ||||||
|             self._driver = Driver(ds_driver) |             self.driver = Driver(ds_driver) | ||||||
|         else: |         else: | ||||||
|             # Raise an exception if the returned pointer is NULL  |             # Raise an exception if the returned pointer is NULL  | ||||||
|             raise OGRException('Invalid data source file "%s"' % ds_input) |             raise OGRException('Invalid data source file "%s"' % ds_input) | ||||||
|  |  | ||||||
|     def __del__(self): |     def __del__(self): | ||||||
|         "Destroys this DataStructure object." |         "Destroys this DataStructure object." | ||||||
|         if self._ptr: destroy_ds(self._ptr) |         if self._ptr: capi.destroy_ds(self._ptr) | ||||||
|  |  | ||||||
|     def __iter__(self): |     def __iter__(self): | ||||||
|         "Allows for iteration over the layers in a data source." |         "Allows for iteration over the layers in a data source." | ||||||
| @@ -103,12 +99,12 @@ class DataSource(object): | |||||||
|     def __getitem__(self, index): |     def __getitem__(self, index): | ||||||
|         "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, basestring): |         if isinstance(index, basestring): | ||||||
|             l = get_layer_by_name(self._ptr, index) |             l = capi.get_layer_by_name(self.ptr, index) | ||||||
|             if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index) |             if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index) | ||||||
|         elif isinstance(index, int): |         elif isinstance(index, int): | ||||||
|             if index < 0 or index >= self.layer_count: |             if index < 0 or index >= self.layer_count: | ||||||
|                 raise OGRIndexError('index out of range') |                 raise OGRIndexError('index out of range') | ||||||
|             l = get_layer(self._ptr, index) |             l = capi.get_layer(self._ptr, index) | ||||||
|         else: |         else: | ||||||
|             raise TypeError('Invalid index type: %s' % type(index)) |             raise TypeError('Invalid index type: %s' % type(index)) | ||||||
|         return Layer(l, self) |         return Layer(l, self) | ||||||
| @@ -121,18 +117,12 @@ class DataSource(object): | |||||||
|         "Returns OGR GetName and Driver for the Data Source." |         "Returns OGR GetName and Driver for the Data Source." | ||||||
|         return '%s (%s)' % (self.name, str(self.driver)) |         return '%s (%s)' % (self.name, str(self.driver)) | ||||||
|  |  | ||||||
|     #### DataSource Properties #### |  | ||||||
|     @property |  | ||||||
|     def driver(self): |  | ||||||
|         "Returns the Driver object for this Data Source." |  | ||||||
|         return self._driver |  | ||||||
|          |  | ||||||
|     @property |     @property | ||||||
|     def layer_count(self): |     def layer_count(self): | ||||||
|         "Returns the number of layers in the data source." |         "Returns the number of layers in the data source." | ||||||
|         return get_layer_count(self._ptr) |         return capi.get_layer_count(self._ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def name(self): |     def name(self): | ||||||
|         "Returns the name of the data source." |         "Returns the name of the data source." | ||||||
|         return get_ds_name(self._ptr) |         return capi.get_ds_name(self._ptr) | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| # prerequisites imports  | # prerequisites imports  | ||||||
| from ctypes import c_void_p | 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.error import OGRException | ||||||
| from django.contrib.gis.gdal.prototypes.ds import \ | from django.contrib.gis.gdal.prototypes import ds as capi | ||||||
|     get_driver, get_driver_by_name, get_driver_count, get_driver_name, register_all |  | ||||||
|  |  | ||||||
| # 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 | ||||||
| # | # | ||||||
| # The OGR_Dr_* routines are relevant here. | # The OGR_Dr_* routines are relevant here. | ||||||
| class Driver(object): | class Driver(GDALBase): | ||||||
|     "Wraps an OGR Data Source Driver." |     "Wraps an OGR Data Source Driver." | ||||||
|  |  | ||||||
|     # Case-insensitive aliases for OGR Drivers. |     # Case-insensitive aliases for OGR Drivers. | ||||||
| @@ -24,7 +24,6 @@ class Driver(object): | |||||||
|  |  | ||||||
|         if isinstance(dr_input, basestring): |         if isinstance(dr_input, basestring): | ||||||
|             # If a string name of the driver was passed in |             # If a string name of the driver was passed in | ||||||
|             self._ptr = None # Initially NULL |  | ||||||
|             self._register() |             self._register() | ||||||
|  |  | ||||||
|             # Checking the alias dictionary (case-insensitive) to see if an alias |             # Checking the alias dictionary (case-insensitive) to see if an alias | ||||||
| @@ -35,10 +34,10 @@ class Driver(object): | |||||||
|                 name = dr_input |                 name = dr_input | ||||||
|  |  | ||||||
|             # Attempting to get the OGR driver by the string name. |             # Attempting to get the OGR driver by the string name. | ||||||
|             dr = get_driver_by_name(name) |             dr = capi.get_driver_by_name(name) | ||||||
|         elif isinstance(dr_input, int): |         elif isinstance(dr_input, int): | ||||||
|             self._register() |             self._register() | ||||||
|             dr = get_driver(dr_input) |             dr = capi.get_driver(dr_input) | ||||||
|         elif isinstance(dr_input, c_void_p): |         elif isinstance(dr_input, c_void_p): | ||||||
|             dr = dr_input |             dr = dr_input | ||||||
|         else: |         else: | ||||||
| @@ -47,20 +46,20 @@ class Driver(object): | |||||||
|         # 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(dr_input)) |             raise OGRException('Could not initialize OGR Driver on input: %s' % str(dr_input)) | ||||||
|         self._ptr = dr |         self.ptr = dr | ||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         "Returns the string name of the OGR Driver." |         "Returns the string name of the OGR Driver." | ||||||
|         return get_driver_name(self._ptr) |         return capi.get_driver_name(self.ptr) | ||||||
|  |  | ||||||
|     def _register(self): |     def _register(self): | ||||||
|         "Attempts to register all the data source drivers." |         "Attempts to register all the data source drivers." | ||||||
|         # 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: register_all() |         if not self.driver_count: capi.register_all() | ||||||
|                      |                      | ||||||
|     # Driver properties |     # Driver properties | ||||||
|     @property |     @property | ||||||
|     def driver_count(self): |     def driver_count(self): | ||||||
|         "Returns the number of OGR data source drivers registered." |         "Returns the number of OGR data source drivers registered." | ||||||
|         return get_driver_count() |         return capi.get_driver_count() | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ | |||||||
|  Lower left (min_x, min_y) o----------+ |  Lower left (min_x, min_y) o----------+ | ||||||
| """ | """ | ||||||
| from ctypes import Structure, c_double | from ctypes import Structure, c_double | ||||||
| from types import TupleType, ListType |  | ||||||
| from django.contrib.gis.gdal.error import OGRException | 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. | ||||||
| @@ -42,7 +41,7 @@ class Envelope(object): | |||||||
|             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, ListType)): |             elif isinstance(args[0], (tuple, list)): | ||||||
|                 # A tuple was passed in. |                 # A tuple was passed in. | ||||||
|                 if len(args[0]) != 4: |                 if len(args[0]) != 4: | ||||||
|                     raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0])) |                     raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0])) | ||||||
| @@ -58,10 +57,10 @@ class Envelope(object): | |||||||
|             raise OGRException('Incorrect number (%d) of arguments.' % len(args)) |             raise OGRException('Incorrect number (%d) of arguments.' % len(args)) | ||||||
|  |  | ||||||
|         # Checking the x,y coordinates |         # Checking the x,y coordinates | ||||||
|         if self.min_x >= self.max_x: |         if self.min_x > self.max_x: | ||||||
|             raise OGRException('Envelope minimum X >= maximum X.') |             raise OGRException('Envelope minimum X > maximum X.') | ||||||
|         if self.min_y >= self.max_y: |         if self.min_y > self.max_y: | ||||||
|             raise OGRException('Envelope minimum Y >= maximum Y.') |             raise OGRException('Envelope minimum Y > maximum Y.') | ||||||
|  |  | ||||||
|     def __eq__(self, other): |     def __eq__(self, other): | ||||||
|         """ |         """ | ||||||
| @@ -71,7 +70,7 @@ class Envelope(object): | |||||||
|         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) | ||||||
|         elif isinstance(other, TupleType) and len(other) == 4: |         elif isinstance(other, tuple) and len(other) == 4: | ||||||
|             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: | ||||||
| @@ -89,6 +88,48 @@ class Envelope(object): | |||||||
|         self._envelope.MaxX = seq[2] |         self._envelope.MaxX = seq[2] | ||||||
|         self._envelope.MaxY = seq[3] |         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:  | ||||||
|  |             # Individiual parameters passed in.  | ||||||
|  |             return self.expand_to_include(args)  | ||||||
|  |         else:  | ||||||
|  |             raise OGRException('Incorrect number (%d) of arguments.' % len(args[0]))  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def min_x(self): |     def min_x(self): | ||||||
|         "Returns the value of the minimum X coordinate." |         "Returns the value of the minimum X coordinate." | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|  OGR methods. |  OGR methods. | ||||||
| """ | """ | ||||||
| #### OGR & SRS Exceptions #### | #### OGR & SRS Exceptions #### | ||||||
|  | class GDALException(Exception): pass | ||||||
| class OGRException(Exception): pass | class OGRException(Exception): pass | ||||||
| class SRSException(Exception): pass | class SRSException(Exception): pass | ||||||
| class OGRIndexError(OGRException, KeyError): | class OGRIndexError(OGRException, KeyError): | ||||||
|   | |||||||
| @@ -1,36 +1,31 @@ | |||||||
| # The GDAL C library, OGR exception, and the Field object | # 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.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 | from django.contrib.gis.gdal.srs import SpatialReference | ||||||
|  |  | ||||||
| # ctypes function prototypes | # ctypes function prototypes | ||||||
| from django.contrib.gis.gdal.prototypes.ds import \ | from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api | ||||||
|     destroy_feature, feature_equal, get_fd_geom_type, get_feat_geom_ref, \ |  | ||||||
|     get_feat_name, get_feat_field_count, get_fid, get_field_defn, \ |  | ||||||
|     get_field_index, get_field_name |  | ||||||
| from django.contrib.gis.gdal.prototypes.geom import clone_geom, get_geom_srs |  | ||||||
| from django.contrib.gis.gdal.prototypes.srs import clone_srs |  | ||||||
|  |  | ||||||
| # 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 | ||||||
| # | # | ||||||
| # The OGR_F_* routines are relevant here. | # The OGR_F_* routines are relevant here. | ||||||
| class Feature(object): | class Feature(GDALBase): | ||||||
|     "A class that wraps an OGR Feature, needs to be instantiated from a Layer object." |     "A class that wraps an OGR Feature, needs to be instantiated from a Layer object." | ||||||
|  |  | ||||||
|     #### Python 'magic' routines #### |     #### Python 'magic' routines #### | ||||||
|     def __init__(self, feat, fdefn): |     def __init__(self, feat, fdefn): | ||||||
|         "Initializes on the pointers for the feature and the layer definition." |         "Initializes on the pointers for the feature and the layer definition." | ||||||
|         self._ptr = None # Initially NULL |  | ||||||
|         if not feat or not fdefn: |         if not feat or not fdefn: | ||||||
|             raise OGRException('Cannot create OGR Feature, invalid pointer given.') |             raise OGRException('Cannot create OGR Feature, invalid pointer given.') | ||||||
|         self._ptr = feat |         self.ptr = feat | ||||||
|         self._fdefn = fdefn |         self._fdefn = fdefn | ||||||
|  |  | ||||||
|     def __del__(self): |     def __del__(self): | ||||||
|         "Releases a reference to this object." |         "Releases a reference to this object." | ||||||
|         if self._ptr: destroy_feature(self._ptr) |         if self._ptr: capi.destroy_feature(self._ptr) | ||||||
|  |  | ||||||
|     def __getitem__(self, index): |     def __getitem__(self, index): | ||||||
|         """ |         """ | ||||||
| @@ -45,7 +40,7 @@ class Feature(object): | |||||||
|             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(self._ptr, i) |         return Field(self.ptr, i) | ||||||
|      |      | ||||||
|     def __iter__(self): |     def __iter__(self): | ||||||
|         "Iterates over each field in the Feature." |         "Iterates over each field in the Feature." | ||||||
| @@ -62,41 +57,41 @@ class Feature(object): | |||||||
|  |  | ||||||
|     def __eq__(self, other): |     def __eq__(self, other): | ||||||
|         "Does equivalence testing on the features." |         "Does equivalence testing on the features." | ||||||
|         return bool(feature_equal(self._ptr, other._ptr)) |         return bool(capi.feature_equal(self.ptr, other._ptr)) | ||||||
|  |  | ||||||
|     #### Feature Properties #### |     #### Feature Properties #### | ||||||
|     @property |     @property | ||||||
|     def fid(self): |     def fid(self): | ||||||
|         "Returns the feature identifier." |         "Returns the feature identifier." | ||||||
|         return get_fid(self._ptr) |         return capi.get_fid(self.ptr) | ||||||
|          |          | ||||||
|     @property |     @property | ||||||
|     def layer_name(self): |     def layer_name(self): | ||||||
|         "Returns the name of the layer for the feature." |         "Returns the name of the layer for the feature." | ||||||
|         return get_feat_name(self._fdefn) |         return capi.get_feat_name(self._fdefn) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def num_fields(self): |     def num_fields(self): | ||||||
|         "Returns the number of fields in the Feature." |         "Returns the number of fields in the Feature." | ||||||
|         return get_feat_field_count(self._ptr) |         return capi.get_feat_field_count(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def fields(self): |     def fields(self): | ||||||
|         "Returns a list of fields in the Feature." |         "Returns a list of fields in the Feature." | ||||||
|         return [get_field_name(get_field_defn(self._fdefn, i))  |         return [capi.get_field_name(capi.get_field_defn(self._fdefn, i))  | ||||||
|                 for i in xrange(self.num_fields)] |                 for i in xrange(self.num_fields)] | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def geom(self): |     def geom(self): | ||||||
|         "Returns the OGR Geometry for this Feature." |         "Returns the OGR Geometry for this Feature." | ||||||
|         # Retrieving the geometry pointer for the feature. |         # Retrieving the geometry pointer for the feature. | ||||||
|         geom_ptr = get_feat_geom_ref(self._ptr) |         geom_ptr = capi.get_feat_geom_ref(self.ptr) | ||||||
|         return OGRGeometry(clone_geom(geom_ptr)) |         return OGRGeometry(geom_api.clone_geom(geom_ptr)) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def geom_type(self): |     def geom_type(self): | ||||||
|         "Returns the OGR Geometry Type for this Feture." |         "Returns the OGR Geometry Type for this Feture." | ||||||
|         return OGRGeomType(get_fd_geom_type(self._fdefn)) |         return OGRGeomType(capi.get_fd_geom_type(self._fdefn)) | ||||||
|      |      | ||||||
|     #### Feature Methods #### |     #### Feature Methods #### | ||||||
|     def get(self, field): |     def get(self, field): | ||||||
| @@ -110,6 +105,6 @@ 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 = get_field_index(self._ptr, field_name) |         i = capi.get_field_index(self.ptr, 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 | ||||||
|   | |||||||
| @@ -1,16 +1,14 @@ | |||||||
| from ctypes import byref, c_int | from ctypes import byref, c_int | ||||||
| from datetime import date, datetime, time | 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.error import OGRException | ||||||
| from django.contrib.gis.gdal.prototypes.ds import \ | from django.contrib.gis.gdal.prototypes import ds as capi | ||||||
|     get_feat_field_defn, get_field_as_datetime, get_field_as_double, \ |  | ||||||
|     get_field_as_integer, get_field_as_string, get_field_name, get_field_precision, \ |  | ||||||
|     get_field_type, get_field_type_name, get_field_width |  | ||||||
|  |  | ||||||
| # 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 | ||||||
| # | # | ||||||
| # The OGR_Fld_* routines are relevant here. | # The OGR_Fld_* routines are relevant here. | ||||||
| class Field(object): | class Field(GDALBase): | ||||||
|     "A class that wraps an OGR Field, needs to be instantiated from a Feature object." |     "A class that wraps an OGR Field, needs to be instantiated from a Feature object." | ||||||
|  |  | ||||||
|     #### Python 'magic' routines #### |     #### Python 'magic' routines #### | ||||||
| @@ -24,13 +22,13 @@ class Field(object): | |||||||
|         self._index = index |         self._index = index | ||||||
|          |          | ||||||
|         # Getting the pointer for this field. |         # Getting the pointer for this field. | ||||||
|         fld = get_feat_field_defn(feat, index) |         fld_ptr = capi.get_feat_field_defn(feat, index) | ||||||
|         if not fld: |         if not fld_ptr: | ||||||
|             raise OGRException('Cannot create OGR Field, invalid pointer given.') |             raise OGRException('Cannot create OGR Field, invalid pointer given.') | ||||||
|         self._ptr = fld |         self.ptr = fld_ptr | ||||||
|  |  | ||||||
|         # Setting the class depending upon the OGR Field Type (OFT) |         # Setting the class depending upon the OGR Field Type (OFT) | ||||||
|         self.__class__ = FIELD_CLASSES[self.type] |         self.__class__ = OGRFieldTypes[self.type] | ||||||
|  |  | ||||||
|         # OFTReal with no precision should be an OFTInteger. |         # OFTReal with no precision should be an OFTInteger. | ||||||
|         if isinstance(self, OFTReal) and self.precision == 0: |         if isinstance(self, OFTReal) and self.precision == 0: | ||||||
| @@ -43,21 +41,21 @@ class Field(object): | |||||||
|     #### Field Methods #### |     #### Field Methods #### | ||||||
|     def as_double(self): |     def as_double(self): | ||||||
|         "Retrieves the Field's value as a double (float)." |         "Retrieves the Field's value as a double (float)." | ||||||
|         return get_field_as_double(self._feat, self._index) |         return capi.get_field_as_double(self._feat, self._index) | ||||||
|  |  | ||||||
|     def as_int(self): |     def as_int(self): | ||||||
|         "Retrieves the Field's value as an integer." |         "Retrieves the Field's value as an integer." | ||||||
|         return get_field_as_integer(self._feat, self._index) |         return capi.get_field_as_integer(self._feat, self._index) | ||||||
|  |  | ||||||
|     def as_string(self): |     def as_string(self): | ||||||
|         "Retrieves the Field's value as a string." |         "Retrieves the Field's value as a string." | ||||||
|         return get_field_as_string(self._feat, self._index) |         return capi.get_field_as_string(self._feat, self._index) | ||||||
|  |  | ||||||
|     def as_datetime(self): |     def as_datetime(self): | ||||||
|         "Retrieves the Field's value as a tuple of date & time components." |         "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)] |         yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)] | ||||||
|         status = get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd), |         status = capi.get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd), | ||||||
|                                        byref(hh), byref(mn), byref(ss), byref(tz)) |                                             byref(hh), byref(mn), byref(ss), byref(tz)) | ||||||
|         if status: |         if status: | ||||||
|             return (yy, mm, dd, hh, mn, ss, tz) |             return (yy, mm, dd, hh, mn, ss, tz) | ||||||
|         else: |         else: | ||||||
| @@ -67,22 +65,22 @@ class Field(object): | |||||||
|     @property |     @property | ||||||
|     def name(self): |     def name(self): | ||||||
|         "Returns the name of this Field." |         "Returns the name of this Field." | ||||||
|         return get_field_name(self._ptr) |         return capi.get_field_name(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def precision(self): |     def precision(self): | ||||||
|         "Returns the precision of this Field." |         "Returns the precision of this Field." | ||||||
|         return get_field_precision(self._ptr) |         return capi.get_field_precision(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def type(self): |     def type(self): | ||||||
|         "Returns the OGR type of this Field." |         "Returns the OGR type of this Field." | ||||||
|         return get_field_type(self._ptr) |         return capi.get_field_type(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def type_name(self): |     def type_name(self): | ||||||
|         "Return the OGR field type name for this Field." |         "Return the OGR field type name for this Field." | ||||||
|         return get_field_type_name(self.type) |         return capi.get_field_type_name(self.type) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def value(self): |     def value(self): | ||||||
| @@ -93,7 +91,7 @@ class Field(object): | |||||||
|     @property |     @property | ||||||
|     def width(self): |     def width(self): | ||||||
|         "Returns the width of this Field." |         "Returns the width of this Field." | ||||||
|         return get_field_width(self._ptr) |         return capi.get_field_width(self.ptr) | ||||||
|  |  | ||||||
| ### The Field sub-classes for each OGR Field type. ### | ### The Field sub-classes for each OGR Field type. ### | ||||||
| class OFTInteger(Field): | class OFTInteger(Field): | ||||||
| @@ -163,8 +161,8 @@ class OFTRealList(Field): pass | |||||||
| class OFTStringList(Field): pass | class OFTStringList(Field): pass | ||||||
| class OFTWideStringList(Field): pass | class OFTWideStringList(Field): pass | ||||||
|  |  | ||||||
| # Class mapping dictionary for OFT Types | # Class mapping dictionary for OFT Types and reverse mapping. | ||||||
| FIELD_CLASSES = { 0 : OFTInteger, | OGRFieldTypes = { 0 : OFTInteger, | ||||||
|                   1 : OFTIntegerList, |                   1 : OFTIntegerList, | ||||||
|                   2 : OFTReal, |                   2 : OFTReal, | ||||||
|                   3 : OFTRealList, |                   3 : OFTRealList, | ||||||
| @@ -177,3 +175,4 @@ FIELD_CLASSES = { 0 : OFTInteger, | |||||||
|                  10 : OFTTime, |                  10 : OFTTime, | ||||||
|                  11 : OFTDateTime, |                  11 : OFTDateTime, | ||||||
|                   } |                   } | ||||||
|  | ROGRFieldTypes = dict([(cls, num) for num, cls in OGRFieldTypes.items()]) | ||||||
|   | |||||||
| @@ -44,14 +44,15 @@ from binascii import a2b_hex | |||||||
| from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p | from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p | ||||||
|  |  | ||||||
| # Getting GDAL prerequisites | # 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.envelope import Envelope, OGREnvelope | ||||||
| from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException | from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException | ||||||
| from django.contrib.gis.gdal.geomtype import OGRGeomType | from django.contrib.gis.gdal.geomtype import OGRGeomType | ||||||
| from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform | from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform | ||||||
|  |  | ||||||
| # Getting the ctypes prototype functions that interface w/the GDAL C library. | # Getting the ctypes prototype functions that interface w/the GDAL C library. | ||||||
| from django.contrib.gis.gdal.prototypes.geom import * | from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api | ||||||
| from django.contrib.gis.gdal.prototypes.srs import clone_srs | GEOJSON = capi.GEOJSON | ||||||
|  |  | ||||||
| # 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 | ||||||
| @@ -64,13 +65,12 @@ wkt_regex = re.compile(r'^(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOIN | |||||||
| json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$') | json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$') | ||||||
|  |  | ||||||
| #### OGRGeometry Class #### | #### OGRGeometry Class #### | ||||||
| class OGRGeometry(object): | class OGRGeometry(GDALBase): | ||||||
|     "Generally encapsulates an OGR geometry." |     "Generally encapsulates an OGR geometry." | ||||||
|  |  | ||||||
|     def __init__(self, geom_input, srs=None): |     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._ptr = c_void_p(None) # Initially NULL |  | ||||||
|         str_instance = isinstance(geom_input, basestring) |         str_instance = isinstance(geom_input, basestring) | ||||||
|  |  | ||||||
|         # If HEX, unpack input to to a binary buffer. |         # If HEX, unpack input to to a binary buffer. | ||||||
| @@ -91,27 +91,27 @@ class OGRGeometry(object): | |||||||
|                 if wkt_m.group('type').upper() == 'LINEARRING': |                 if wkt_m.group('type').upper() == 'LINEARRING': | ||||||
|                     # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT. |                     # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT. | ||||||
|                     #  See http://trac.osgeo.org/gdal/ticket/1992. |                     #  See http://trac.osgeo.org/gdal/ticket/1992. | ||||||
|                     g = create_geom(OGRGeomType(wkt_m.group('type')).num) |                     g = capi.create_geom(OGRGeomType(wkt_m.group('type')).num) | ||||||
|                     import_wkt(g, byref(c_char_p(geom_input))) |                     capi.import_wkt(g, byref(c_char_p(geom_input))) | ||||||
|                 else: |                 else: | ||||||
|                     g = from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p())) |                     g = capi.from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p())) | ||||||
|             elif json_m: |             elif json_m: | ||||||
|                 if GEOJSON: |                 if GEOJSON: | ||||||
|                     g = from_json(geom_input) |                     g = capi.from_json(geom_input) | ||||||
|                 else: |                 else: | ||||||
|                     raise NotImplementedError('GeoJSON input only supported on GDAL 1.5+.') |                     raise NotImplementedError('GeoJSON input only supported on GDAL 1.5+.') | ||||||
|             else: |             else: | ||||||
|                 # Seeing if the input is a valid short-hand string |                 # Seeing if the input is a valid short-hand string | ||||||
|                 # (e.g., 'Point', 'POLYGON'). |                 # (e.g., 'Point', 'POLYGON'). | ||||||
|                 ogr_t = OGRGeomType(geom_input) |                 ogr_t = OGRGeomType(geom_input) | ||||||
|                 g = create_geom(OGRGeomType(geom_input).num) |                 g = capi.create_geom(OGRGeomType(geom_input).num) | ||||||
|         elif isinstance(geom_input, buffer): |         elif isinstance(geom_input, buffer): | ||||||
|             # WKB was passed in |             # WKB was passed in | ||||||
|             g = from_wkb(str(geom_input), None, byref(c_void_p()), len(geom_input)) |             g = capi.from_wkb(str(geom_input), None, byref(c_void_p()), len(geom_input)) | ||||||
|         elif isinstance(geom_input, OGRGeomType): |         elif isinstance(geom_input, OGRGeomType): | ||||||
|             # OGRGeomType was passed in, an empty geometry will be created. |             # OGRGeomType was passed in, an empty geometry will be created. | ||||||
|             g = create_geom(geom_input.num) |             g = capi.create_geom(geom_input.num) | ||||||
|         elif isinstance(geom_input, c_void_p): |         elif isinstance(geom_input, self.ptr_type): | ||||||
|             # OGR pointer (c_void_p) was the input. |             # OGR pointer (c_void_p) was the input. | ||||||
|             g = geom_input |             g = geom_input | ||||||
|         else: |         else: | ||||||
| @@ -121,7 +121,7 @@ class OGRGeometry(object): | |||||||
|         # by setting the pointer for the object. |         # by setting the pointer for the object. | ||||||
|         if not g: |         if not g: | ||||||
|             raise OGRException('Cannot create OGR Geometry from input: %s' % str(geom_input)) |             raise OGRException('Cannot create OGR Geometry from input: %s' % str(geom_input)) | ||||||
|         self._ptr = g |         self.ptr = g | ||||||
|  |  | ||||||
|         # Assigning the SpatialReference object to the geometry, if valid. |         # Assigning the SpatialReference object to the geometry, if valid. | ||||||
|         if bool(srs): self.srs = srs |         if bool(srs): self.srs = srs | ||||||
| @@ -129,9 +129,16 @@ class OGRGeometry(object): | |||||||
|         # Setting the class depending upon the OGR Geometry Type |         # Setting the class depending upon the OGR Geometry Type | ||||||
|         self.__class__ = GEO_CLASSES[self.geom_type.num] |         self.__class__ = GEO_CLASSES[self.geom_type.num] | ||||||
|  |  | ||||||
|  |     @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) ) | ||||||
|  |   | ||||||
|     def __del__(self): |     def __del__(self): | ||||||
|         "Deletes this Geometry." |         "Deletes this Geometry." | ||||||
|         if self._ptr: destroy_geom(self._ptr) |         if self._ptr: capi.destroy_geom(self._ptr) | ||||||
|  |  | ||||||
|     ### Geometry set-like operations ### |     ### Geometry set-like operations ### | ||||||
|     # g = g1 | g2 |     # g = g1 | g2 | ||||||
| @@ -170,22 +177,22 @@ class OGRGeometry(object): | |||||||
|     @property |     @property | ||||||
|     def dimension(self): |     def dimension(self): | ||||||
|         "Returns 0 for points, 1 for lines, and 2 for surfaces." |         "Returns 0 for points, 1 for lines, and 2 for surfaces." | ||||||
|         return get_dims(self._ptr) |         return capi.get_dims(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def coord_dim(self): |     def coord_dim(self): | ||||||
|         "Returns the coordinate dimension of the Geometry." |         "Returns the coordinate dimension of the Geometry." | ||||||
|         return get_coord_dims(self._ptr) |         return capi.get_coord_dims(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def geom_count(self): |     def geom_count(self): | ||||||
|         "The number of elements in this Geometry." |         "The number of elements in this Geometry." | ||||||
|         return get_geom_count(self._ptr) |         return capi.get_geom_count(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def point_count(self): |     def point_count(self): | ||||||
|         "Returns the number of Points in this Geometry." |         "Returns the number of Points in this Geometry." | ||||||
|         return get_point_count(self._ptr) |         return capi.get_point_count(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def num_points(self): |     def num_points(self): | ||||||
| @@ -201,28 +208,28 @@ class OGRGeometry(object): | |||||||
|     def geom_type(self): |     def geom_type(self): | ||||||
|         "Returns the Type for this Geometry." |         "Returns the Type for this Geometry." | ||||||
|         try: |         try: | ||||||
|             return OGRGeomType(get_geom_type(self._ptr)) |             return OGRGeomType(capi.get_geom_type(self.ptr)) | ||||||
|         except OGRException: |         except OGRException: | ||||||
|             # VRT datasources return an invalid geometry type |             # VRT datasources return an invalid geometry type | ||||||
|             # number, but a valid name -- we'll try that instead. |             # number, but a valid name -- we'll try that instead. | ||||||
|             # See: http://trac.osgeo.org/gdal/ticket/2491 |             # See: http://trac.osgeo.org/gdal/ticket/2491 | ||||||
|             return OGRGeomType(get_geom_name(self._ptr)) |             return OGRGeomType(capi.get_geom_name(self.ptr)) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def geom_name(self): |     def geom_name(self): | ||||||
|         "Returns the Name of this Geometry." |         "Returns the Name of this Geometry." | ||||||
|         return get_geom_name(self._ptr) |         return capi.get_geom_name(self.ptr) | ||||||
|  |  | ||||||
|     @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." | ||||||
|         return get_area(self._ptr) |         return capi.get_area(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def envelope(self): |     def envelope(self): | ||||||
|         "Returns the envelope for this Geometry." |         "Returns the envelope for this Geometry." | ||||||
|         # TODO: Fix Envelope() for Point geometries. |         # TODO: Fix Envelope() for Point geometries. | ||||||
|         return Envelope(get_envelope(self._ptr, byref(OGREnvelope()))) |         return Envelope(capi.get_envelope(self.ptr, byref(OGREnvelope()))) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def extent(self): |     def extent(self): | ||||||
| @@ -232,39 +239,40 @@ class OGRGeometry(object): | |||||||
|     #### SpatialReference-related Properties #### |     #### SpatialReference-related Properties #### | ||||||
|      |      | ||||||
|     # The SRS property |     # The SRS property | ||||||
|     def get_srs(self): |     def _get_srs(self): | ||||||
|         "Returns the Spatial Reference for this Geometry." |         "Returns the Spatial Reference for this Geometry." | ||||||
|         try: |         try: | ||||||
|             srs_ptr = get_geom_srs(self._ptr) |             srs_ptr = capi.get_geom_srs(self.ptr) | ||||||
|             return SpatialReference(clone_srs(srs_ptr)) |             return SpatialReference(srs_api.clone_srs(srs_ptr)) | ||||||
|         except SRSException: |         except SRSException: | ||||||
|             return None |             return None | ||||||
|  |  | ||||||
|     def set_srs(self, srs): |     def _set_srs(self, srs): | ||||||
|         "Sets the SpatialReference for this geometry." |         "Sets the SpatialReference for this geometry." | ||||||
|         if isinstance(srs, SpatialReference): |         if isinstance(srs, SpatialReference): | ||||||
|             srs_ptr = clone_srs(srs._ptr) |             srs_ptr = srs_api.clone_srs(srs.ptr) | ||||||
|         elif isinstance(srs, (int, long, basestring)): |         elif isinstance(srs, (int, long, basestring)): | ||||||
|             sr = SpatialReference(srs) |             sr = SpatialReference(srs) | ||||||
|             srs_ptr = clone_srs(sr._ptr) |             srs_ptr = srs_api.clone_srs(sr.ptr) | ||||||
|         else: |         else: | ||||||
|             raise TypeError('Cannot assign spatial reference with object of type: %s' % type(srs)) |             raise TypeError('Cannot assign spatial reference with object of type: %s' % type(srs)) | ||||||
|         assign_srs(self._ptr, srs_ptr) |         capi.assign_srs(self.ptr, srs_ptr) | ||||||
|  |  | ||||||
|     srs = property(get_srs, set_srs) |     srs = property(_get_srs, _set_srs) | ||||||
|  |  | ||||||
|     # The SRID property |     # The SRID property | ||||||
|     def get_srid(self): |     def _get_srid(self): | ||||||
|         if self.srs: return self.srs.srid |         srs = self.srs | ||||||
|         else: return None |         if srs: return srs.srid | ||||||
|  |         return None | ||||||
|  |  | ||||||
|     def set_srid(self, srid): |     def _set_srid(self, srid): | ||||||
|         if isinstance(srid, (int, long)): |         if isinstance(srid, (int, long)): | ||||||
|             self.srs = srid |             self.srs = srid | ||||||
|         else: |         else: | ||||||
|             raise TypeError('SRID must be set with an integer.') |             raise TypeError('SRID must be set with an integer.') | ||||||
|  |  | ||||||
|     srid = property(get_srid, set_srid) |     srid = property(_get_srid, _set_srid) | ||||||
|  |  | ||||||
|     #### Output Methods #### |     #### Output Methods #### | ||||||
|     @property |     @property | ||||||
| @@ -276,7 +284,7 @@ class OGRGeometry(object): | |||||||
|     @property |     @property | ||||||
|     def gml(self): |     def gml(self): | ||||||
|         "Returns the GML representation of the Geometry." |         "Returns the GML representation of the Geometry." | ||||||
|         return to_gml(self._ptr) |         return capi.to_gml(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def hex(self): |     def hex(self): | ||||||
| @@ -286,16 +294,28 @@ class OGRGeometry(object): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def json(self): |     def json(self): | ||||||
|  |         """ | ||||||
|  |         Returns the GeoJSON representation of this Geometry (requires | ||||||
|  |         GDAL 1.5+). | ||||||
|  |         """ | ||||||
|         if GEOJSON:  |         if GEOJSON:  | ||||||
|             return to_json(self._ptr) |             return capi.to_json(self.ptr) | ||||||
|         else: |         else: | ||||||
|             raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.') |             raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.') | ||||||
|     geojson = json |     geojson = json | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def kml(self): | ||||||
|  |         "Returns the KML representation of the Geometry." | ||||||
|  |         if GEOJSON: | ||||||
|  |             return capi.to_kml(self.ptr, None) | ||||||
|  |         else: | ||||||
|  |             raise NotImplementedError('KML output only supported on GDAL 1.5+.') | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def wkb_size(self): |     def wkb_size(self): | ||||||
|         "Returns the size of the WKB buffer." |         "Returns the size of the WKB buffer." | ||||||
|         return get_wkbsize(self._ptr) |         return capi.get_wkbsize(self.ptr) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def wkb(self): |     def wkb(self): | ||||||
| @@ -307,19 +327,19 @@ class OGRGeometry(object): | |||||||
|         sz = self.wkb_size |         sz = self.wkb_size | ||||||
|         # Creating the unsigned character buffer, and passing it in by reference. |         # Creating the unsigned character buffer, and passing it in by reference. | ||||||
|         buf = (c_ubyte * sz)() |         buf = (c_ubyte * sz)() | ||||||
|         wkb = to_wkb(self._ptr, byteorder, byref(buf)) |         wkb = capi.to_wkb(self.ptr, byteorder, byref(buf)) | ||||||
|         # Returning a buffer of the string at the pointer. |         # Returning a buffer of the string at the pointer. | ||||||
|         return buffer(string_at(buf, sz)) |         return buffer(string_at(buf, sz)) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def wkt(self): |     def wkt(self): | ||||||
|         "Returns the WKT representation of the Geometry." |         "Returns the WKT representation of the Geometry." | ||||||
|         return to_wkt(self._ptr, byref(c_char_p())) |         return capi.to_wkt(self.ptr, byref(c_char_p())) | ||||||
|      |      | ||||||
|     #### Geometry Methods #### |     #### Geometry Methods #### | ||||||
|     def clone(self): |     def clone(self): | ||||||
|         "Clones this OGR Geometry." |         "Clones this OGR Geometry." | ||||||
|         return OGRGeometry(clone_geom(self._ptr), self.srs) |         return OGRGeometry(capi.clone_geom(self.ptr), self.srs) | ||||||
|  |  | ||||||
|     def close_rings(self): |     def close_rings(self): | ||||||
|         """ |         """ | ||||||
| @@ -328,7 +348,7 @@ class OGRGeometry(object): | |||||||
|         end. |         end. | ||||||
|         """ |         """ | ||||||
|         # Closing the open rings. |         # Closing the open rings. | ||||||
|         geom_close_rings(self._ptr) |         capi.geom_close_rings(self.ptr) | ||||||
|  |  | ||||||
|     def transform(self, coord_trans, clone=False): |     def transform(self, coord_trans, clone=False): | ||||||
|         """ |         """ | ||||||
| @@ -344,12 +364,12 @@ class OGRGeometry(object): | |||||||
|             klone.transform(coord_trans) |             klone.transform(coord_trans) | ||||||
|             return klone |             return klone | ||||||
|         if isinstance(coord_trans, CoordTransform): |         if isinstance(coord_trans, CoordTransform): | ||||||
|             geom_transform(self._ptr, coord_trans._ptr) |             capi.geom_transform(self.ptr, coord_trans.ptr) | ||||||
|         elif isinstance(coord_trans, SpatialReference): |         elif isinstance(coord_trans, SpatialReference): | ||||||
|             geom_transform_to(self._ptr, coord_trans._ptr) |             capi.geom_transform_to(self.ptr, coord_trans.ptr) | ||||||
|         elif isinstance(coord_trans, (int, long, basestring)): |         elif isinstance(coord_trans, (int, long, basestring)): | ||||||
|             sr = SpatialReference(coord_trans) |             sr = SpatialReference(coord_trans) | ||||||
|             geom_transform_to(self._ptr, sr._ptr) |             capi.geom_transform_to(self.ptr, sr.ptr) | ||||||
|         else: |         else: | ||||||
|             raise TypeError('Transform only accepts CoordTransform, SpatialReference, string, and integer objects.') |             raise TypeError('Transform only accepts CoordTransform, SpatialReference, string, and integer objects.') | ||||||
|  |  | ||||||
| @@ -366,52 +386,52 @@ class OGRGeometry(object): | |||||||
|  |  | ||||||
|         # Returning the output of the given function with the other geometry's |         # Returning the output of the given function with the other geometry's | ||||||
|         # pointer. |         # pointer. | ||||||
|         return func(self._ptr, other._ptr) |         return func(self.ptr, other.ptr) | ||||||
|  |  | ||||||
|     def intersects(self, other): |     def intersects(self, other): | ||||||
|         "Returns True if this geometry intersects with the other." |         "Returns True if this geometry intersects with the other." | ||||||
|         return self._topology(ogr_intersects, other) |         return self._topology(capi.ogr_intersects, other) | ||||||
|      |      | ||||||
|     def equals(self, other): |     def equals(self, other): | ||||||
|         "Returns True if this geometry is equivalent to the other." |         "Returns True if this geometry is equivalent to the other." | ||||||
|         return self._topology(ogr_equals, other) |         return self._topology(capi.ogr_equals, other) | ||||||
|  |  | ||||||
|     def disjoint(self, other): |     def disjoint(self, other): | ||||||
|         "Returns True if this geometry and the other are spatially disjoint." |         "Returns True if this geometry and the other are spatially disjoint." | ||||||
|         return self._topology(ogr_disjoint, other) |         return self._topology(capi.ogr_disjoint, other) | ||||||
|  |  | ||||||
|     def touches(self, other): |     def touches(self, other): | ||||||
|         "Returns True if this geometry touches the other." |         "Returns True if this geometry touches the other." | ||||||
|         return self._topology(ogr_touches, other) |         return self._topology(capi.ogr_touches, other) | ||||||
|  |  | ||||||
|     def crosses(self, other): |     def crosses(self, other): | ||||||
|         "Returns True if this geometry crosses the other." |         "Returns True if this geometry crosses the other." | ||||||
|         return self._topology(ogr_crosses, other) |         return self._topology(capi.ogr_crosses, other) | ||||||
|  |  | ||||||
|     def within(self, other): |     def within(self, other): | ||||||
|         "Returns True if this geometry is within the other." |         "Returns True if this geometry is within the other." | ||||||
|         return self._topology(ogr_within, other) |         return self._topology(capi.ogr_within, other) | ||||||
|  |  | ||||||
|     def contains(self, other): |     def contains(self, other): | ||||||
|         "Returns True if this geometry contains the other." |         "Returns True if this geometry contains the other." | ||||||
|         return self._topology(ogr_contains, other) |         return self._topology(capi.ogr_contains, other) | ||||||
|  |  | ||||||
|     def overlaps(self, other): |     def overlaps(self, other): | ||||||
|         "Returns True if this geometry overlaps the other." |         "Returns True if this geometry overlaps the other." | ||||||
|         return self._topology(ogr_overlaps, other) |         return self._topology(capi.ogr_overlaps, other) | ||||||
|  |  | ||||||
|     #### Geometry-generation Methods #### |     #### Geometry-generation Methods #### | ||||||
|     def _geomgen(self, gen_func, other=None): |     def _geomgen(self, gen_func, other=None): | ||||||
|         "A helper routine for the OGR routines that generate geometries." |         "A helper routine for the OGR routines that generate geometries." | ||||||
|         if isinstance(other, OGRGeometry): |         if isinstance(other, OGRGeometry): | ||||||
|             return OGRGeometry(gen_func(self._ptr, other._ptr), self.srs) |             return OGRGeometry(gen_func(self.ptr, other.ptr), self.srs) | ||||||
|         else: |         else: | ||||||
|             return OGRGeometry(gen_func(self._ptr), self.srs) |             return OGRGeometry(gen_func(self.ptr), self.srs) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def boundary(self): |     def boundary(self): | ||||||
|         "Returns the boundary of this geometry." |         "Returns the boundary of this geometry." | ||||||
|         return self._geomgen(get_boundary) |         return self._geomgen(capi.get_boundary) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def convex_hull(self): |     def convex_hull(self): | ||||||
| @@ -419,35 +439,35 @@ class OGRGeometry(object): | |||||||
|         Returns the smallest convex Polygon that contains all the points in  |         Returns the smallest convex Polygon that contains all the points in  | ||||||
|         this Geometry. |         this Geometry. | ||||||
|         """ |         """ | ||||||
|         return self._geomgen(geom_convex_hull) |         return self._geomgen(capi.geom_convex_hull) | ||||||
|  |  | ||||||
|     def difference(self, other): |     def difference(self, other): | ||||||
|         """ |         """ | ||||||
|         Returns a new geometry consisting of the region which is the difference |         Returns a new geometry consisting of the region which is the difference | ||||||
|         of this geometry and the other. |         of this geometry and the other. | ||||||
|         """ |         """ | ||||||
|         return self._geomgen(geom_diff, other) |         return self._geomgen(capi.geom_diff, other) | ||||||
|  |  | ||||||
|     def intersection(self, other): |     def intersection(self, other): | ||||||
|         """ |         """ | ||||||
|         Returns a new geometry consisting of the region of intersection of this |         Returns a new geometry consisting of the region of intersection of this | ||||||
|         geometry and the other. |         geometry and the other. | ||||||
|         """ |         """ | ||||||
|         return self._geomgen(geom_intersection, other) |         return self._geomgen(capi.geom_intersection, other) | ||||||
|  |  | ||||||
|     def sym_difference(self, other): |     def sym_difference(self, other): | ||||||
|         """                                                                                                                                                 |         """                                                                                                                                                 | ||||||
|         Returns a new geometry which is the symmetric difference of this |         Returns a new geometry which is the symmetric difference of this | ||||||
|         geometry and the other. |         geometry and the other. | ||||||
|         """ |         """ | ||||||
|         return self._geomgen(geom_sym_diff, other) |         return self._geomgen(capi.geom_sym_diff, other) | ||||||
|  |  | ||||||
|     def union(self, other): |     def union(self, other): | ||||||
|         """ |         """ | ||||||
|         Returns a new geometry consisting of the region which is the union of |         Returns a new geometry consisting of the region which is the union of | ||||||
|         this geometry and the other. |         this geometry and the other. | ||||||
|         """ |         """ | ||||||
|         return self._geomgen(geom_union, other) |         return self._geomgen(capi.geom_union, other) | ||||||
|  |  | ||||||
| # The subclasses for OGR Geometry. | # The subclasses for OGR Geometry. | ||||||
| class Point(OGRGeometry): | class Point(OGRGeometry): | ||||||
| @@ -455,18 +475,18 @@ class Point(OGRGeometry): | |||||||
|     @property |     @property | ||||||
|     def x(self): |     def x(self): | ||||||
|         "Returns the X coordinate for this Point." |         "Returns the X coordinate for this Point." | ||||||
|         return getx(self._ptr, 0) |         return capi.getx(self.ptr, 0) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def y(self): |     def y(self): | ||||||
|         "Returns the Y coordinate for this Point." |         "Returns the Y coordinate for this Point." | ||||||
|         return gety(self._ptr, 0) |         return capi.gety(self.ptr, 0) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def z(self): |     def z(self): | ||||||
|         "Returns the Z coordinate for this Point." |         "Returns the Z coordinate for this Point." | ||||||
|         if self.coord_dim == 3: |         if self.coord_dim == 3: | ||||||
|             return getz(self._ptr, 0) |             return capi.getz(self.ptr, 0) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def tuple(self): |     def tuple(self): | ||||||
| @@ -483,7 +503,7 @@ class LineString(OGRGeometry): | |||||||
|         "Returns the Point at the given index." |         "Returns the Point at the given index." | ||||||
|         if index >= 0 and index < self.point_count: |         if index >= 0 and index < self.point_count: | ||||||
|             x, y, z = c_double(), c_double(), c_double() |             x, y, z = c_double(), c_double(), c_double() | ||||||
|             get_point(self._ptr, index, byref(x), byref(y), byref(z)) |             capi.get_point(self.ptr, index, byref(x), byref(y), byref(z)) | ||||||
|             dim = self.coord_dim |             dim = self.coord_dim | ||||||
|             if dim == 1: |             if dim == 1: | ||||||
|                 return (x.value,) |                 return (x.value,) | ||||||
| @@ -514,23 +534,23 @@ class LineString(OGRGeometry): | |||||||
|         Internal routine that returns a sequence (list) corresponding with |         Internal routine that returns a sequence (list) corresponding with | ||||||
|         the given function. |         the given function. | ||||||
|         """ |         """ | ||||||
|         return [func(self._ptr, i) for i in xrange(len(self))] |         return [func(self.ptr, i) for i in xrange(len(self))] | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def x(self): |     def x(self): | ||||||
|         "Returns the X coordinates in a list." |         "Returns the X coordinates in a list." | ||||||
|         return self._listarr(getx) |         return self._listarr(capi.getx) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def y(self): |     def y(self): | ||||||
|         "Returns the Y coordinates in a list." |         "Returns the Y coordinates in a list." | ||||||
|         return self._listarr(gety) |         return self._listarr(capi.gety) | ||||||
|      |      | ||||||
|     @property |     @property | ||||||
|     def z(self): |     def z(self): | ||||||
|         "Returns the Z coordinates in a list." |         "Returns the Z coordinates in a list." | ||||||
|         if self.coord_dim == 3: |         if self.coord_dim == 3: | ||||||
|             return self._listarr(getz) |             return self._listarr(capi.getz) | ||||||
|  |  | ||||||
| # LinearRings are used in Polygons. | # LinearRings are used in Polygons. | ||||||
| class LinearRing(LineString): pass | class LinearRing(LineString): pass | ||||||
| @@ -551,7 +571,7 @@ class Polygon(OGRGeometry): | |||||||
|         if index < 0 or index >= self.geom_count: |         if index < 0 or index >= self.geom_count: | ||||||
|             raise OGRIndexError('index out of range: %s' % index) |             raise OGRIndexError('index out of range: %s' % index) | ||||||
|         else: |         else: | ||||||
|             return OGRGeometry(clone_geom(get_geom_ref(self._ptr, index)), self.srs) |             return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs) | ||||||
|  |  | ||||||
|     # Polygon Properties |     # Polygon Properties | ||||||
|     @property |     @property | ||||||
| @@ -577,7 +597,7 @@ class Polygon(OGRGeometry): | |||||||
|         "Returns the centroid (a Point) of this Polygon." |         "Returns the centroid (a Point) of this Polygon." | ||||||
|         # The centroid is a Point, create a geometry for this. |         # The centroid is a Point, create a geometry for this. | ||||||
|         p = OGRGeometry(OGRGeomType('Point')) |         p = OGRGeometry(OGRGeomType('Point')) | ||||||
|         get_centroid(self._ptr, p._ptr) |         capi.get_centroid(self.ptr, p.ptr) | ||||||
|         return p |         return p | ||||||
|  |  | ||||||
| # Geometry Collection base class. | # Geometry Collection base class. | ||||||
| @@ -589,7 +609,7 @@ class GeometryCollection(OGRGeometry): | |||||||
|         if index < 0 or index >= self.geom_count: |         if index < 0 or index >= self.geom_count: | ||||||
|             raise OGRIndexError('index out of range: %s' % index) |             raise OGRIndexError('index out of range: %s' % index) | ||||||
|         else: |         else: | ||||||
|             return OGRGeometry(clone_geom(get_geom_ref(self._ptr, index)), self.srs) |             return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs) | ||||||
|          |          | ||||||
|     def __iter__(self): |     def __iter__(self): | ||||||
|         "Iterates over each Geometry." |         "Iterates over each Geometry." | ||||||
| @@ -604,12 +624,12 @@ class GeometryCollection(OGRGeometry): | |||||||
|         "Add the geometry to this Geometry Collection." |         "Add the geometry to this Geometry Collection." | ||||||
|         if isinstance(geom, OGRGeometry): |         if isinstance(geom, OGRGeometry): | ||||||
|             if isinstance(geom, self.__class__): |             if isinstance(geom, self.__class__): | ||||||
|                 for g in geom: add_geom(self._ptr, g._ptr) |                 for g in geom: capi.add_geom(self.ptr, g.ptr) | ||||||
|             else: |             else: | ||||||
|                 add_geom(self._ptr, geom._ptr) |                 capi.add_geom(self.ptr, geom.ptr) | ||||||
|         elif isinstance(geom, basestring): |         elif isinstance(geom, basestring): | ||||||
|             tmp = OGRGeometry(geom) |             tmp = OGRGeometry(geom) | ||||||
|             add_geom(self._ptr, tmp._ptr) |             capi.add_geom(self.ptr, tmp.ptr) | ||||||
|         else: |         else: | ||||||
|             raise OGRException('Must add an OGRGeometry.') |             raise OGRException('Must add an OGRGeometry.') | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,9 @@ class OGRGeomType(object): | |||||||
|         if isinstance(type_input, OGRGeomType): |         if isinstance(type_input, OGRGeomType): | ||||||
|             num = type_input.num |             num = type_input.num | ||||||
|         elif isinstance(type_input, basestring): |         elif isinstance(type_input, basestring): | ||||||
|             num = self._str_types.get(type_input.lower(), None) |             type_input = type_input.lower() | ||||||
|  |             if type_input == 'geometry': type_input='unknown' | ||||||
|  |             num = self._str_types.get(type_input, None) | ||||||
|             if num is None: |             if num is None: | ||||||
|                 raise OGRException('Invalid OGR String Type "%s"' % type_input) |                 raise OGRException('Invalid OGR String Type "%s"' % type_input) | ||||||
|         elif isinstance(type_input, int): |         elif isinstance(type_input, int): | ||||||
| @@ -67,7 +69,8 @@ class OGRGeomType(object): | |||||||
|     def django(self): |     def django(self): | ||||||
|         "Returns the Django GeometryField for this OGR Type." |         "Returns the Django GeometryField for this OGR Type." | ||||||
|         s = self.name |         s = self.name | ||||||
|         if s in ('Unknown', 'LinearRing', 'None'): |         if s in ('LinearRing', 'None'): | ||||||
|             return None |             return None | ||||||
|         else: |         elif s == 'Unknown': | ||||||
|             return s + 'Field' |             s = 'Geometry' | ||||||
|  |         return s + 'Field' | ||||||
|   | |||||||
| @@ -2,26 +2,22 @@ | |||||||
| from ctypes import byref | from ctypes import byref | ||||||
|  |  | ||||||
| # Other GDAL imports. | # 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.envelope import Envelope, OGREnvelope | ||||||
| from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException | from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException | ||||||
| from django.contrib.gis.gdal.feature import Feature | from django.contrib.gis.gdal.feature import Feature | ||||||
| from django.contrib.gis.gdal.field import FIELD_CLASSES | from django.contrib.gis.gdal.field import OGRFieldTypes | ||||||
| from django.contrib.gis.gdal.geometries import OGRGeomType | from django.contrib.gis.gdal.geometries import OGRGeomType | ||||||
| from django.contrib.gis.gdal.srs import SpatialReference | from django.contrib.gis.gdal.srs import SpatialReference | ||||||
|  |  | ||||||
| # GDAL ctypes function prototypes. | # GDAL ctypes function prototypes. | ||||||
| from django.contrib.gis.gdal.prototypes.ds import \ | from django.contrib.gis.gdal.prototypes import ds as capi, srs as srs_api | ||||||
|     get_extent, get_fd_geom_type, get_fd_name, get_feature, get_feature_count, \ |  | ||||||
|     get_field_count, get_field_defn, get_field_name, get_field_precision, \ |  | ||||||
|     get_field_width, get_field_type, get_layer_defn, get_layer_srs, \ |  | ||||||
|     get_next_feature, reset_reading, test_capability |  | ||||||
| from django.contrib.gis.gdal.prototypes.srs import clone_srs |  | ||||||
|  |  | ||||||
| # 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 | ||||||
| # | # | ||||||
| # The OGR_L_* routines are relevant here. | # The OGR_L_* routines are relevant here. | ||||||
| class Layer(object): | class Layer(GDALBase): | ||||||
|     "A class that wraps an OGR Layer, needs to be instantiated from a DataSource object." |     "A class that wraps an OGR Layer, needs to be instantiated from a DataSource object." | ||||||
|  |  | ||||||
|     #### Python 'magic' routines #### |     #### Python 'magic' routines #### | ||||||
| @@ -32,12 +28,11 @@ class Layer(object): | |||||||
|         reference to it is kept with this Layer.  This prevents garbage  |         reference to it is kept with this Layer.  This prevents garbage  | ||||||
|         collection of the `DataSource` while this Layer is still active. |         collection of the `DataSource` while this Layer is still active. | ||||||
|         """ |         """ | ||||||
|         self._ptr = None # Initially NULL |  | ||||||
|         if not layer_ptr: |         if not layer_ptr: | ||||||
|             raise OGRException('Cannot create Layer, invalid pointer given') |             raise OGRException('Cannot create Layer, invalid pointer given') | ||||||
|         self._ptr = layer_ptr |         self.ptr = layer_ptr | ||||||
|         self._ds = ds |         self._ds = ds | ||||||
|         self._ldefn = get_layer_defn(self._ptr) |         self._ldefn = capi.get_layer_defn(self._ptr) | ||||||
|         # Does the Layer support random reading? |         # Does the Layer support random reading? | ||||||
|         self._random_read = self.test_capability('RandomRead') |         self._random_read = self.test_capability('RandomRead') | ||||||
|  |  | ||||||
| @@ -59,9 +54,9 @@ class Layer(object): | |||||||
|     def __iter__(self): |     def __iter__(self): | ||||||
|         "Iterates over each Feature in the Layer." |         "Iterates over each Feature in the Layer." | ||||||
|         # ResetReading() must be called before iteration is to begin. |         # ResetReading() must be called before iteration is to begin. | ||||||
|         reset_reading(self._ptr) |         capi.reset_reading(self._ptr) | ||||||
|         for i in xrange(self.num_feat): |         for i in xrange(self.num_feat): | ||||||
|             yield Feature(get_next_feature(self._ptr), self._ldefn) |             yield Feature(capi.get_next_feature(self._ptr), self._ldefn) | ||||||
|  |  | ||||||
|     def __len__(self): |     def __len__(self): | ||||||
|         "The length is the number of features." |         "The length is the number of features." | ||||||
| @@ -81,7 +76,7 @@ class Layer(object): | |||||||
|         if self._random_read: |         if self._random_read: | ||||||
|             # If the Layer supports random reading, return. |             # If the Layer supports random reading, return. | ||||||
|             try: |             try: | ||||||
|                 return Feature(get_feature(self._ptr, feat_id), self._ldefn) |                 return Feature(capi.get_feature(self.ptr, feat_id), self._ldefn) | ||||||
|             except OGRException: |             except OGRException: | ||||||
|                 pass |                 pass | ||||||
|         else: |         else: | ||||||
| @@ -97,35 +92,35 @@ class Layer(object): | |||||||
|     def extent(self): |     def extent(self): | ||||||
|         "Returns the extent (an Envelope) of this layer." |         "Returns the extent (an Envelope) of this layer." | ||||||
|         env = OGREnvelope() |         env = OGREnvelope() | ||||||
|         get_extent(self._ptr, byref(env), 1) |         capi.get_extent(self.ptr, byref(env), 1) | ||||||
|         return Envelope(env) |         return Envelope(env) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def name(self): |     def name(self): | ||||||
|         "Returns the name of this layer in the Data Source." |         "Returns the name of this layer in the Data Source." | ||||||
|         return get_fd_name(self._ldefn) |         return capi.get_fd_name(self._ldefn) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def num_feat(self, force=1): |     def num_feat(self, force=1): | ||||||
|         "Returns the number of features in the Layer." |         "Returns the number of features in the Layer." | ||||||
|         return get_feature_count(self._ptr, force) |         return capi.get_feature_count(self.ptr, force) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def num_fields(self): |     def num_fields(self): | ||||||
|         "Returns the number of fields in the Layer." |         "Returns the number of fields in the Layer." | ||||||
|         return get_field_count(self._ldefn) |         return capi.get_field_count(self._ldefn) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def geom_type(self): |     def geom_type(self): | ||||||
|         "Returns the geometry type (OGRGeomType) of the Layer." |         "Returns the geometry type (OGRGeomType) of the Layer." | ||||||
|         return OGRGeomType(get_fd_geom_type(self._ldefn)) |         return OGRGeomType(capi.get_fd_geom_type(self._ldefn)) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def srs(self): |     def srs(self): | ||||||
|         "Returns the Spatial Reference used in this Layer." |         "Returns the Spatial Reference used in this Layer." | ||||||
|         try: |         try: | ||||||
|             ptr = get_layer_srs(self._ptr) |             ptr = capi.get_layer_srs(self.ptr) | ||||||
|             return SpatialReference(clone_srs(ptr)) |             return SpatialReference(srs_api.clone_srs(ptr)) | ||||||
|         except SRSException: |         except SRSException: | ||||||
|             return None |             return None | ||||||
|  |  | ||||||
| @@ -135,7 +130,7 @@ class Layer(object): | |||||||
|         Returns a list of string names corresponding to each of the Fields |         Returns a list of string names corresponding to each of the Fields | ||||||
|         available in this Layer. |         available in this Layer. | ||||||
|         """ |         """ | ||||||
|         return [get_field_name(get_field_defn(self._ldefn, i))  |         return [capi.get_field_name(capi.get_field_defn(self._ldefn, i))  | ||||||
|                 for i in xrange(self.num_fields) ] |                 for i in xrange(self.num_fields) ] | ||||||
|      |      | ||||||
|     @property |     @property | ||||||
| @@ -146,19 +141,19 @@ class Layer(object): | |||||||
|         an OGR layer that had an integer, a floating-point, and string |         an OGR layer that had an integer, a floating-point, and string | ||||||
|         fields. |         fields. | ||||||
|         """ |         """ | ||||||
|         return [FIELD_CLASSES[get_field_type(get_field_defn(self._ldefn, i))] |         return [OGRFieldTypes[capi.get_field_type(capi.get_field_defn(self._ldefn, i))] | ||||||
|                 for i in xrange(self.num_fields)] |                 for i in xrange(self.num_fields)] | ||||||
|  |  | ||||||
|     @property  |     @property  | ||||||
|     def field_widths(self): |     def field_widths(self): | ||||||
|         "Returns a list of the maximum field widths for the features." |         "Returns a list of the maximum field widths for the features." | ||||||
|         return [get_field_width(get_field_defn(self._ldefn, i)) |         return [capi.get_field_width(capi.get_field_defn(self._ldefn, i)) | ||||||
|                 for i in xrange(self.num_fields)] |                 for i in xrange(self.num_fields)] | ||||||
|  |  | ||||||
|     @property  |     @property  | ||||||
|     def field_precisions(self): |     def field_precisions(self): | ||||||
|         "Returns the field precisions for the features." |         "Returns the field precisions for the features." | ||||||
|         return [get_field_precision(get_field_defn(self._ldefn, i)) |         return [capi.get_field_precision(capi.get_field_defn(self._ldefn, i)) | ||||||
|                 for i in xrange(self.num_fields)] |                 for i in xrange(self.num_fields)] | ||||||
|  |  | ||||||
|     #### Layer Methods #### |     #### Layer Methods #### | ||||||
| @@ -190,4 +185,4 @@ class Layer(object): | |||||||
|           'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions', |           'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions', | ||||||
|           'DeleteFeature', and 'FastSetNextByIndex'. |           'DeleteFeature', and 'FastSetNextByIndex'. | ||||||
|         """ |         """ | ||||||
|         return bool(test_capability(self._ptr, capability)) |         return bool(capi.test_capability(self.ptr, capability)) | ||||||
|   | |||||||
| @@ -38,9 +38,11 @@ def topology_func(f): | |||||||
| if GEOJSON: | if GEOJSON: | ||||||
|     from_json = geom_output(lgdal.OGR_G_CreateGeometryFromJson, [c_char_p]) |     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) |     to_json = string_output(lgdal.OGR_G_ExportToJson, [c_void_p], str_result=True) | ||||||
|  |     to_kml = string_output(lgdal.OGR_G_ExportToKML, [c_void_p, c_char_p], str_result=True)  | ||||||
| else: | else: | ||||||
|     from_json = False |     from_json = False | ||||||
|     to_json = False |     to_json = False | ||||||
|  |     to_kml = False | ||||||
|  |  | ||||||
| # GetX, GetY, GetZ all return doubles. | # GetX, GetY, GetZ all return doubles. | ||||||
| getx = pnt_func(lgdal.OGR_G_GetX) | getx = pnt_func(lgdal.OGR_G_GetX) | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ 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_proj = void_output(lgdal.OSRImportFromProj4, [c_void_p, c_char_p]) | ||||||
| from_epsg = void_output(std_call('OSRImportFromEPSG'), [c_void_p, c_int]) | 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_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. | # Morphing to/from ESRI WKT. | ||||||
| morph_to_esri = void_output(lgdal.OSRMorphToESRI, [c_void_p]) | morph_to_esri = void_output(lgdal.OSRMorphToESRI, [c_void_p]) | ||||||
|   | |||||||
| @@ -27,89 +27,74 @@ | |||||||
|   NAD83 / Texas South Central |   NAD83 / Texas South Central | ||||||
| """ | """ | ||||||
| import re | import re | ||||||
| from types import UnicodeType, TupleType |  | ||||||
| from ctypes import byref, c_char_p, c_int, c_void_p | from ctypes import byref, c_char_p, c_int, c_void_p | ||||||
|  |  | ||||||
| # Getting the error checking routine and exceptions | # Getting the error checking routine and exceptions | ||||||
|  | from django.contrib.gis.gdal.base import GDALBase | ||||||
| from django.contrib.gis.gdal.error import OGRException, SRSException | from django.contrib.gis.gdal.error import OGRException, SRSException | ||||||
| from django.contrib.gis.gdal.prototypes.srs import * | from django.contrib.gis.gdal.prototypes import srs as capi | ||||||
|  |  | ||||||
| #### Spatial Reference class. #### | #### Spatial Reference class. #### | ||||||
| class SpatialReference(object): | class SpatialReference(GDALBase): | ||||||
|     """ |     """ | ||||||
|     A wrapper for the OGRSpatialReference object.  According to the GDAL website, |     A wrapper for the OGRSpatialReference object.  According to the GDAL website, | ||||||
|     the SpatialReference object "provide[s] services to represent coordinate  |     the SpatialReference object "provide[s] services to represent coordinate  | ||||||
|     systems (projections and datums) and to transform between them." |     systems (projections and datums) and to transform between them." | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     # Well-Known Geographical Coordinate System Name |  | ||||||
|     _well_known = {'WGS84':4326, 'WGS72':4322, 'NAD27':4267, 'NAD83':4269} |  | ||||||
|     _epsg_regex = re.compile('^(EPSG:)?(?P<epsg>\d+)$', re.I) |  | ||||||
|     _proj_regex = re.compile(r'^\+proj') |  | ||||||
|  |  | ||||||
|     #### Python 'magic' routines #### |     #### Python 'magic' routines #### | ||||||
|     def __init__(self, srs_input='', srs_type='wkt'): |     def __init__(self, srs_input=''): | ||||||
|         """ |         """ | ||||||
|         Creates a GDAL OSR Spatial Reference object from the given 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  |         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  |         EPSG code, a PROJ.4 string, and/or a projection "well known" shorthand  | ||||||
|         string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83'). |         string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83'). | ||||||
|         """ |         """ | ||||||
|         # Intializing pointer and string buffer. |  | ||||||
|         self._ptr = None |  | ||||||
|         buf = c_char_p('') |         buf = c_char_p('') | ||||||
|  |         srs_type = 'user' | ||||||
|  |  | ||||||
|         if isinstance(srs_input, basestring): |         if isinstance(srs_input, basestring): | ||||||
|             # Encoding to ASCII if unicode passed in. |             # Encoding to ASCII if unicode passed in. | ||||||
|             if isinstance(srs_input, UnicodeType): |             if isinstance(srs_input, unicode): | ||||||
|                 srs_input = srs_input.encode('ascii') |                 srs_input = srs_input.encode('ascii') | ||||||
|  |             try: | ||||||
|             epsg_m = self._epsg_regex.match(srs_input) |                 # If SRID is a string, e.g., '4326', then make acceptable | ||||||
|             proj_m = self._proj_regex.match(srs_input) |                 # as user input. | ||||||
|             if epsg_m: |                 srid = int(srs_input) | ||||||
|                 # Is this an EPSG well known name?     |                 srs_input = 'EPSG:%d' % srid | ||||||
|                 srs_type = 'epsg' |             except ValueError: | ||||||
|                 srs_input = int(epsg_m.group('epsg')) |  | ||||||
|             elif proj_m: |  | ||||||
|                 # Is the string a PROJ.4 string? |  | ||||||
|                 srs_type = 'proj' |  | ||||||
|             elif srs_input in self._well_known: |  | ||||||
|                 # Is this a short-hand well known name?   |  | ||||||
|                 srs_type = 'epsg' |  | ||||||
|                 srs_input = self._well_known[srs_input] |  | ||||||
|             elif srs_type == 'proj': |  | ||||||
|                 pass |                 pass | ||||||
|             else: |         elif isinstance(srs_input, (int, long)): | ||||||
|                 # Setting the buffer with WKT, PROJ.4 string, etc. |  | ||||||
|                 buf = c_char_p(srs_input) |  | ||||||
|         elif isinstance(srs_input, int): |  | ||||||
|             # EPSG integer code was input. |             # EPSG integer code was input. | ||||||
|             if srs_type != 'epsg': srs_type = 'epsg' |             srs_type = 'epsg' | ||||||
|         elif isinstance(srs_input, c_void_p): |         elif isinstance(srs_input, self.ptr_type): | ||||||
|  |             srs = srs_input | ||||||
|             srs_type = 'ogr' |             srs_type = 'ogr' | ||||||
|         else: |         else: | ||||||
|             raise TypeError('Invalid SRS type "%s"' % srs_type) |             raise TypeError('Invalid SRS type "%s"' % srs_type) | ||||||
|  |  | ||||||
|         if srs_type == 'ogr': |         if srs_type == 'ogr': | ||||||
|             # SRS input is OGR pointer |             # Input is already an SRS pointer. | ||||||
|             srs = srs_input |             srs = srs_input | ||||||
|         else: |         else: | ||||||
|             # Creating a new pointer, using the string buffer. |             # Creating a new SRS pointer, using the string buffer. | ||||||
|             srs = new_srs(buf) |             srs = capi.new_srs(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: %s' % srs_input) |             raise SRSException('Could not create spatial reference from: %s' % srs_input) | ||||||
|         else: |         else: | ||||||
|             self._ptr = srs |             self.ptr = srs | ||||||
|  |  | ||||||
|         # Post-processing if in PROJ.4 or EPSG formats. |         # Importing from either the user input string or an integer SRID. | ||||||
|         if srs_type == 'proj': self.import_proj(srs_input) |         if srs_type == 'user': | ||||||
|         elif srs_type == 'epsg': self.import_epsg(srs_input) |             self.import_user_input(srs_input) | ||||||
|  |         elif srs_type == 'epsg': | ||||||
|  |             self.import_epsg(srs_input) | ||||||
|  |  | ||||||
|     def __del__(self): |     def __del__(self): | ||||||
|         "Destroys this spatial reference." |         "Destroys this spatial reference." | ||||||
|         if self._ptr: release_srs(self._ptr) |         if self._ptr: capi.release_srs(self._ptr) | ||||||
|  |  | ||||||
|     def __getitem__(self, target): |     def __getitem__(self, target): | ||||||
|         """ |         """ | ||||||
| @@ -134,7 +119,7 @@ class SpatialReference(object): | |||||||
|         >>> print srs['UNIT|AUTHORITY', 1] # The authority value for the untis |         >>> print srs['UNIT|AUTHORITY', 1] # The authority value for the untis | ||||||
|         9122 |         9122 | ||||||
|         """ |         """ | ||||||
|         if isinstance(target, TupleType): |         if isinstance(target, tuple): | ||||||
|             return self.attr_value(*target) |             return self.attr_value(*target) | ||||||
|         else: |         else: | ||||||
|             return self.attr_value(target) |             return self.attr_value(target) | ||||||
| @@ -149,40 +134,40 @@ class SpatialReference(object): | |||||||
|         The attribute value for the given target node (e.g. 'PROJCS'). The index |         The attribute value for the given target node (e.g. 'PROJCS'). The index | ||||||
|         keyword specifies an index of the child node to return. |         keyword specifies an index of the child node to return. | ||||||
|         """ |         """ | ||||||
|         if not isinstance(target, str) or not isinstance(index, int): |         if not isinstance(target, basestring) or not isinstance(index, int): | ||||||
|             raise TypeError |             raise TypeError | ||||||
|         return get_attr_value(self._ptr, target, index) |         return capi.get_attr_value(self.ptr, target, index) | ||||||
|  |  | ||||||
|     def auth_name(self, target): |     def auth_name(self, target): | ||||||
|         "Returns the authority name for the given string target node." |         "Returns the authority name for the given string target node." | ||||||
|         return get_auth_name(self._ptr, target) |         return capi.get_auth_name(self.ptr, target) | ||||||
|      |      | ||||||
|     def auth_code(self, target): |     def auth_code(self, target): | ||||||
|         "Returns the authority code for the given string target node." |         "Returns the authority code for the given string target node." | ||||||
|         return get_auth_code(self._ptr, target) |         return capi.get_auth_code(self.ptr, target) | ||||||
|  |  | ||||||
|     def clone(self): |     def clone(self): | ||||||
|         "Returns a clone of this SpatialReference object." |         "Returns a clone of this SpatialReference object." | ||||||
|         return SpatialReference(clone_srs(self._ptr)) |         return SpatialReference(capi.clone_srs(self.ptr)) | ||||||
|  |  | ||||||
|     def from_esri(self): |     def from_esri(self): | ||||||
|         "Morphs this SpatialReference from ESRI's format to EPSG." |         "Morphs this SpatialReference from ESRI's format to EPSG." | ||||||
|         morph_from_esri(self._ptr) |         capi.morph_from_esri(self.ptr) | ||||||
|  |  | ||||||
|     def identify_epsg(self): |     def identify_epsg(self): | ||||||
|         """ |         """ | ||||||
|         This method inspects the WKT of this SpatialReference, and will |         This method inspects the WKT of this SpatialReference, and will | ||||||
|         add EPSG authority nodes where an EPSG identifier is applicable. |         add EPSG authority nodes where an EPSG identifier is applicable. | ||||||
|         """ |         """ | ||||||
|         identify_epsg(self._ptr) |         capi.identify_epsg(self.ptr) | ||||||
|  |  | ||||||
|     def to_esri(self): |     def to_esri(self): | ||||||
|         "Morphs this SpatialReference to ESRI's format." |         "Morphs this SpatialReference to ESRI's format." | ||||||
|         morph_to_esri(self._ptr) |         capi.morph_to_esri(self.ptr) | ||||||
|  |  | ||||||
|     def validate(self): |     def validate(self): | ||||||
|         "Checks to see if the given spatial reference is valid." |         "Checks to see if the given spatial reference is valid." | ||||||
|         srs_validate(self._ptr) |         capi.srs_validate(self.ptr) | ||||||
|      |      | ||||||
|     #### Name & SRID properties #### |     #### Name & SRID properties #### | ||||||
|     @property |     @property | ||||||
| @@ -205,25 +190,25 @@ class SpatialReference(object): | |||||||
|     @property |     @property | ||||||
|     def linear_name(self): |     def linear_name(self): | ||||||
|         "Returns the name of the linear units." |         "Returns the name of the linear units." | ||||||
|         units, name = linear_units(self._ptr, byref(c_char_p())) |         units, name = capi.linear_units(self.ptr, byref(c_char_p())) | ||||||
|         return name |         return name | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def linear_units(self): |     def linear_units(self): | ||||||
|         "Returns the value of the linear units." |         "Returns the value of the linear units." | ||||||
|         units, name = linear_units(self._ptr, byref(c_char_p())) |         units, name = capi.linear_units(self.ptr, byref(c_char_p())) | ||||||
|         return units |         return units | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def angular_name(self): |     def angular_name(self): | ||||||
|         "Returns the name of the angular units." |         "Returns the name of the angular units." | ||||||
|         units, name = angular_units(self._ptr, byref(c_char_p())) |         units, name = capi.angular_units(self.ptr, byref(c_char_p())) | ||||||
|         return name |         return name | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def angular_units(self): |     def angular_units(self): | ||||||
|         "Returns the value of the angular units." |         "Returns the value of the angular units." | ||||||
|         units, name = angular_units(self._ptr, byref(c_char_p())) |         units, name = capi.angular_units(self.ptr, byref(c_char_p())) | ||||||
|         return units |         return units | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
| @@ -234,9 +219,9 @@ class SpatialReference(object): | |||||||
|         or angular units. |         or angular units. | ||||||
|         """ |         """ | ||||||
|         if self.projected or self.local: |         if self.projected or self.local: | ||||||
|             return linear_units(self._ptr, byref(c_char_p())) |             return capi.linear_units(self.ptr, byref(c_char_p())) | ||||||
|         elif self.geographic: |         elif self.geographic: | ||||||
|             return angular_units(self._ptr, byref(c_char_p())) |             return capi.angular_units(self.ptr, byref(c_char_p())) | ||||||
|         else: |         else: | ||||||
|             return (None, None) |             return (None, None) | ||||||
|  |  | ||||||
| @@ -252,17 +237,17 @@ class SpatialReference(object): | |||||||
|     @property |     @property | ||||||
|     def semi_major(self): |     def semi_major(self): | ||||||
|         "Returns the Semi Major Axis for this Spatial Reference." |         "Returns the Semi Major Axis for this Spatial Reference." | ||||||
|         return semi_major(self._ptr, byref(c_int())) |         return capi.semi_major(self.ptr, byref(c_int())) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def semi_minor(self): |     def semi_minor(self): | ||||||
|         "Returns the Semi Minor Axis for this Spatial Reference." |         "Returns the Semi Minor Axis for this Spatial Reference." | ||||||
|         return semi_minor(self._ptr, byref(c_int())) |         return capi.semi_minor(self.ptr, byref(c_int())) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def inverse_flattening(self): |     def inverse_flattening(self): | ||||||
|         "Returns the Inverse Flattening for this Spatial Reference." |         "Returns the Inverse Flattening for this Spatial Reference." | ||||||
|         return invflattening(self._ptr, byref(c_int())) |         return capi.invflattening(self.ptr, byref(c_int())) | ||||||
|  |  | ||||||
|     #### Boolean Properties #### |     #### Boolean Properties #### | ||||||
|     @property |     @property | ||||||
| @@ -271,12 +256,12 @@ class SpatialReference(object): | |||||||
|         Returns True if this SpatialReference is geographic  |         Returns True if this SpatialReference is geographic  | ||||||
|          (root node is GEOGCS). |          (root node is GEOGCS). | ||||||
|         """ |         """ | ||||||
|         return bool(isgeographic(self._ptr)) |         return bool(capi.isgeographic(self.ptr)) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def local(self): |     def local(self): | ||||||
|         "Returns True if this SpatialReference is local (root node is LOCAL_CS)." |         "Returns True if this SpatialReference is local (root node is LOCAL_CS)." | ||||||
|         return bool(islocal(self._ptr)) |         return bool(capi.islocal(self.ptr)) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def projected(self): |     def projected(self): | ||||||
| @@ -284,40 +269,44 @@ class SpatialReference(object): | |||||||
|         Returns True if this SpatialReference is a projected coordinate system  |         Returns True if this SpatialReference is a projected coordinate system  | ||||||
|          (root node is PROJCS). |          (root node is PROJCS). | ||||||
|         """ |         """ | ||||||
|         return bool(isprojected(self._ptr)) |         return bool(capi.isprojected(self.ptr)) | ||||||
|  |  | ||||||
|     #### Import Routines ##### |     #### Import Routines ##### | ||||||
|     def import_wkt(self, wkt): |     def import_epsg(self, epsg): | ||||||
|         "Imports the Spatial Reference from OGC WKT (string)" |         "Imports the Spatial Reference from the EPSG code (an integer)." | ||||||
|         from_wkt(self._ptr, byref(c_char_p(wkt))) |         capi.from_epsg(self.ptr, epsg) | ||||||
|  |  | ||||||
|     def import_proj(self, proj): |     def import_proj(self, proj): | ||||||
|         "Imports the Spatial Reference from a PROJ.4 string." |         "Imports the Spatial Reference from a PROJ.4 string." | ||||||
|         from_proj(self._ptr, proj) |         capi.from_proj(self.ptr, proj) | ||||||
|  |  | ||||||
|     def import_epsg(self, epsg): |     def import_user_input(self, user_input): | ||||||
|         "Imports the Spatial Reference from the EPSG code (an integer)." |         "Imports the Spatial Reference from the given user input string." | ||||||
|         from_epsg(self._ptr, epsg) |         capi.from_user_input(self.ptr, 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): |     def import_xml(self, xml): | ||||||
|         "Imports the Spatial Reference from an XML string." |         "Imports the Spatial Reference from an XML string." | ||||||
|         from_xml(self._ptr, xml) |         capi.from_xml(self.ptr, xml) | ||||||
|  |  | ||||||
|     #### Export Properties #### |     #### Export Properties #### | ||||||
|     @property |     @property | ||||||
|     def wkt(self): |     def wkt(self): | ||||||
|         "Returns the WKT representation of this Spatial Reference." |         "Returns the WKT representation of this Spatial Reference." | ||||||
|         return to_wkt(self._ptr, byref(c_char_p())) |         return capi.to_wkt(self.ptr, byref(c_char_p())) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def pretty_wkt(self, simplify=0): |     def pretty_wkt(self, simplify=0): | ||||||
|         "Returns the 'pretty' representation of the WKT." |         "Returns the 'pretty' representation of the WKT." | ||||||
|         return to_pretty_wkt(self._ptr, byref(c_char_p()), simplify) |         return capi.to_pretty_wkt(self.ptr, byref(c_char_p()), simplify) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def proj(self): |     def proj(self): | ||||||
|         "Returns the PROJ.4 representation for this Spatial Reference." |         "Returns the PROJ.4 representation for this Spatial Reference." | ||||||
|         return to_proj(self._ptr, byref(c_char_p())) |         return capi.to_proj(self.ptr, byref(c_char_p())) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def proj4(self): |     def proj4(self): | ||||||
| @@ -327,34 +316,22 @@ class SpatialReference(object): | |||||||
|     @property |     @property | ||||||
|     def xml(self, dialect=''): |     def xml(self, dialect=''): | ||||||
|         "Returns the XML representation of this Spatial Reference." |         "Returns the XML representation of this Spatial Reference." | ||||||
|         # FIXME: This leaks memory, have to figure out why. |         return capi.to_xml(self.ptr, byref(c_char_p()), dialect) | ||||||
|         return to_xml(self._ptr, byref(c_char_p()), dialect) |  | ||||||
|  |  | ||||||
|     def to_esri(self): | class CoordTransform(GDALBase): | ||||||
|         "Morphs this SpatialReference to ESRI's format." |  | ||||||
|         morph_to_esri(self._ptr) |  | ||||||
|  |  | ||||||
|     def from_esri(self): |  | ||||||
|         "Morphs this SpatialReference from ESRI's format to EPSG." |  | ||||||
|         morph_from_esri(self._ptr) |  | ||||||
|  |  | ||||||
| class CoordTransform(object): |  | ||||||
|     "The coordinate system transformation object." |     "The coordinate system transformation object." | ||||||
|  |  | ||||||
|     def __init__(self, source, target): |     def __init__(self, source, target): | ||||||
|         "Initializes on a source and target SpatialReference objects." |         "Initializes on a source and target SpatialReference objects." | ||||||
|         self._ptr = None # 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 TypeError('source and target must be of type SpatialReference') | ||||||
|         self._ptr = new_ct(source._ptr, target._ptr) |         self.ptr = capi.new_ct(source._ptr, target._ptr) | ||||||
|         if not self._ptr: |  | ||||||
|             raise SRSException('could not intialize CoordTransform object') |  | ||||||
|         self._srs1_name = source.name |         self._srs1_name = source.name | ||||||
|         self._srs2_name = target.name |         self._srs2_name = target.name | ||||||
|  |  | ||||||
|     def __del__(self): |     def __del__(self): | ||||||
|         "Deletes this Coordinate Transformation object." |         "Deletes this Coordinate Transformation object." | ||||||
|         if self._ptr: destroy_ct(self._ptr) |         if self._ptr: capi.destroy_ct(self._ptr) | ||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         return 'Transform from "%s" to "%s"' % (self._srs1_name, self._srs2_name) |         return 'Transform from "%s" to "%s"' % (self._srs1_name, self._srs2_name) | ||||||
|   | |||||||
| @@ -5,16 +5,13 @@ of these tests require the use of the database. | |||||||
| from unittest import TestSuite, TextTestRunner | from unittest import TestSuite, TextTestRunner | ||||||
| 
 | 
 | ||||||
| # Importing the GDAL test modules. | # Importing the GDAL test modules. | ||||||
| from django.contrib.gis.tests import \ | import test_driver, test_ds, test_envelope, test_geom, test_srs | ||||||
|      test_gdal_driver, test_gdal_ds, test_gdal_envelope, \ |  | ||||||
|      test_gdal_geom, test_gdal_srs |  | ||||||
| 
 | 
 | ||||||
| 
 | test_suites = [test_driver.suite(), | ||||||
| test_suites = [test_gdal_driver.suite(), |                test_ds.suite(), | ||||||
|                test_gdal_ds.suite(), |                test_envelope.suite(), | ||||||
|                test_gdal_envelope.suite(), |                test_geom.suite(), | ||||||
|                test_gdal_geom.suite(), |                test_srs.suite(), | ||||||
|                test_gdal_srs.suite(), |  | ||||||
|                ] |                ] | ||||||
| 
 | 
 | ||||||
| def suite(): | def suite(): | ||||||
| @@ -1,10 +1,13 @@ | |||||||
| import os, os.path, unittest | import os, os.path, unittest | ||||||
| from django.contrib.gis.gdal import DataSource, Envelope, OGRException, OGRIndexError | from django.contrib.gis.gdal import DataSource, Envelope, OGRException, OGRIndexError | ||||||
| from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString | from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString | ||||||
|  | from django.contrib import gis | ||||||
| 
 | 
 | ||||||
| # Path for SHP files | # Path for SHP files | ||||||
| data_path = os.path.join(os.path.dirname(__file__), 'data') | data_path = os.path.join(os.path.dirname(gis.__file__), 'tests' + os.sep + 'data') | ||||||
| def get_ds_file(name, ext): | def get_ds_file(name, ext): | ||||||
|  |      | ||||||
|  | 
 | ||||||
|     return os.sep.join([data_path, name, name + '.%s' % ext]) |     return os.sep.join([data_path, name, name + '.%s' % ext]) | ||||||
| 
 | 
 | ||||||
| # Test SHP data source object | # Test SHP data source object | ||||||
							
								
								
									
										94
									
								
								django/contrib/gis/gdal/tests/test_envelope.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								django/contrib/gis/gdal/tests/test_envelope.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | |||||||
|  | import unittest | ||||||
|  | from django.contrib.gis.gdal import Envelope, OGRException | ||||||
|  |  | ||||||
|  | class TestPoint(object): | ||||||
|  |     def __init__(self, x, y): | ||||||
|  |         self.x = x | ||||||
|  |         self.y = y | ||||||
|  |  | ||||||
|  | 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, u'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)  | ||||||
|  |  | ||||||
|  | def suite(): | ||||||
|  |     s = unittest.TestSuite() | ||||||
|  |     s.addTest(unittest.makeSuite(EnvelopeTest)) | ||||||
|  |     return s | ||||||
|  |  | ||||||
|  | def run(verbosity=2): | ||||||
|  |     unittest.TextTestRunner(verbosity=verbosity).run(suite()) | ||||||
| @@ -7,7 +7,7 @@ from django.contrib.gis.tests.geometries import * | |||||||
| class OGRGeomTest(unittest.TestCase): | class OGRGeomTest(unittest.TestCase): | ||||||
|     "This tests the OGR Geometry." |     "This tests the OGR Geometry." | ||||||
| 
 | 
 | ||||||
|     def test00_geomtype(self): |     def test00a_geomtype(self): | ||||||
|         "Testing OGRGeomType object." |         "Testing OGRGeomType object." | ||||||
| 
 | 
 | ||||||
|         # OGRGeomType should initialize on all these inputs. |         # OGRGeomType should initialize on all these inputs. | ||||||
| @@ -22,9 +22,9 @@ class OGRGeomTest(unittest.TestCase): | |||||||
|             self.fail('Could not create an OGRGeomType object!') |             self.fail('Could not create an OGRGeomType object!') | ||||||
| 
 | 
 | ||||||
|         # Should throw TypeError on this input |         # Should throw TypeError on this input | ||||||
|         self.assertRaises(TypeError, OGRGeomType.__init__, 23) |         self.assertRaises(OGRException, OGRGeomType, 23) | ||||||
|         self.assertRaises(TypeError, OGRGeomType.__init__, 'fooD') |         self.assertRaises(OGRException, OGRGeomType, 'fooD') | ||||||
|         self.assertRaises(TypeError, OGRGeomType.__init__, 9) |         self.assertRaises(OGRException, OGRGeomType, 9) | ||||||
| 
 | 
 | ||||||
|         # Equivalence can take strings, ints, and other OGRGeomTypes |         # Equivalence can take strings, ints, and other OGRGeomTypes | ||||||
|         self.assertEqual(True, OGRGeomType(1) == OGRGeomType(1)) |         self.assertEqual(True, OGRGeomType(1) == OGRGeomType(1)) | ||||||
| @@ -38,9 +38,14 @@ class OGRGeomTest(unittest.TestCase): | |||||||
| 
 | 
 | ||||||
|         # Testing the Django field name equivalent property. |         # Testing the Django field name equivalent property. | ||||||
|         self.assertEqual('PointField', OGRGeomType('Point').django) |         self.assertEqual('PointField', OGRGeomType('Point').django) | ||||||
|         self.assertEqual(None, OGRGeomType('Unknown').django) |         self.assertEqual('GeometryField', OGRGeomType('Unknown').django) | ||||||
|         self.assertEqual(None, OGRGeomType('none').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 test01a_wkt(self): |     def test01a_wkt(self): | ||||||
|         "Testing WKT output." |         "Testing WKT output." | ||||||
|         for g in wkt_out: |         for g in wkt_out: | ||||||
| @@ -165,6 +170,12 @@ class OGRGeomTest(unittest.TestCase): | |||||||
| 
 | 
 | ||||||
|     def test07a_polygons(self): |     def test07a_polygons(self): | ||||||
|         "Testing Polygon objects." |         "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)') |         prev = OGRGeometry('POINT(0 0)') | ||||||
|         for p in polygons: |         for p in polygons: | ||||||
|             poly = OGRGeometry(p.wkt) |             poly = OGRGeometry(p.wkt) | ||||||
| @@ -9,42 +9,45 @@ def geo_suite(): | |||||||
|     """ |     """ | ||||||
|     from django.conf import settings |     from django.conf import settings | ||||||
|     from django.contrib.gis.tests.utils import mysql, oracle, postgis |     from django.contrib.gis.tests.utils import mysql, oracle, postgis | ||||||
|     from django.contrib.gis.gdal import HAS_GDAL |     from django.contrib.gis import gdal, utils | ||||||
|     from django.contrib.gis.utils import HAS_GEOIP |  | ||||||
|  |  | ||||||
|     # Tests that require use of a spatial database (e.g., creation of models) |     # The test suite. | ||||||
|     test_models = ['geoapp',] |     s = unittest.TestSuite() | ||||||
|  |  | ||||||
|     # Tests that do not require setting up and tearing down a spatial database. |     # Adding the GEOS tests. (__future__) | ||||||
|  |     #from django.contrib.gis.geos import tests as geos_tests | ||||||
|  |     #s.addTest(geos_tests.suite()) | ||||||
|  |  | ||||||
|  |     # Test apps that require use of a spatial database (e.g., creation of models) | ||||||
|  |     test_apps = ['geoapp', 'relatedapp'] | ||||||
|  |     if oracle or postgis: | ||||||
|  |         test_apps.append('distapp') | ||||||
|  |  | ||||||
|  |     # Tests that do not require setting up and tearing down a spatial database | ||||||
|  |     # and are modules in `django.contrib.gis.tests`. | ||||||
|     test_suite_names = [ |     test_suite_names = [ | ||||||
|         'test_geos', |         'test_geos', | ||||||
|         'test_measure', |         'test_measure', | ||||||
|         ] |         ] | ||||||
|     if HAS_GDAL: |  | ||||||
|         if oracle or postgis: |  | ||||||
|             test_models += ['distapp', 'layermap', 'relatedapp'] |  | ||||||
|         elif mysql: |  | ||||||
|             test_models += ['relatedapp', 'layermap'] |  | ||||||
|  |  | ||||||
|         test_suite_names += [ |     if gdal.HAS_GDAL: | ||||||
|             'test_gdal_driver', |         # These tests require GDAL. | ||||||
|             'test_gdal_ds', |         test_suite_names.append('test_spatialrefsys') | ||||||
|             'test_gdal_envelope', |         test_apps.append('layermap') | ||||||
|             'test_gdal_geom', |  | ||||||
|             'test_gdal_srs', |         # Adding the GDAL tests. | ||||||
|             'test_spatialrefsys', |         from django.contrib.gis.gdal import tests as gdal_tests | ||||||
|             ] |         s.addTest(gdal_tests.suite()) | ||||||
|     else: |     else: | ||||||
|         print >>sys.stderr, "GDAL not available - no GDAL tests will be run." |         print >>sys.stderr, "GDAL not available - no GDAL tests will be run." | ||||||
|  |  | ||||||
|     if HAS_GEOIP and hasattr(settings, 'GEOIP_PATH'): |     if utils.HAS_GEOIP and hasattr(settings, 'GEOIP_PATH'): | ||||||
|         test_suite_names.append('test_geoip') |         test_suite_names.append('test_geoip') | ||||||
|  |  | ||||||
|     s = unittest.TestSuite() |     for suite_name in test_suite_names: | ||||||
|     for test_suite in test_suite_names: |         tsuite = getattr(__import__('django.contrib.gis.tests', globals(), locals(), [suite_name]), suite_name) | ||||||
|         tsuite = getattr(__import__('django.contrib.gis.tests', globals(), locals(), [test_suite]),test_suite) |  | ||||||
|         s.addTest(tsuite.suite()) |         s.addTest(tsuite.suite()) | ||||||
|     return s, test_models |     return s, test_apps | ||||||
|  |  | ||||||
| def run_gis_tests(test_labels, **kwargs): | def run_gis_tests(test_labels, **kwargs): | ||||||
|     """ |     """ | ||||||
| @@ -80,9 +83,9 @@ def run_gis_tests(test_labels, **kwargs): | |||||||
|  |  | ||||||
|     # Creating the test suite, adding the test models to INSTALLED_APPS, and |     # Creating the test suite, adding the test models to INSTALLED_APPS, and | ||||||
|     # adding the model test suites to our suite package. |     # adding the model test suites to our suite package. | ||||||
|     gis_suite, test_models = geo_suite() |     gis_suite, test_apps = geo_suite() | ||||||
|     for test_model in test_models: |     for test_app in test_apps: | ||||||
|         module_name = 'django.contrib.gis.tests.%s' % test_model |         module_name = 'django.contrib.gis.tests.%s' % test_app | ||||||
|         if mysql: |         if mysql: | ||||||
|             test_module_name = 'tests_mysql' |             test_module_name = 'tests_mysql' | ||||||
|         else: |         else: | ||||||
| @@ -90,7 +93,7 @@ def run_gis_tests(test_labels, **kwargs): | |||||||
|         new_installed.append(module_name) |         new_installed.append(module_name) | ||||||
|  |  | ||||||
|         # Getting the model test suite |         # Getting the model test suite | ||||||
|         tsuite = getattr(__import__('django.contrib.gis.tests.%s' % test_model, globals(), locals(), [test_module_name]),  |         tsuite = getattr(__import__('django.contrib.gis.tests.%s' % test_app, globals(), locals(), [test_module_name]), | ||||||
|                          test_module_name) |                          test_module_name) | ||||||
|         gis_suite.addTest(tsuite.suite()) |         gis_suite.addTest(tsuite.suite()) | ||||||
|  |  | ||||||
| @@ -198,3 +201,25 @@ def run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[], suite= | |||||||
|  |  | ||||||
|     # Returning the total failures and errors |     # Returning the total failures and errors | ||||||
|     return len(result.failures) + len(result.errors) |     return len(result.failures) + len(result.errors) | ||||||
|  |  | ||||||
|  | # Class for creating a fake module with a run method.  This is for the | ||||||
|  | # GEOS and GDAL tests that were moved to their respective modules. | ||||||
|  | class _DeprecatedTestModule(object): | ||||||
|  |     def __init__(self, tests, mod): | ||||||
|  |         self.tests = tests | ||||||
|  |         self.mod = mod | ||||||
|  |  | ||||||
|  |     def run(self): | ||||||
|  |         from warnings import warn | ||||||
|  |         warn('This test module is deprecated because it has moved to ' \ | ||||||
|  |              '`django.contrib.gis.%s.tests` and will disappear in 1.2.' % | ||||||
|  |              self.mod, DeprecationWarning) | ||||||
|  |         self.tests.run() | ||||||
|  |  | ||||||
|  | #from django.contrib.gis.geos import tests as _tests | ||||||
|  | #test_geos = _DeprecatedTestModule(_tests, 'geos') | ||||||
|  |  | ||||||
|  | from django.contrib.gis.gdal import HAS_GDAL | ||||||
|  | if HAS_GDAL: | ||||||
|  |     from django.contrib.gis.gdal import tests as _tests | ||||||
|  |     test_gdal = _DeprecatedTestModule(_tests, 'gdal') | ||||||
|   | |||||||
| @@ -1,45 +0,0 @@ | |||||||
| 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()) |  | ||||||
		Reference in New Issue
	
	Block a user