Django

Code

Show
Ignore:
Timestamp:
07/21/08 20:10:59 (5 months ago)
Author:
jbronn
Message:

gis: gdal: Features may now be fetched from OGR layers that do not support random access reading, but no more negative indexes are allowed; cleaned up OGRGeomType; moved test vector data into its own directory.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/gdal/error.py

    r6686 r8034  
    2626                6 : (OGRException, 'OGR failure.'), 
    2727                7 : (SRSException, 'Unsupported SRS.'), 
     28                8 : (OGRException, 'Invalid handle.'), 
    2829                } 
    2930OGRERR_NONE = 0 
  • django/branches/gis/django/contrib/gis/gdal/geometries.py

    r7767 r8034  
    202202    def geom_type(self): 
    203203        "Returns the Type for this Geometry." 
    204         return OGRGeomType(get_geom_type(self._ptr)) 
     204        try: 
     205            return OGRGeomType(get_geom_type(self._ptr)) 
     206        except OGRException: 
     207            # VRT datasources return an invalid geometry type 
     208            # number, but a valid name -- we'll try that instead. 
     209            # See: http://trac.osgeo.org/gdal/ticket/2491 
     210            return OGRGeomType(get_geom_name(self._ptr)) 
    205211 
    206212    @property 
  • django/branches/gis/django/contrib/gis/gdal/geomtype.py

    r7665 r8034  
    55    "Encapulates OGR Geometry Types." 
    66 
    7     # Ordered array of acceptable strings and their corresponding OGRwkbGeometryType 
    8     __ogr_str = ['Unknown', 'Point', 'LineString', 'Polygon', 'MultiPoint', 
    9                  'MultiLineString', 'MultiPolygon', 'GeometryCollection', 
    10                  'LinearRing'] 
    11     __ogr_int = [0, 1, 2, 3, 4, 5, 6, 7, 101] 
     7    # Dictionary of acceptable OGRwkbGeometryType s and their string names. 
     8    _types = {0 : 'Unknown', 
     9              1 : 'Point', 
     10              2 : 'LineString', 
     11              3 : 'Polygon', 
     12              4 : 'MultiPoint', 
     13              5 : 'MultiLineString', 
     14              6 : 'MultiPolygon', 
     15              7 : 'GeometryCollection', 
     16              100 : 'None', 
     17              101 : 'LinearRing', 
     18              } 
     19    # Reverse type dictionary, keyed by lower-case of the name. 
     20    _str_types = dict([(v.lower(), k) for k, v in _types.items()]) 
    1221 
    1322    def __init__(self, type_input): 
    1423        "Figures out the correct OGR Type based upon the input." 
    1524        if isinstance(type_input, OGRGeomType): 
    16             self._index = type_input._index 
     25            num = type_input.num 
    1726        elif isinstance(type_input, basestring): 
    18             idx = self._has_str(self.__ogr_str, type_input
    19             if idx == None: 
     27            num = self._str_types.get(type_input.lower(), None
     28            if num is None: 
    2029                raise OGRException('Invalid OGR String Type "%s"' % type_input) 
    21             self._index = idx 
    2230        elif isinstance(type_input, int): 
    23             if not type_input in self.__ogr_int
     31            if not type_input in self._types
    2432                raise OGRException('Invalid OGR Integer Type: %d' % type_input) 
    25             self._index =  self.__ogr_int.index(type_input) 
     33            num = type_input 
    2634        else: 
    2735            raise TypeError('Invalid OGR input type given.') 
     36         
     37        # Setting the OGR geometry type number. 
     38        self.num = num 
    2839 
    2940    def __str__(self): 
    30         "Returns a short-hand string form of the OGR Geometry type." 
    31         return self.__ogr_str[self._index] 
     41        "Returns the value of the name property." 
     42        return self.name 
    3243 
    3344    def __eq__(self, other): 
     
    3748        """ 
    3849        if isinstance(other, OGRGeomType): 
    39             return self._index == other._index 
     50            return self.num == other.num 
    4051        elif isinstance(other, basestring): 
    41             idx = self._has_str(self.__ogr_str, other) 
    42             if not (idx == None): return self._index == idx 
     52            return self.name.lower() == other.lower() 
     53        elif isinstance(other, int): 
     54            return self.num == other 
     55        else: 
    4356            return False 
    44         elif isinstance(other, int): 
    45             if not other in self.__ogr_int: return False 
    46             return self.__ogr_int.index(other) == self._index 
    47         else: 
    48             raise TypeError('Cannot compare with type: %s' % str(type(other))) 
    4957 
    5058    def __ne__(self, other): 
    5159        return not (self == other) 
    5260 
    53     def _has_str(self, arr, s): 
    54         "Case-insensitive search of the string array for the given pattern." 
    55         s_low = s.lower() 
    56         for i in xrange(len(arr)): 
    57             if s_low == arr[i].lower(): return i 
    58         return None 
     61    @property 
     62    def name(self): 
     63        "Returns a short-hand string form of the OGR Geometry type." 
     64        return self._types[self.num] 
    5965 
    6066    @property 
    6167    def django(self): 
    6268        "Returns the Django GeometryField for this OGR Type." 
    63         s = self.__ogr_str[self._index] 
    64         if s in ('Unknown', 'LinearRing'): 
     69        s = self.name 
     70        if s in ('Unknown', 'LinearRing', 'None'): 
    6571            return None 
    6672        else: 
    6773            return s + 'Field' 
    68  
    69     @property 
    70     def num(self): 
    71         "Returns the OGRwkbGeometryType number for the OGR Type." 
    72         return self.__ogr_int[self._index] 
  • django/branches/gis/django/contrib/gis/gdal/layer.py

    r6992 r8034  
    1515    get_field_count, get_field_defn, get_field_name, get_field_precision, \ 
    1616    get_field_width, get_field_type, get_layer_defn, get_layer_srs, \ 
    17     get_next_feature, reset_reading 
     17    get_next_feature, reset_reading, test_capability 
    1818from django.contrib.gis.gdal.prototypes.srs import clone_srs 
    1919 
     
    3333        self._ptr = layer_ptr 
    3434        self._ldefn = get_layer_defn(self._ptr) 
     35        # Does the Layer support random reading? 
     36        self._random_read = self.test_capability('RandomRead') 
    3537 
    3638    def __getitem__(self, index): 
    3739        "Gets the Feature at the specified index." 
    38         if not isinstance(index, (slice, int)): 
    39             raise TypeError 
    40         end = self.num_feat 
    41         if isinstance(index,int): 
    42             # An integer index was given 
    43             if index < 0: 
    44                 index = end - index 
    45             if index < 0 or index >= self.num_feat: 
    46                 raise OGRIndexError('index out of range') 
     40        if isinstance(index, (int, long)): 
     41            # An integer index was given -- we cannot do a check based on the 
     42            # number of features because the beginning and ending feature IDs 
     43            # are not guaranteed to be 0 and len(layer)-1, respectively. 
     44            if index < 0: raise OGRIndexError('Negative indices are not allowed on OGR Layers.') 
    4745            return self._make_feature(index) 
    48         else:  
     46        elif isinstance(index, slice): 
    4947            # A slice was given 
    50             start, stop, stride = index.indices(end) 
    51             return [self._make_feature(offset) for offset in range(start,stop,stride)] 
     48            start, stop, stride = index.indices(self.num_feat) 
     49            return [self._make_feature(fid) for fid in xrange(start, stop, stride)] 
     50        else: 
     51            raise TypeError('Integers and slices may only be used when indexing OGR Layers.') 
    5252 
    5353    def __iter__(self): 
     
    5555        # ResetReading() must be called before iteration is to begin. 
    5656        reset_reading(self._ptr) 
    57         for i in range(self.num_feat): 
     57        for i in xrange(self.num_feat): 
    5858            yield Feature(get_next_feature(self._ptr), self._ldefn) 
    5959 
     
    6666        return self.name 
    6767 
    68     def _make_feature(self, offset): 
    69         "Helper routine for __getitem__ that makes a feature from an offset." 
    70         return Feature(get_feature(self._ptr, offset), self._ldefn) 
     68    def _make_feature(self, feat_id): 
     69        """ 
     70        Helper routine for __getitem__ that constructs a Feature from the given 
     71        Feature ID.  If the OGR Layer does not support random-access reading, 
     72        then each feature of the layer will be incremented through until the 
     73        a Feature is found matching the given feature ID. 
     74        """ 
     75        if self._random_read: 
     76            # If the Layer supports random reading, return. 
     77            try: 
     78                return Feature(get_feature(self._ptr, feat_id), self._ldefn) 
     79            except OGRException: 
     80                pass 
     81        else: 
     82            # Random access isn't supported, have to increment through 
     83            # each feature until the given feature ID is encountered. 
     84            for feat in self: 
     85                if feat.fid == feat_id: return feat 
     86        # Should have returned a Feature, raise an OGRIndexError.     
     87        raise OGRIndexError('Invalid feature id: %s.' % feat_id) 
    7188 
    7289    #### Layer properties #### 
     
    159176        else: 
    160177            return [feat.geom for feat in self] 
     178 
     179    def test_capability(self, capability): 
     180        """ 
     181        Returns a bool indicating whether the this Layer supports the given 
     182        capability (a string).  Valid capability strings include: 
     183          'RandomRead', 'SequentialWrite', 'RandomWrite', 'FastSpatialFilter', 
     184          'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions', 
     185          'DeleteFeature', and 'FastSetNextByIndex'. 
     186        """ 
     187        return bool(test_capability(self._ptr, capability)) 
  • django/branches/gis/django/contrib/gis/gdal/prototypes/ds.py

    r6914 r8034  
    3838get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p]) 
    3939reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False) 
     40test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p]) 
    4041 
    4142### Feature Definition Routines ###