Changeset 6686
- Timestamp:
- 11/17/07 15:38:36 (8 months ago)
- Files:
-
- django/branches/gis/django/contrib/gis/gdal/datasource.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/gdal/driver.py (modified) (5 diffs)
- django/branches/gis/django/contrib/gis/gdal/envelope.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/gdal/error.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/gdal/feature.py (modified) (6 diffs)
- django/branches/gis/django/contrib/gis/gdal/field.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/gdal/geometries.py (modified) (24 diffs)
- django/branches/gis/django/contrib/gis/gdal/geomtype.py (modified) (4 diffs)
- django/branches/gis/django/contrib/gis/gdal/__init__.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/gdal/layer.py (modified) (8 diffs)
- django/branches/gis/django/contrib/gis/gdal/libgdal.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/gdal/prototypes (added)
- django/branches/gis/django/contrib/gis/gdal/prototypes/ds.py (added)
- django/branches/gis/django/contrib/gis/gdal/prototypes/errcheck.py (added)
- django/branches/gis/django/contrib/gis/gdal/prototypes/generation.py (added)
- django/branches/gis/django/contrib/gis/gdal/prototypes/geom.py (added)
- django/branches/gis/django/contrib/gis/gdal/prototypes/__init__.py (added)
- django/branches/gis/django/contrib/gis/gdal/prototypes/srs.py (added)
- django/branches/gis/django/contrib/gis/gdal/srs.py (modified) (15 diffs)
- django/branches/gis/django/contrib/gis/tests/test_gdal_ds.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/tests/test_gdal_geom.py (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/gdal/datasource.py
r6639 r6686 1 # types and ctypes 2 from types import StringType 3 from ctypes import c_char_p, c_int, c_void_p, byref, string_at 1 """ 2 DataSource is a wrapper for the OGR Data Source object, which provides 3 an interface for reading vector geometry data from many different file 4 formats (including ESRI shapefiles). 5 6 When instantiating a DataSource object, use the filename of a 7 GDAL-supported data source. For example, a SHP file or a 8 TIGER/Line file from the government. 9 10 The ds_driver keyword is used internally when a ctypes pointer 11 is passed in directly. 12 13 Example: 14 ds = DataSource('/home/foo/bar.shp') 15 for layer in ds: 16 for feature in layer: 17 # Getting the geometry for the feature. 18 g = feature.geom 19 20 # Getting the 'description' field for the feature. 21 desc = feature['description'] 22 23 # We can also increment through all of the fields 24 # attached to this feature. 25 for field in feature: 26 # Get the name of the field (e.g. 'description') 27 nm = field.name 28 29 # Get the type (integer) of the field, e.g. 0 => OFTInteger 30 t = field.type 31 32 # Returns the value the field; OFTIntegers return ints, 33 # OFTReal returns floats, all else returns string. 34 val = field.value 35 """ 36 # ctypes prerequisites. 37 from ctypes import byref, c_void_p 4 38 5 39 # The GDAL C library, OGR exceptions, and the Layer object. 6 from django.contrib.gis.gdal. libgdal import lgdal7 from django.contrib.gis.gdal.error import OGRException, OGRIndexError , check_err40 from django.contrib.gis.gdal.driver import Driver 41 from django.contrib.gis.gdal.error import OGRException, OGRIndexError 8 42 from django.contrib.gis.gdal.layer import Layer 9 from django.contrib.gis.gdal.driver import Driver10 43 11 """ 12 DataSource is a wrapper for the OGR Data Source object, which provides 13 an interface for reading vector geometry data from many different file 14 formats (including ESRI shapefiles). 15 16 When instantiating a DataSource object, use the filename of a 17 GDAL-supported data source. For example, a SHP file or a 18 TIGER/Line file from the government. 19 20 The ds_driver keyword is used internally when a ctypes pointer 21 is passed in directly. 22 23 Example: 24 ds = DataSource('/home/foo/bar.shp') 25 for layer in ds: 26 for feature in layer: 27 # Getting the geometry for the feature. 28 g = feature.geom 29 30 # Getting the 'description' field for the feature. 31 desc = feature['description'] 32 33 # We can also increment through all of the fields 34 # attached to this feature. 35 for field in feature: 36 # Get the name of the field (e.g. 'description') 37 nm = field.name 38 39 # Get the type (integer) of the field, e.g. 0 => OFTInteger 40 t = field.type 41 42 # Returns the value the field; OFTIntegers return ints, 43 # OFTReal returns floats, all else returns string. 44 val = field.value 45 """ 44 # Getting the ctypes prototypes for the DataSource. 45 from django.contrib.gis.gdal.prototypes.ds import \ 46 destroy_ds, get_driver_count, register_all, open_ds, release_ds, \ 47 get_ds_name, get_layer, get_layer_count, get_layer_by_name 46 48 47 49 # For more information, see the OGR C API source code: … … 49 51 # 50 52 # The OGR_DS_* routines are relevant here. 51 52 53 class DataSource(object): 53 54 "Wraps an OGR Data Source object." 54 55 55 56 #### Python 'magic' routines #### 56 def __init__(self, ds_input, ds_driver=False ):57 def __init__(self, ds_input, ds_driver=False, write=False): 57 58 58 self._ds = None # Initially NULL 59 # DataSource pointer is initially NULL. 60 self._ptr = None 61 62 # The write flag. 63 if write: 64 self._write = 1 65 else: 66 self._write = 0 59 67 60 68 # Registering all the drivers, this needs to be done 61 69 # _before_ we try to open up a data source. 62 if not lgdal.OGRGetDriverCount() and not lgdal.OGRRegisterAll():70 if not get_driver_count() and not register_all(): 63 71 raise OGRException('Could not register all the OGR data source drivers!') 64 72 65 if isinstance(ds_input, StringType): 66 73 if isinstance(ds_input, basestring): 67 74 # The data source driver is a void pointer. 68 75 ds_driver = c_void_p() 69 76 70 77 # OGROpen will auto-detect the data source type. 71 ds = lgdal.OGROpen(c_char_p(ds_input), c_int(0), byref(ds_driver))78 ds = open_ds(ds_input, self._write, byref(ds_driver)) 72 79 elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p): 73 80 ds = ds_input 74 81 else: 75 raise OGRException('Invalid data source input type: %s' % str(type(ds_input)))82 raise OGRException('Invalid data source input type: %s' % type(ds_input)) 76 83 77 # Raise an exception if the returned pointer is NULL 78 if not ds: 79 self._ds = False 84 if bool(ds): 85 self._ptr = ds 86 self._driver = Driver(ds_driver) 87 else: 88 # Raise an exception if the returned pointer is NULL 80 89 raise OGRException('Invalid data source file "%s"' % ds_input) 81 else:82 self._ds = ds83 self._driver = Driver(ds_driver)84 90 85 91 def __del__(self): 86 " This releases the reference to the data source (destroying it if it's the only one)."87 if self._ ds: lgdal.OGRReleaseDataSource(self._ds)92 "Destroys this DataStructure object." 93 if self._ptr: destroy_ds(self._ptr) 88 94 89 95 def __iter__(self): 90 96 "Allows for iteration over the layers in a data source." 91 97 for i in xrange(self.layer_count): 92 yield self .__getitem__(i)98 yield self[i] 93 99 94 100 def __getitem__(self, index): 95 101 "Allows use of the index [] operator to get a layer at the index." 96 if isinstance(index, StringType):97 l = lgdal.OGR_DS_GetLayerByName(self._ds, c_char_p(index))102 if isinstance(index, basestring): 103 l = get_layer_by_name(self._ptr, index) 98 104 if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index) 99 el se:105 elif isinstance(index, int): 100 106 if index < 0 or index >= self.layer_count: 101 107 raise OGRIndexError('index out of range') 102 l = lgdal.OGR_DS_GetLayer(self._ds, c_int(index)) 108 l = get_layer(self._ptr, index) 109 else: 110 raise TypeError('Invalid index type: %s' % type(index)) 103 111 return Layer(l) 104 112 … … 120 128 def layer_count(self): 121 129 "Returns the number of layers in the data source." 122 return lgdal.OGR_DS_GetLayerCount(self._ds)130 return get_layer_count(self._ptr) 123 131 124 132 @property 125 133 def name(self): 126 134 "Returns the name of the data source." 127 return string_at(lgdal.OGR_DS_GetName(self._ds)) 128 135 return get_ds_name(self._ptr) django/branches/gis/django/contrib/gis/gdal/driver.py
r6639 r6686 1 # types and ctypes 2 from types import StringType 3 from ctypes import c_char_p, c_int, c_void_p, byref, string_at 4 5 # The GDAL C library, OGR exceptions, and the Layer object. 6 from django.contrib.gis.gdal.libgdal import lgdal 1 # prerequisites imports 2 from ctypes import c_void_p 7 3 from django.contrib.gis.gdal.error import OGRException 4 from django.contrib.gis.gdal.prototypes.ds import \ 5 get_driver, get_driver_by_name, get_driver_count, get_driver_name, register_all 8 6 9 7 # For more information, see the OGR C API source code: … … 11 9 # 12 10 # The OGR_Dr_* routines are relevant here. 13 14 11 class Driver(object): 15 12 "Wraps an OGR Data Source Driver." … … 23 20 } 24 21 25 def __init__(self, input, ptr=False):22 def __init__(self, dr_input): 26 23 "Initializes an OGR driver on either a string or integer input." 27 24 28 if isinstance( input, StringType):25 if isinstance(dr_input, basestring): 29 26 # If a string name of the driver was passed in 30 self._ dr = None # Initially NULL27 self._ptr = None # Initially NULL 31 28 self._register() 32 29 33 30 # Checking the alias dictionary (case-insensitive) to see if an alias 34 31 # exists for the given driver. 35 if input.lower() in self._alias:36 name = c_char_p(self._alias[input.lower()])32 if dr_input.lower() in self._alias: 33 name = self._alias[dr_input.lower()] 37 34 else: 38 name = c_char_p(input)35 name = dr_input 39 36 40 37 # Attempting to get the OGR driver by the string name. 41 dr = lgdal.OGRGetDriverByName(name)42 elif isinstance( input, int):38 dr = get_driver_by_name(name) 39 elif isinstance(dr_input, int): 43 40 self._register() 44 dr = lgdal.OGRGetDriver(c_int(input))45 elif isinstance( input, c_void_p):46 dr = input41 dr = get_driver(dr_input) 42 elif isinstance(dr_input, c_void_p): 43 dr = dr_input 47 44 else: 48 raise OGRException('Unrecognized input type for OGR Driver: %s' % str(type( input)))45 raise OGRException('Unrecognized input type for OGR Driver: %s' % str(type(dr_input))) 49 46 50 47 # Making sure we get a valid pointer to the OGR Driver 51 48 if not dr: 52 raise OGRException('Could not initialize OGR Driver on input: %s' % str( input))53 self._ dr = dr49 raise OGRException('Could not initialize OGR Driver on input: %s' % str(dr_input)) 50 self._ptr = dr 54 51 55 52 def __str__(self): 56 53 "Returns the string name of the OGR Driver." 57 return string_at(lgdal.OGR_Dr_GetName(self._dr))54 return get_driver_name(self._ptr) 58 55 59 56 def _register(self): … … 61 58 # Only register all if the driver count is 0 (or else all drivers 62 59 # will be registered over and over again) 63 if not self.driver_count and not lgdal.OGRRegisterAll():60 if not self.driver_count and not register_all(): 64 61 raise OGRException('Could not register all the OGR data source drivers!') 65 62 … … 68 65 def driver_count(self): 69 66 "Returns the number of OGR data source drivers registered." 70 return lgdal.OGRGetDriverCount() 71 72 def create_ds(self, **kwargs): 73 "Creates a data source using the keyword args as name value options." 74 raise NotImplementedError 75 # Getting the options string 76 #options = '' 77 #n_opts = len(kwargs) 78 #for i in xrange(n_opts): 79 # options += '%s=%s' % (str(k), str(v)) 80 # if i < n_opts-1: options += ',' 81 #opts = c_char_p(options) 82 83 84 85 67 return get_driver_count() django/branches/gis/django/contrib/gis/gdal/envelope.py
r6436 r6686 1 1 """ 2 2 The GDAL/OGR library uses an Envelope structure to hold the bounding 3 box information for a geometry. The envelope (bounding box) contains4 two pairs of coordinates, one for the lower left coordinate and one5 for the upper right coordinate:3 box information for a geometry. The envelope (bounding box) contains 4 two pairs of coordinates, one for the lower left coordinate and one 5 for the upper right coordinate: 6 6 7 +----------o Upper right; (max_x, max_y) 8 | | 9 | | 10 | | 11 Lower left (min_x, min_y) o----------+ 12 7 +----------o Upper right; (max_x, max_y) 8 | | 9 | | 10 | | 11 Lower left (min_x, min_y) o----------+ 13 12 """ 14 13 from ctypes import Structure, c_double … … 30 29 """ 31 30 The Envelope object is a C structure that contains the minimum and 32 maximum X, Y coordinates for a rectangle bounding box. The naming33 of the variables is compatible with the OGR Envelope structure.31 maximum X, Y coordinates for a rectangle bounding box. The naming 32 of the variables is compatible with the OGR Envelope structure. 34 33 """ 35 34 … … 37 36 """ 38 37 The initialization function may take an OGREnvelope structure, 4-element 39 tuple or list, or 4 individual arguments.38 tuple or list, or 4 individual arguments. 40 39 """ 41 40 django/branches/gis/django/contrib/gis/gdal/error.py
r6412 r6686 1 1 """ 2 This module houses the OGR & SRS Exception objects, and the3 check_err() routine which checks the status code returned by4 OGR methods.2 This module houses the OGR & SRS Exception objects, and the 3 check_err() routine which checks the status code returned by 4 OGR methods. 5 5 """ 6 7 # OGR & SRS Exceptions 6 #### OGR & SRS Exceptions #### 8 7 class OGRException(Exception): pass 9 8 class SRSException(Exception): pass … … 16 15 """ 17 16 silent_variable_failure = True 17 18 #### OGR error checking codes and routine #### 18 19 19 20 # OGR Error Codes … … 37 38 raise e, msg 38 39 else: 39 raise OGRException , 'Unknown error code: "%s"' % code40 raise OGRException('Unknown error code: "%s"' % code) django/branches/gis/django/contrib/gis/gdal/feature.py
r6639 r6686 1 # types and ctypes2 from types import StringType3 from ctypes import c_char_p, c_int, c_void_p, string_at4 5 1 # The GDAL C library, OGR exception, and the Field object 6 from django.contrib.gis.gdal.libgdal import lgdal7 2 from django.contrib.gis.gdal.error import OGRException, OGRIndexError 8 3 from django.contrib.gis.gdal.field import Field 9 4 from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType 10 5 from django.contrib.gis.gdal.srs import SpatialReference 6 7 # ctypes function prototypes 8 from django.contrib.gis.gdal.prototypes.ds import \ 9 destroy_feature, feature_equal, get_fd_geom_type, get_feat_geom_ref, \ 10 get_feat_name, get_feat_field_count, get_fid, get_field_defn, \ 11 get_field_index 12 from django.contrib.gis.gdal.prototypes.geom import clone_geom, get_geom_srs 13 from django.contrib.gis.gdal.prototypes.srs import clone_srs 11 14 12 15 # For more information, see the OGR C API source code: … … 19 22 #### Python 'magic' routines #### 20 23 def __init__(self, feat, fdefn): 21 "Needs a C pointer (Python integer in ctypes) in order to initialize." 22 self._feat = None # Initially NULL 23 self._fdefn = None 24 "Initializes on the pointers for the feature and the layer definition." 25 self._ptr = None # Initially NULL 24 26 if not feat or not fdefn: 25 27 raise OGRException('Cannot create OGR Feature, invalid pointer given.') 26 self._ feat= feat28 self._ptr = feat 27 29 self._fdefn = fdefn 28 30 29 31 def __del__(self): 30 32 "Releases a reference to this object." 31 if self._ feat: lgdal.OGR_F_Destroy(self._feat)33 if self._ptr: destroy_feature(self._ptr) 32 34 33 35 def __getitem__(self, index): 34 36 "Gets the Field at the specified index." 35 if isinstance(index, StringType):37 if isinstance(index, basestring): 36 38 i = self.index(index) 37 39 else: … … 39 41 raise OGRIndexError('index out of range') 40 42 i = index 41 return Field(lgdal.OGR_F_GetFieldDefnRef(self._feat, c_int(i)), 42 string_at(lgdal.OGR_F_GetFieldAsString(self._feat, c_int(i)))) 43 return Field(self._ptr, i) 43 44 44 45 def __iter__(self): 45 46 "Iterates over each field in the Feature." 46 47 for i in xrange(self.num_fields): 47 yield self .__getitem__(i)48 yield self[i] 48 49 49 50 def __len__(self): … … 57 58 def __eq__(self, other): 58 59 "Does equivalence testing on the features." 59 if lgdal.OGR_F_Equal(self._feat, other._feat): 60 return True 61 else: 62 return False 60 return bool(feature_equal(self._ptr, other._ptr)) 63 61 64 62 #### Feature Properties #### … … 66 64 def fid(self): 67 65 "Returns the feature identifier." 68 return lgdal.OGR_F_GetFID(self._feat)66 return get_fid(self._ptr) 69 67 70 68 @property 71 69 def layer_name(self): 72 70 "Returns the name of the layer for the feature." 73 return string_at(lgdal.OGR_FD_GetName(self._fdefn))71 return get_feat_name(self._fdefn) 74 72 75 73 @property 76 74 def num_fields(self): 77 75 "Returns the number of fields in the Feature." 78 return lgdal.OGR_F_GetFieldCount(self._feat)76 return get_feat_field_count(self._ptr) 79 77 80 78 @property 81 79 def fields(self): 82 80 "Returns a list of fields in the Feature." 83 return [ string_at(lgdal.OGR_Fld_GetNameRef(lgdal.OGR_FD_GetFieldDefn(self._fdefn, i))) 84 for i in xrange(self.num_fields) ] 81 return [get_field_name(get_field_defn(self._fdefn, i)) 82 for i in xrange(self.num_fields)] 83 85 84 @property 86 85 def geom(self): 87 86 "Returns the OGR Geometry for this Feature." 88 87 # Retrieving the geometry pointer for the feature. 89 geom_ptr = lgdal.OGR_F_GetGeometryRef(self._feat) 90 if not geom_ptr: 91 raise OGRException('Cannot retrieve Geometry from the feature.') 88 geom_ptr = get_feat_geom_ref(self._ptr) 92 89 93 90 # Attempting to retrieve the Spatial Reference for the geometry. 94 srs_ptr = lgdal.OSRClone(lgdal.OGR_G_GetSpatialReference(geom_ptr))95 if srs_ptr:96 srs = SpatialReference( srs_ptr, 'ogr')97 e lse:91 try: 92 srs_ptr = get_geom_srs(geom_ptr) 93 srs = SpatialReference(clone_srs(srs_ptr)) 94 except OGRException: 98 95 srs = None 99 100 # Geometry is cloned so the feature isn't invalidated. 101 return OGRGeometry(c_void_p(lgdal.OGR_G_Clone(geom_ptr)), srs) 102 96 # Geometry is cloned so the feature isn't invalidated. 97 return OGRGeometry(clone_geom(geom_ptr), srs) 98 103 99 @property 104 100 def geom_type(self): 105 101 "Returns the OGR Geometry Type for this Feture." 106 return OGRGeomType( lgdal.OGR_FD_GetGeomType(self._fdefn))102 return OGRGeomType(get_fd_geom_type(self._fdefn)) 107 103 108 104 #### Feature Methods #### … … 114 110 """ 115 111 field_name = getattr(field, 'name', field) 116 return self .__getitem__(field_name).value112 return self[field_name].value 117 113 118 114 def index(self, field_name): 119 115 "Returns the index of the given field name." 120 i = lgdal.OGR_F_GetFieldIndex(self._feat, c_char_p(field_name))116 i = get_field_index(self._ptr, field_name) 121 117 if i < 0: raise OGRIndexError('invalid OFT field name given: "%s"' % field_name) 122 118 return i 123 124 def clone(self):125 "Clones this Feature."126 return Feature(lgdal.OGR_F_Clone(self._feat))django/branches/gis/django/contrib/gis/gdal/field.py
r6639 r6686 1 from ctypes import string_at2 from d jango.contrib.gis.gdal.libgdal import lgdal1 from ctypes import byref, c_int 2 from datetime import date, datetime, time 3 3 from django.contrib.gis.gdal.error import OGRException 4 from django.contrib.gis.gdal.prototypes.ds import \ 5 get_feat_field_defn, get_field_as_datetime, get_field_as_double, \ 6 get_field_as_integer, get_field_as_string, get_field_name, get_field_precision, \ 7 get_field_type, get_field_type_name, get_field_width 4 8 5 9 # For more information, see the OGR C API source code: … … 11 15 12 16 #### Python 'magic' routines #### 13 def __init__(self, fld, val=''): 14 "Needs a C pointer (Python integer in ctypes) in order to initialize." 15 self._fld = None # Initially NULL 16 17 def __init__(self, feat, index): 18 """ 19 Initializes on the feature pointer and the integer index of 20 the field within the feature. 21 """ 22 # Setting the feature pointer and index. 23 self._feat = feat 24 self._index = index 25 26 # Getting the pointer for this field. 27 fld = get_feat_field_defn(feat, index) 17 28 if not fld: 18 29 raise OGRException('Cannot create OGR Field, invalid pointer given.') 19 self._fld = fld 20 self._val = val 30 self._ptr = fld 21 31 22 32 # Setting the class depending upon the OGR Field Type (OFT) 23 33 self.__class__ = FIELD_CLASSES[self.type] 24 34 35 # OFTReal with no precision should be an OFTInteger. 36 if isinstance(self, OFTReal) and self.precision == 0: 37 self.__class__ = OFTInteger 38 25 39 def __str__(self): 26 40 "Returns the string representation of the Field." 27 return '%s (%s)' % (self.name, self.value) 41 return str(self.value).strip() 42 43 #### Field Methods #### 44 def as_double(self): 45 "Retrieves the Field's value as a double (float)." 46 return get_field_as_double(self._feat, self._index) 47 48 def as_int(self): 49 "Retrieves the Field's value as an integer." 50 return get_field_as_integer(self._feat, self._index) 51 52 def as_string(self): 53 "Retrieves the Field's value as a string." 54 return get_field_as_string(self._feat, self._index) 55 56 def as_datetime(self): 57 "Retrieves the Field's value as a tuple of date & time components." 58 yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)] 59 status = get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd), 60 byref(hh), byref(mn), byref(ss), byref(tz)) 61 if status: 62 return (yy, mm, dd, hh, mn, ss, tz) 63 else: 64 raise OGRException('Unable to retrieve date & time information from the field.') 28 65 29 66 #### Field Properties #### 30 67 @property 31 68 def name(self): 32 "Returns the name of the field." 33 return string_at(lgdal.OGR_Fld_GetNameRef(self._fld)) 69 "Returns the name of this Field." 70 return get_field_name(self._ptr) 71 72 @property 73 def precision(self): 74 "Returns the precision of this Field." 75 return get_field_precision(self._ptr) 34 76 35 77 @property 36 78 def type(self): 37 "Returns the type of this field." 38 return lgdal.OGR_Fld_GetType(self._fld) 79 "Returns the OGR type of this Field." 80 return get_field_type(self._ptr) 81 82 @property 83 def type_name(self): 84 "Return the OGR field type name for this Field." 85 return get_field_type_name(self.type) 39 86 40 87 @property 41 88 def value(self): 42 "Returns the value of this type of field." 43 return self._val 89 "Returns the value of this Field." 90 # Default is to get the field as a string. 91 return self.as_string() 44 92 45 # The Field sub-classes for each OGR Field type. 93 @property 94 def width(self): 95 "Returns the width of this Field." 96 return get_field_width(self._ptr) 97 98 ### The Field sub-classes for each OGR Field type. ### 46 99 class OFTInteger(Field): 47 100 @property 48 101 def value(self): 49 102 "Returns an integer contained in this field." 50 try: 51 return int(self._val) 52 except ValueError: 53 return None 54 class OFTIntegerList(Field): pass 103 return self.as_int() 104 105 @property 106 def type(self): 107 """ 108 GDAL uses OFTReals to represent OFTIntegers in created 109 shapefiles -- forcing the type here since the underlying field 110 type may actually be OFTReal. 111 """ 112 return 0 55 113 56 114 class OFTReal(Field): … … 58 116 def value(self): 59 117 "Returns a float contained in this field." 60 try: 61 return float(self._val) 62 except ValueError: 63 return None 118 return self.as_double() 119 120 # String & Binary fields, just subclasses 121 class OFTString(Field): pass 122 class OFTWideString(Field): pass 123 class OFTBinary(Field): pass 124 125 # OFTDate, OFTTime, OFTDateTime fields. 126 class OFTDate(Field): 127 @property 128 def value(self): 129 "Returns a Python `date` object for the OFTDate field." 130 yy, mm, dd, hh, mn, ss, tz = self.as_datetime() 131 return date(yy.value, mm.value, dd.value) 132 133 class OFTDateTime(Field): 134 @property 135 def value(self): 136 "Returns a Python `datetime` object for this OFTDateTime field." 137 yy, mm, dd, hh, mn, ss, tz = self.as_datetime() 138 # TODO: Adapt timezone information. 139 # See http://lists.maptools.org/pipermail/gdal-dev/2006-February/007990.html 140 # The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous), 141 # 100=GMT, 104=GMT+1, 80=GMT-5, etc. 142 return datetime(yy.value, mm.value, dd.value, hh.value, mn.value, ss.value) 143 144 class OFTTime(Field): 145 @property 146 def value(self): 147 "Returns a Python `time` object for this OFTTime field." 148 yy, mm, dd, hh, mn, ss, tz = self.as_datetime() 149 return time(hh.value, mn.value, ss.value) 150 151 # List fields are also just subclasses 152 class OFTIntegerList(Field): pass 64 153 class OFTRealList(Field): pass 65 66 class OFTString(Field):67 def __str__(self):68 return '%s ("%s")' % (self.name, self.value)69 70 154 class OFTStringList(Field): pass 71 class OFTWideString(Field): pass72 155 class OFTWideStringList(Field): pass 73 class OFTBinary(Field): pass74 class OFTDate(Field): pass75 class OFTTime(Field): pass76 class OFTDateTime(Field): pass77 156 78 157 # Class mapping dictionary for OFT Types django/branches/gis/django/contrib/gis/gdal/geometries.py
r6464 r6686 1 1 """ 2 The OGRGeometry is a wrapper for using the OGR Geometry class3 (see http://www.gdal.org/ogr/classOGRGeometry.html). OGRGeometry4 may be instantiated when reading geometries from OGR Data Sources5 (e.g. SHP files), or when given OGC WKT (a string).6 7 While the 'full' API is not present yet, the API is "pythonic" unlike8 the traditional and "next-generation" OGR Python bindings. One major9 advantage OGR Geometries have over their GEOS counterparts is support10 for spatial reference systems and their transformation.11 12 Example:13 >>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference14 >>> wkt1, wkt2 = 'POINT(-90 30)', 'POLYGON((0 0, 5 0, 5 5, 0 5)'15 >>> pnt = OGRGeometry(wkt1)16 >>> print pnt17 POINT (-90 30)18 >>> mpnt = OGRGeometry(OGRGeomType('MultiPoint'), SpatialReference('WGS84'))19 >>> mpnt.add(wkt1)20 >>> mpnt.add(wkt1)21 >>> print mpnt22 MULTIPOINT (-90 30,-90 30)23 >>> print mpnt.srs.name24 WGS 8425 >>> print mpnt.srs.proj26 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs27 >>> mpnt.transform_to(SpatialReference('NAD27'))28 >>> print mpnt.proj29 +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs30 >>> print mpnt31 MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641)32 2 The OGRGeometry is a wrapper for using the OGR Geometry class 3 (see http://www.gdal.org/ogr/classOGRGeometry.html). OGRGeometry 4 may be instantiated when reading geometries from OGR Data Sources 5 (e.g. SHP files), or when given OGC WKT (a string). 6 7 While the 'full' API is not present yet, the API is "pythonic" unlike 8 the traditional and "next-generation" OGR Python bindings. One major 9 advantage OGR Geometries have over their GEOS counterparts is support 10 for spatial reference systems and their transformation. 11 12 Example: 13 >>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference 14 >>> wkt1, wkt2 = 'POINT(-90 30)', 'POLYGON((0 0, 5 0, 5 5, 0 5)' 15 >>> pnt = OGRGeometry(wkt1) 16 >>> print pnt 17 POINT (-90 30) 18 >>> mpnt = OGRGeometry(OGRGeomType('MultiPoint'), SpatialReference('WGS84')) 19 >>> mpnt.add(wkt1) 20 >>> mpnt.add(wkt1) 21 >>> print mpnt 22 MULTIPOINT (-90 30,-90 30) 23 >>> print mpnt.srs.name 24 WGS 84 25 >>> print mpnt.srs.proj 26 +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs 27 >>> mpnt.transform_to(SpatialReference('NAD27')) 28 >>> print mpnt.proj 29 +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs 30 >>> print mpnt 31 MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641) 32 33 33 The OGRGeomType class is to make it easy to specify an OGR geometry type: 34 >>> from django.contrib.gis.gdal import OGRGeomType35 >>> gt1 = OGRGeomType(3) # Using an integer for the type36 >>> gt2 = OGRGeomType('Polygon') # Using a string37 >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive38 >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects39 True34 >>> from django.contrib.gis.gdal import OGRGeomType 35 >>> gt1 = OGRGeomType(3) # Using an integer for the type 36 >>> gt2 = OGRGeomType('Polygon') # Using a string 37 >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive 38 >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects 39 True 40 40 """ 41 # Python library imports41 # Python library requisites. 42 42 import re, sys 43 from binascii import a2b_hex , b2a_hex44 from ctypes import byref, create_string_buffer, string_at, c_char_p, c_double, c_int, c_void_p43 from binascii import a2b_hex 44 from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p 45 45 from types import BufferType, IntType, StringType, UnicodeType 46 46 47 47 # Getting GDAL prerequisites 48 from django.contrib.gis.gdal.libgdal import lgdal49 48 from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope 50 from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError49 from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException 51 50 from django.contrib.gis.gdal.geomtype import OGRGeomType 52 51 from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform 52 53 # Getting the ctypes prototype functions that interface w/the GDAL C library. 54 from django.contrib.gis.gdal.prototypes.geom import * 55 from django.contrib.gis.gdal.prototypes.srs import clone_srs 53 56 54 57 # For more information, see the OGR C API source code: … … 57 60 # The OGR_G_* routines are relevant here. 58 61 59 #### ctypes prototypes for functions that return double values #### 60 def pnt_func(f): 61 "For accessing point information." 62 f.restype = c_double 63 f.argtypes = [c_void_p, c_int] 64 return f 65 # GetX, GetY, GetZ all return doubles. 66 getx = pnt_func(lgdal.OGR_G_GetX) 67 gety = pnt_func(lgdal.OGR_G_GetY) 68 getz = pnt_func(lgdal.OGR_G_GetZ) 69 70 # GetArea returns a double. 71 get_area = lgdal.OGR_G_GetArea 72 get_area.restype = c_double 73 get_area.argtypes = [c_void_p] 74 75 # Regular expression for determining whether the input is HEXEWKB. 62 # Regular expressions for recognizing HEXEWKB and WKT. 76 63 hex_regex = re.compile(r'^[0-9A-F]+$', re.I) 64 wkt_regex = re.compile(r'^(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+$', re.I) 77 65 78 66 #### OGRGeometry Class #### … … 83 71 "Initializes Geometry on either WKT or an OGR pointer as input." 84 72 85 self._ g= c_void_p(None) # Initially NULL73 self._ptr = c_void_p(None) # Initially NULL 86 74 87 75 # Checking if unicode … … 95 83 96 84 if isinstance(geom_input, StringType): 97 # First, trying the input as WKT 98 buf = c_char_p(geom_input) 99 g = c_void_p() 100 101 try: 102 check_err(lgdal.OGR_G_CreateFromWkt(byref(buf), c_void_p(), byref(g))) 103 except OGRException: 104 try: 105 # Seeing if the input is a valid short-hand string 106 ogr_t = OGRGeomType(geom_input) 107 g = lgdal.OGR_G_CreateGeometry(ogr_t.num) 108 except: 109 raise OGRException('Could not initialize OGR Geometry from: %s' % geom_input) 85 m = wkt_regex.match(geom_input) 86 if m: 87 if m.group('type').upper() == 'LINEARRING': 88 # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT. 89 # See http://trac.osgeo.org/gdal/ticket/1992. 90 g = create_geom(OGRGeomType(m.group('type')).num) 91 import_wkt(g, byref(c_char_p(geom_input))) 92 else: 93 g = from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p())) 94 else: 95 # Seeing if the input is a valid short-hand string 96 # (e.g., 'Point', 'POLYGON'). 97 ogr_t = OGRGeomType(geom_input) 98 g = create_geom(OGRGeomType(geom_input).num) 110 99 elif isinstance(geom_input, BufferType): 111 100 # WKB was passed in 112 g = c_void_p() 113 check_err(lgdal.OGR_G_CreateFromWkb(c_char_p(str(geom_input)), c_void_p(), byref(g), len(geom_input))) 101 g = from_wkb(str(geom_input), None, byref(c_void_p()), len(geom_input)) 114 102 elif isinstance(geom_input, OGRGeomType): 115 103 # OGRGeomType was passed in, an empty geometry will be created. 116 g = lgdal.OGR_G_CreateGeometry(geom_input.num)104 g = create_geom(geom_input.num) 117 105 elif isinstance(geom_input, c_void_p): 118 106 #
