/[thuban]/branches/WIP-pyshapelib-bramz/Extensions/ogr/ogrshapes.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Extensions/ogr/ogrshapes.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/thuban/Extensions/ogr/ogrshapes.py revision 2435 by nhueffme, Tue Dec 7 16:44:51 2004 UTC branches/WIP-pyshapelib-bramz/Extensions/ogr/ogrshapes.py revision 2734 by bramz, Thu Mar 1 12:42:59 2007 UTC
# Line 1  Line 1 
1  # Copyright (C) 2004 by Intevation GmbH  # Copyright (C) 2004 by Intevation GmbH     vim:encoding=latin-1:
2  # Authors:  # Authors:
3  # Nina H�ffmeyer <[email protected]>  # Nina H�ffmeyer <[email protected]>
4  #  #
# Line 17  except ImportError: Line 17  except ImportError:
17      ogr = None      ogr = None
18    
19  import os  import os
 import weakref  
 from math import ceil, log  
20    
21  from Thuban import _  from Thuban import _
22  from Thuban.Model import table  from Thuban.Model import table
23    from Thuban.Model import transientdb
24    from Thuban.Model.transientdb import  TransientDatabase
25    
26  from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT  from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
27  from Thuban.Model.data import RAW_PYTHON, RAW_SHAPEFILE, RAW_WKT  from Thuban.Model.data import RAW_PYTHON, RAW_SHAPEFILE, RAW_WKT
28    from Thuban.Model.data import FileShapeStore
 # Raw data in ogr format  
 RAW_OGRSHAPES = "RAW_OGRSHAPES"  
   
   
29    
30  def has_ogr_support():  def has_ogr_support():
31      """Return whether this Thuban instance supports ogr file formats      """Return whether this Thuban instance supports ogr file formats
# Line 40  def has_ogr_support(): Line 36  def has_ogr_support():
36      return ogr is not None      return ogr is not None
37    
38  if ogr is not None:  if ogr is not None:
39      # mapping from ogr-lib shapetype and table constants to our constants      SHAPETYPE_UNKNOWN = ogr.wkbUnknown
40        SHAPETYPE_GEOMCOLL = ogr.wkbGeometryCollection
41        SHAPETYPE_NONE = ogr.wkbNone
42    
43        # mapping from ogr-lib shapetypes and table constants to our constants
44      ogrlib_shapetypes = {ogr.wkbPolygon: SHAPETYPE_POLYGON,      ogrlib_shapetypes = {ogr.wkbPolygon: SHAPETYPE_POLYGON,
45                         ogr.wkbLineString: SHAPETYPE_ARC,                  ogr.wkbLineString: SHAPETYPE_ARC,
46                         ogr.wkbPoint: SHAPETYPE_POINT}                  ogr.wkbPoint: SHAPETYPE_POINT,
47                    ogr.wkbUnknown: SHAPETYPE_UNKNOWN,
48                    ogr.wkbNone: SHAPETYPE_NONE,
49                    ogr.wkbGeometryCollection: SHAPETYPE_GEOMCOLL}
50    
51      fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,      fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,
52          ogr.OFTInteger: table.FIELDTYPE_INT,                  ogr.OFTInteger: table.FIELDTYPE_INT,
53          ogr.OFTReal: table.FIELDTYPE_DOUBLE}                  ogr.OFTReal: table.FIELDTYPE_DOUBLE}
54    
55    else:
56        ogrlib_shapetypes = {}
57        fieldtype_map = {}
58        SHAPETYPE_UNKNOWN = 0
59        SHAPETYPE_GEOMCOLL = 7
60        SHAPETYPE_NONE = 100
61    
62    
63  class OGRShape:  class OGRShape:
64        """Represent one shape of an OGRShapeStore
65        """
66    
67        def __init__(self, shapestore, shape):
68            """Initialize the shape object.
69    
70            shapestore should be an instance of OGRShapeStore,
71            shape should be an instance of an OGRFeature.
72            """
73            self.ogrlayer = shapestore.ogrlayer
74            id_column = shapestore.Id_column()
75            self.feature = shape
76            if id_column is None:
77                self.shapeid = self.feature.GetFID()
78            else:
79                self.shapeid = self.feature.GetField(id_column)
80            self.geom = self.feature.GetGeometryRef()
81            if self.geom:
82                self.shapetype = self.geom.GetGeometryType()
83                self.bbox = self._compute_bbox()
84                self.points = self._points()
85            else:
86                self.shapetype = ogr.wkbNone
87                self.bbox = None
88                self.points = [[]]
89            try:
90                self.shapetype = ogrlib_shapetypes[self.shapetype]
91            except:
92                self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
93    
94            self.geoms = self._geoms()
95    
96      """Represent one shape of an OGRShapeStore"""      def _geoms(self):
97            """Return a list of geometry objects.
98    
99      def __init__(self, ogrlayer, shapeid):          If the shape is a geometry collection, all contained geometry
100          self.ogrlayer = ogrlayer          objects are stored to the list as OGRGeometry objects.
101          self.shapeid = shapeid          """
102            geoms = []
103            if self.shapetype == SHAPETYPE_GEOMCOLL:
104                for i in range(self.geom.GetGeometryCount()):
105                    geoms.append(OGRGeometry(self, self.geom, i))
106            return geoms
107    
108        def _compute_bbox(self):
109            """
110            Compute the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
111            """
112            minx, maxx, miny, maxy = self.geom.GetEnvelope()
113            return (minx, miny, maxx, maxy)
114    
115      def compute_bbox(self):      def compute_bbox(self):
116          """          """
117          Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)          Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
118          """          """
119          shape = self.ogrlayer.GetFeature(self.shapeid)          return self.bbox
         geom = shape.GetGeometryRef()  
         minx, maxx, miny, maxy = geom.GetEnvelope()  
         return (minx, miny, maxx, maxy)  
120    
121      def ShapeID(self):      def ShapeID(self):
122            """Return the feature id of this shape.
123            """
124          return self.shapeid          return self.shapeid
125    
     # diese Methode funktioniert vielleicht noch nicht f�r andere Formate als shp  
     #(wenn ein polygon aus mehreren  
     # Ringen besteht o.�., hat ein Geometry-Objekt mehr als einen GeometryRef().----------------------------  
126      def Points(self):      def Points(self):
127          """Return the coordinates of the shape as a list of lists of pairs"""          """Return the coordinates of the shape as a list of lists of pairs
128          feature = self.ogrlayer.GetFeature(self.shapeid)          """
129          geometry = feature.GetGeometryRef()          return self.points
130          while geometry.GetGeometryCount() != 0:  
131                  geometry = geometry.GetGeometryRef(0)      def _points(self):
132          points = []          """Get the coordinates of the shape as a list of lists of pairs
133          for point in range(geometry.GetPointCount()):          """
134                  x = geometry.GetX(point)          shape = []
135                  y = geometry.GetY(point)  
136                  points.append((x, y))          if self.geom is None:
137          points = [points]              return shape.append([])
138          return points  
139            # if geometry object is of type point or line
140            if self.geom.GetGeometryCount() == 0:
141                points =[]
142                for point in range(self.geom.GetPointCount()):
143                    x = self.geom.GetX(point)
144                    y = self.geom.GetY(point)
145                    points.append((x, y))
146                return [points]
147            # if geometry object is of type polygon or multipolygon
148            for i in range(self.geom.GetGeometryCount()):
149                points = []
150                geometry = self.geom.GetGeometryRef(i)
151                # if geometry object is polygon
152                if geometry.GetGeometryCount() == 0:
153                    for point in range(geometry.GetPointCount()):
154                        x = geometry.GetX(point)
155                        y = geometry.GetY(point)
156                        points.append((x, y))
157                    shape.append(points)
158                # if geometry object is of type multipolygon or geometry collection
159                else:
160                    for j in range(geometry.GetGeometryCount()):
161                        points = []
162                        subgeom = geometry.GetGeometryRef(j)
163                        for point in range(subgeom.GetPointCount()):
164                            x = subgeom.GetX(point)
165                            y = subgeom.GetY(point)
166                            points.append((x, y))
167                        shape.append(points)
168            return shape
169    
170      def RawData(self):      def RawData(self):
171          """Return the shape id to use with the shapestore"""          """Return the shape id to use with the shapestore
172            """
173          return self.shapeid          return self.shapeid
174    
175      def OGRLayer(self):      def OGRLayer(self):
176          """Return the ogrlayer object"""          """Return the ogrlayer object
177            """
178          return self.ogrlayer          return self.ogrlayer
179    
180        def ShapeType(self):
181            """Return the shapetype of this shape (may differ from the layer's
182            shapetype)
183            """
184            return self.shapetype
185    
186        def GetGeoms(self):
187            """Return the list of geometries of this feature.
188    
189            If this feature is a geometry collection, all contained geometries
190            are given. Else the returned list is empty.
191            """
192            return self.geoms
193    
194        def GetGeom(self, index):
195            """Return the OGRGeometry object at the specified index.
196    
197            This is not none only if the shape is a geometry collection.
198            """
199            if index < len(self.geoms):
200                return self.geoms[index]
201            else:
202                return None
203    
204    
205    class OGRGeometry:
206        """This class represents a geometry belonging to a specified feature.
207        """
208    
209        def __init__(self, shape, geom, index):
210            """Initialize the geometry object.
211    
212            shape should be an OGRShape, which this geometry belongs to.
213            geom is the base geometry, index is the ReferenceID.
214            """
215            self.shape = shape
216            self.index = index
217    
218            self.geom = geom.GetGeometryRef(index)
219            try:
220                self.shapetype = ogrlib_shapetypes[self.geom.GetGeometryType()]
221            except:
222                self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
223    
224    
225        def ShapeType(self):
226            """Return the shapetype of this geometry object."""
227            return self.shapetype
228    
229    
230  class OGRShapeStore:  class OGRShapeStore:
231        """Corresponds to an OGRLayer object, containing features/shapes and
232           providing the same methods like ShapefileStore.
233    
234           In fact, for all file based shape stores, the class OGRFileShapeStore
235           should be used. Only database shape stores should be
236           used with OGRShapeStore. It is subject to re-factoring
237           to end up with better class names and sensible base classes.
238        """
239    
240        # TODO: re-factor this class to be not responsible for file-based
241        # stores anymore.
242    
243        def __init__(self, session, filename, layername, id_column = None):
244            """Initialize the shapestore.
245    
246            All required information is loaded from the datasource.
247            """
248            # if id_column is None, data is loaded from file, so we need path
249            # if id_column is not None, data is loaded from database
250            if id_column is None:
251                self.filename = os.path.abspath(filename)
252            else:
253                self.filename = filename
254            self.layername = layername
255    
256      """Corresponds to an OGRLayer object, containing features/shapes and providing all methods Thuban          self.ogrdatasource = ogr.Open(filename)
257         needs."""          self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
258    
259      def __init__(self, session, filename, layername):          if id_column is not None:
260          # Make the filename absolute. The filename will be              self.id_column = id_column
261          # interpreted relative to that anyway, but when saving a          else:
262          # session we need to compare absolute paths and it's usually              self.id_column = None
263          # safer to always work with absolute paths.  
264            self.table = OGRTable(session, self.ogrdatasource, self.ogrlayer,
265          self.filename = os.path.abspath(filename)                                  self.id_column)
         self.layername = layername  
   
         self.ogrdatasource = ogr.Open(self.filename)  
         self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)  
         self.table = OGRTable(self.ogrdatasource, self.ogrlayer)  
266    
267          self._open_ogrlayer(layername)          self._open_ogrlayer(layername)
268    
269      def _open_ogrlayer(self, layername):      def _open_ogrlayer(self, layername):
270          self.numshapes = self.ogrlayer.GetFeatureCount()          """Get all required information from the datasource.
271          self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()          """
272          extent = self.ogrlayer.GetExtent()          self.numshapes = self.ogrlayer.GetFeatureCount()
273            self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
274          if extent:  
275                  self.bbox = [extent[0], extent[2], extent[1], extent[3]]          extent = self.ogrlayer.GetExtent()
276          else:          if extent:
277                  self.bbox = None              self.bbox = [extent[0], extent[2], extent[1], extent[3]]
278            else:
279                self.bbox = None
280    
281            try:
282                self.shapetype = ogrlib_shapetypes[self.shapetype]
283            except:
284                # if shapetype is not contained in ogrlib_shapetypes
285                # treat it like SHAPETYPE_UNKNOWN
286                self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
287    
288          self.shapetype = ogrlib_shapetypes[self.shapetype]          self.shapes = self.shapes()
289    
290        def shapes(self):
291            """Return a collection of all features as OGRShape objects.
292            """
293            shapes = {}
294            self.ogrlayer.ResetReading()
295            if self.id_column is None:
296                nextFeature = self.ogrlayer.GetNextFeature()
297                while nextFeature is not None:
298                    fid = nextFeature.GetFID()
299                    shape = OGRShape(self, nextFeature)
300                    shapes[shape.ShapeID()] = shape
301                    nextFeature = self.ogrlayer.GetNextFeature()
302            else:
303                lay = self.ogrdatasource.ExecuteSQL("SELECT %s, * from %s"
304                                        % (self.id_column, self.layername))
305                if lay is not None:
306                    lay.ResetReading()
307                    nextFeature = lay.GetNextFeature()
308                    while nextFeature is not None:
309                        fid = nextFeature.GetField(0)
310                        shape = OGRShape(self, nextFeature)
311                        shapes[shape.ShapeID()] = shape
312                        nextFeature = lay.GetNextFeature()
313                    self.ogrdatasource.ReleaseResultSet(lay)
314            return shapes
315    
316      def OGRLayer(self):      def OGRLayer(self):
317          """Return the OGRLayer object"""          """Return the OGRLayer object
318            """
319          return self.ogrlayer          return self.ogrlayer
320    
321      def FileName(self):      def FileName(self):
322          """Return the filename used to open the file"""          """Return the filename used to open the file
323            """
324          return self.filename          return self.filename
325    
326      def FileType(self):      def FileType(self):
327          """Return the filetype. This is always the string 'ogr-file'"""          """Return the filetype. This is depending on the driver used to open
328          return "ogr-file"          the file.
329            """
330            return self.ogrdatasource.GetDriver().GetName()
331    
332      def ShapeType(self):      def ShapeType(self):
333          """Return the type of the shapes in the shapestore.          """Return the type of the shapes in the shapestore.
334    
335          This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.          This is either SHAPETYPE_POINT, SHAPETYPE_ARC, SHAPETYPE_POLYGON,
336            SHAEPTYPE_GEOMCOLL, SHAPETYPE_NONE or SHAPETYPE_UNKNOWN.
337          """          """
338          return self.shapetype          return self.shapetype
339    
340      def RawShapeFormat(self):      def RawShapeFormat(self):
341          """Return the raw data format of the shape data, i.e. RAW_OGRSHAPES"""          """Return the raw data format of the shape data, i.e. RAW_PYTHON
342          return RAW_OGRSHAPES          """
343            return RAW_PYTHON
344    
345      def NumShapes(self):      def NumShapes(self):
346          """Return the number of shapes in the shape store"""          """Return the number of shapes in the shape store
347            """
348          return self.numshapes          return self.numshapes
349    
350      def BoundingBox(self):      def BoundingBox(self):
# Line 166  class OGRShapeStore: Line 358  class OGRShapeStore:
358          The bbox parameter should be the bounding box as a tuple in the          The bbox parameter should be the bounding box as a tuple in the
359          form (minx, miny, maxx, maxy) in the coordinate system of the          form (minx, miny, maxx, maxy) in the coordinate system of the
360          shape store.          shape store.
   
         The method GetFID() returns feature IDs starting from 0. In Thuban feature IDs start with 1.  
361          """          """
         # Bind a few globals to locals to make it a bit faster  
         cls = OGRShape  
         ogrlayer = self.ogrlayer  
   
362          left, bottom, right, top = bbox          left, bottom, right, top = bbox
363    
364          # create a geometry which can be passed to the layer as spatial filter          # create a geometry which can be passed to the layer as spatial filter
365          bboxpolygon = ogr.CreateGeometryFromWkt('Polygon((%s %s, %s %s, %s %s, %s %s))'          bboxpolygon = ogr.CreateGeometryFromWkt(
366                  %(left, bottom, left, top, right, top, right, bottom))                        ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
367          bboxpolygon.CloseRings()                                   %(left, bottom, left, top, right, top,
368                                      right, bottom, left, bottom)))
369          if ogrlayer.GetSpatialRef():  
370                  bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())          if self.ogrlayer.GetSpatialRef():
371                bboxpolygon.AssignSpatialReference(self.ogrlayer.GetSpatialRef())
372          ogrlayer.ResetReading()  
373          ogrlayer.SetSpatialFilter(bboxpolygon)          self.ogrlayer.ResetReading()
374          numFeatures = ogrlayer.GetFeatureCount()          #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
375          for feature in range(numFeatures):          self.ogrlayer.SetSpatialFilter(bboxpolygon)
376                  nextFeature = ogrlayer.GetNextFeature()  
377                  yield cls(ogrlayer, nextFeature.GetFID())          numFeatures = self.ogrlayer.GetFeatureCount()
378          ogrlayer.SetSpatialFilter(None)          # if no features are in bbox, return all features as shapesInRegion
379          bboxpolygon.Destroy()          # (PostGIS sometimes returns no features even if they are within
380            #  the bounding box)
381            if numFeatures == 0:
382                self.ogrlayer.SetSpatialFilter(None)
383                numFeatures = self.ogrlayer.GetFeatureCount()
384            for feature in range(numFeatures):
385                nextFeature = self.ogrlayer.GetNextFeature()
386                if self.id_column is None:
387                    yield self.shapes[nextFeature.GetFID()]
388                else:
389                    yield self.shapes[nextFeature.GetField(self.id_column)]
390    
391            self.ogrlayer.SetSpatialFilter(None)
392            bboxpolygon.Destroy()
393    
394      def AllShapes(self):      def AllShapes(self):
395          """Return an iterable over the shapes in the shape store."""          """Return an iterable over the shapes in the shape store.
396          for i in xrange(self.NumShapes()):          """
397              yield OGRShape(self.ogrlayer, i)          for id in range(len(self.shapes)):
398                yield self.shapes[id]
399      def Shape(self, index):  
400          """Return the shape with index index"""      def Shape(self, fid):
401          return OGRShape(self.ogrlayer, index)          """Return the shape with fid = fid
402            """
403            if fid in self.table.ids.keys():
404                return self.shapes[fid]
405            else:
406                return None
407    
408      def Table(self):      def Table(self):
409          """Return the table containing the attribute data"""          """Return the table containing the attribute data
410            """
411          return self.table          return self.table
412    
413      def Dependencies(self):      def Dependencies(self):
414          """Return the empty tuple."""          """Return the empty tuple.
415            """
416          return ()          return ()
417    
418      def OrigShapeStore(self):      def OrigShapeStore(self):
419          """Return None."""          """Return None."""
420          return None          return None
421    
422        def Id_column(self):
423            """Return the id_column.
424            """
425            return self.id_column
426    
427    class OGRFileShapeStore(FileShapeStore):
428        """Corresponds to an OGRLayer object, containing features/shapes and
429           providing the same methods like ShapefileStore.
430        """
431    
432        def __init__(self, session, filename, layername, id_column = None):
433            """Initialize the shapestore.
434    
435            All required information is loaded from the datasource.
436            """
437            self._bbox = None
438            self.ogrdatasource = ogr.Open(filename)
439    
440            # filetype is depending on the driver used to open the file.
441            self._filetype = self.ogrdatasource.GetDriver().GetName()
442            if self._filetype == 'ESRI Shapefile':
443                self._filetype = "shapefile"
444            FileShapeStore.__init__(self, filename,
445                                    sublayer_name = layername)
446    
447            self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
448    
449            self._table = OGRTable(session, self.ogrdatasource, self.ogrlayer,
450                                   id_column)
451    
452            self._open_ogrlayer(layername)
453    
454        def _open_ogrlayer(self, layername):
455            """Get all required information from the datasource.
456            """
457            self.numshapes = self.ogrlayer.GetFeatureCount()
458            self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
459    
460            extent = self.ogrlayer.GetExtent()
461            if extent:
462                self._bbox = [extent[0], extent[2], extent[1], extent[3]]
463            else:
464                self._bbox = None
465    
466            try:
467                self.shapetype = ogrlib_shapetypes[self.shapetype]
468            except:
469                # if shapetype is not contained in ogrlib_shapetypes
470                # treat it like SHAPETYPE_UNKNOWN
471                self.shapetype = ogrlib_shapetypes[ogr.wkbUnknown]
472    
473            self.shapes = self.shapes()
474    
475        def FileType(self):
476            """Return the filetype."""
477            return self._filetype
478    
479        def BoundingBox(self):
480            """Return the bounding box of the shapes in the shape file.
481    
482            The coordinate system used is whatever was used in the shape file.
483            If the shape file is empty, return None.
484            """
485            return self._bbox
486    
487        def shapes(self):
488            """Return a collection of all features as OGRShape objects.
489            """
490            shapes = {}
491            self.ogrlayer.ResetReading()
492    
493            nextFeature = self.ogrlayer.GetNextFeature()
494            while nextFeature is not None:
495                fid = nextFeature.GetFID()
496                shape = OGRShape(self, nextFeature)
497                shapes[shape.ShapeID()] = shape
498                nextFeature = self.ogrlayer.GetNextFeature()
499    
500            return shapes
501    
502        def OGRLayer(self):
503            """Return the OGRLayer object
504            """
505            return self.ogrlayer
506    
507        def ShapeType(self):
508            """Return the type of the shapes in the shapestore.
509    
510            This is either SHAPETYPE_POINT, SHAPETYPE_ARC, SHAPETYPE_POLYGON,
511            SHAEPTYPE_GEOMCOLL, SHAPETYPE_NONE or SHAPETYPE_UNKNOWN.
512            """
513            return self.shapetype
514    
515        def RawShapeFormat(self):
516            """Return the raw data format of the shape data, i.e. RAW_PYTHON
517            """
518            return RAW_PYTHON
519    
520        def NumShapes(self):
521            """Return the number of shapes in the shape store
522            """
523            return self.numshapes
524    
525        def ShapesInRegion(self, bbox):
526            """Return an iterable over the shapes that overlap the bounding box.
527    
528            The bbox parameter should be the bounding box as a tuple in the
529            form (minx, miny, maxx, maxy) in the coordinate system of the
530            shape store.
531            """
532            left, bottom, right, top = bbox
533    
534            # create a geometry which can be passed to the layer as spatial filter
535            bboxpolygon = ogr.CreateGeometryFromWkt(
536                          ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
537                                     %(left, bottom, left, top, right, top,
538                                      right, bottom, left, bottom)))
539    
540            if self.ogrlayer.GetSpatialRef():
541                bboxpolygon.AssignSpatialReference(self.ogrlayer.GetSpatialRef())
542    
543            self.ogrlayer.ResetReading()
544            #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
545            self.ogrlayer.SetSpatialFilter(bboxpolygon)
546    
547            numFeatures = self.ogrlayer.GetFeatureCount()
548            # if no features are in bbox, return all features as shapesInRegion
549            # (PostGIS sometimes returns no features even if they are within
550            #  the bounding box)
551            if numFeatures == 0:
552                self.ogrlayer.SetSpatialFilter(None)
553                numFeatures = self.ogrlayer.GetFeatureCount()
554            for feature in range(numFeatures):
555                nextFeature = self.ogrlayer.GetNextFeature()
556                yield self.shapes[nextFeature.GetFID()]
557    
558            self.ogrlayer.SetSpatialFilter(None)
559            bboxpolygon.Destroy()
560    
561        def AllShapes(self):
562            """Return an iterable over the shapes in the shape store.
563            """
564            for id in range(len(self.shapes)):
565                yield self.shapes[id]
566    
567        def Shape(self, fid):
568            """Return the shape with fid = fid
569            """
570            if fid in self.Table().ids.keys():
571                return self.shapes[fid]
572            else:
573                return None
574    
575        def Table(self):
576            """Return the table containing the attribute data."""
577            return self._table
578    
579        def Dependencies(self):
580            """Return the empty tuple.
581            """
582            return ()
583    
584        def OrigShapeStore(self):
585            """Return None."""
586            return None
587    
588  class OGRTable:      def Id_column(self):
589            """Return the id_column.
590            """
591            return None
592    
593      """A Table for an ogr file  class OGRTable(transientdb.AutoTransientTable):
594        """A Table for an ogr datasource.
595      """      """
596    
597      def __init__(self, ds, layer):      def __init__(self, session, ds, layer, id_column):
598          """Initialize the OGRTable.          """Initialize the OGRTable.
599    
600             ds should be an instance of OGRDatasource.          session   - should be the current session.
601             layer should be an instance of OGRLayer.          ds        - should be an instance of OGRDatasource.
602            layer     - should be an instance of OGRLayer.
603            id_column - should be the name of the column used as ID column
604          """          """
   
605          self.datasource = ds          self.datasource = ds
606          self.layer = layer          self.layer = layer
607          self.tablename = layer.GetName()          self.tablename = self.layer.GetName()
608            self.id_column = id_column
609    
610          # Map column names and indices to column objects.          # Map column names and indices to column objects.
611          self.column_map = {}          self.column_map = {}
612    
613            # Map feature ids to ordinals.
614            self._map_ords_and_ids()
615    
616          self._fetch_table_information()          self._fetch_table_information()
617            self._fetch_table_content()
618    
619            transientdb.AutoTransientTable.__init__(self, session.TransientDB(),
620                                                    self)
621    
622      def _fetch_table_information(self):      def _fetch_table_information(self):
623          """Internal: Update information about the table"""          """Internal: Update information about the table
624            """
625          self.columns = []          self.columns = []
626    
627          layerdefn = self.layer.GetLayerDefn()          layerdefn = self.layer.GetLayerDefn()
628          for i in range(layerdefn.GetFieldCount()):          # if FID column is of interest
629                  fielddef = layerdefn.GetFieldDefn(i)          #col = OGRColumn("FID", table.FIELDTYPE_INT, layerdefn.GetFieldCount())
630                  fieldname = fielddef.GetName()          #self.columns.append(col)
631                  fieldtype = fieldtype_map[fielddef.GetType()]          for i in range(layerdefn.GetFieldCount()):
632                  fieldindex = layerdefn.GetFieldIndex(fieldname)              fielddef = layerdefn.GetFieldDefn(i)
633                  col = OGRColumn(fieldname, fieldtype, fieldindex)              fieldname = fielddef.GetName()
634                  if col is not None:              fieldtype = fieldtype_map[fielddef.GetType()]
635                          self.columns.append(col)              fieldindex = layerdefn.GetFieldIndex(fieldname)
636                col = OGRColumn(fieldname, fieldtype, fieldindex)
637                if col is not None:
638                    self.columns.append(col)
639    
640          for col in self.columns:          for col in self.columns:
641              self.column_map[col.name] = col              self.column_map[col.name] = col
642              self.column_map[col.index] = col              self.column_map[col.index] = col
643    
644        def _fetch_table_content(self):
645            """Internal: Update information contained in the table
646            """
647            self.content = []
648            layerdefn = self.layer.GetLayerDefn()
649    
650            self.layer.ResetReading()
651            for i in range(self.layer.GetFeatureCount()):
652                nextFeature = self.layer.GetNextFeature()
653                row = []
654                for j in range(layerdefn.GetFieldCount()):
655                    row.append(nextFeature.GetField(j))
656                # if FID should be listed in the table
657                #if self.id_column is None:
658                #    row.append(nextFeature.GetFID())
659                #else:
660                #    row.append(nextFeature.GetField(self.id_column))
661                self.content.append(row)
662    
663        def _map_ords_and_ids(self):
664            """Create collections which map ordinals to ids and verse visa.
665            """
666            self.ordinals = {}
667            self.ids = {}
668    
669            if self.id_column is not None:
670                lay = self.datasource.ExecuteSQL("SELECT %s from %s"
671                        %(self.id_column, self.tablename))
672                lay.ResetReading()
673                nextFeature = lay.GetNextFeature()
674            else:
675                self.layer.ResetReading()
676                nextFeature = self.layer.GetNextFeature()
677    
678            ord = 0
679            while nextFeature is not None:
680                if self.id_column is not None:
681                    id = nextFeature.GetField(self.id_column)
682                    nextFeature = lay.GetNextFeature()
683                else:
684                    id = nextFeature.GetFID()
685                    nextFeature = self.layer.GetNextFeature()
686                self.ordinals[ord] = id
687                self.ids[id] = ord
688                ord = ord + 1
689            if self.id_column is not None:
690                self.datasource.ReleaseResultSet(lay)
691    
692      def TableName(self):      def TableName(self):
693          """Return the name of the table, which is the name of the layer"""          """Return the name of the table, which is the name of the layer
694            """
695          return self.tablename          return self.tablename
696    
697      def Title(self):      def Title(self):
698          """Return the title of the table.          """Return the title of the table.
   
         The title is currently fixed and equal to the tablename  
699          """          """
700          return self.tablename          return self.tablename
701    
702      def Dependencies(self):      def Dependencies(self):
703          """Return an empty tuple."""          """Return an empty tuple.
704            """
705          return ()          return ()
706    
707      def NumColumns(self):      def NumColumns(self):
708          """Return the number of columns."""          """Return the number of columns.
709            """
710          return len(self.columns)          return len(self.columns)
711    
712      def Columns(self):      def Columns(self):
713          """Return all columns."""          """Return all columns.
714            """
715          return self.columns          return self.columns
716    
717      def Column(self, col):      def Column(self, col):
718          """Return the column col. col can be either a string or an integer."""          """Return the column col. col can be either a string or an integer.
719            """
720          return self.column_map[col]          return self.column_map[col]
721    
722      def HasColumn(self, col):      def HasColumn(self, col):
723          """Return if column col exists. col can be either a string or an integer."""          """Return if column col exists. col can be either a string or an
724            integer.
725            """
726          return self.column_map.has_key(col)          return self.column_map.has_key(col)
727    
728      def NumRows(self):      def NumRows(self):
729          """Return the number of rows in the table, which equals the number of features in the layer."""          """Return the number of rows in the table, which equals the number of
730          return self.layer.GetFeatureCount()          features in the layer.
731            """
732            return len(self.ids)
733    
734      def RowIdToOrdinal(self, gid):      def RowIdToOrdinal(self, gid):
735          """Return the row ordinal given its id"""          """Return the row ordinal given its id
736          return self.layer.GetFeature(gid).GetFID()          """
737            if gid < 0:
738                return gid
739            else:
740                ord = self.ids[gid]
741                return ord
742    
743      def RowOrdinalToId(self, num):      def RowOrdinalToId(self, num):
744          """Return the rowid for given its ordinal"""          """Return the rowid for given its ordinal
745          return self.layer.GetFeature(num).GetFID()          """
746            if num >= 0:
747                id = self.ordinals[num]
748                return id
749            else:
750                return num
751    
752      def ReadRowAsDict(self, row, row_is_ordinal = 0):      def ReadRowAsDict(self, row, row_is_ordinal = 0):
753          """Return a dictionary which contains all the fields."""          """Return a dictionary which contains all the fields.
754          layerdef = self.layer.GetLayerDefn()          """
755          feature = self.layer.GetFeature(row)          if row_is_ordinal == 0:
756          result = {}              rowId = self.RowIdToOrdinal(row)
757          for i in range(feature.GetFieldCount()):          else:
758                  fielddef = layerdef.GetFieldDefn(i)              rowId = row
759                  result[fielddef.GetName()] = feature.GetField(i)          result = {}
760            for i in range(self.NumColumns()):
761                result[self.Column(i).name] = self.content[rowId][i]
762          return result          return result
763    
764      def ReadValue(self, row, col, row_is_ordinal = 0):      def ReadValue(self, row, col, row_is_ordinal = 0):
765          """Return the requested value."""          """Return the requested value.
766          if col is None:          """
767                  return None          if row_is_ordinal == 0:
768          else:              rowId = self.RowIdToOrdinal(row)
769                  feature = self.layer.GetFeature(row)          else:
770                  return feature.GetField(col)              rowId = row
771            colIndex = self.column_map[col].index
772            return self.content[rowId][colIndex]
773    
774      def ValueRange(self, col):      def ValueRange(self, col):
775          """Return the value range of the given column (given as string)."""          """Return the value range of the given column (given as string).
776          result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"          """
777                  %(col, col, self.layer.GetName()))  
778          result.ResetReading()          result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"
779          feature = result.GetNextFeature()                  %(col, col, self.layer.GetName()))
780          try:          result.ResetReading()
781                  min = feature.GetField(0)          feature = result.GetNextFeature()
782                  max = feature.GetField(1)          try:
783          except:              min = feature.GetField(0)
784                  min = 0              max = feature.GetField(1)
785                  max = 0          except:
786          self.datasource.ReleaseResultSet(result)              min = 0
787                max = 0
788            self.datasource.ReleaseResultSet(result)
789          return (min, max)          return (min, max)
790    
791      def UniqueValues(self, col):      def UniqueValues(self, col):
792          """Return all the values being found in the column (given as string)."""          """Return all the values being found in the column (given as string).
793          result = self.datasource.ExecuteSQL("SELECT DISTINCT %s FROM %s ORDER BY %s" %(col, self.layer.GetName(),col))          """
794          values = []          result = self.datasource.ExecuteSQL((
795          while 1:                      "SELECT DISTINCT %s FROM %s ORDER BY %s"
796                  feature = result.GetNextFeature()                       %(col,self.layer.GetName(),col)))
797                  if feature is None:          values = []
798                          break          while 1:
799                  values.append(feature.GetField(0))              feature = result.GetNextFeature()
800          self.datasource.ReleaseResultSet(result)              if feature is None:
801                    break
802                values.append(feature.GetField(0))
803            self.datasource.ReleaseResultSet(result)
804          return values          return values
805    
806      def SimpleQuery(self, left, comparison, right):      def SimpleQuery(self, left, comparison, right):
807          """Return the FIDs resulting from the given query."""          """Return the FIDs resulting from the given query.
808            """
809    
810          if comparison not in ("==", "!=", "<", "<=", ">=", ">"):          if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
811              raise ValueError("Comparison operator %r not allowed" % comparison)              raise ValueError("Comparison operator %r not allowed" %comparison)
812    
813          if comparison == "==":          if comparison == "==":
814              comparison = "="              comparison = "="
# Line 354  class OGRTable: Line 818  class OGRTable:
818          else:          else:
819              right_template = right              right_template = right
820    
821          query = "SELECT FID FROM %s WHERE '%s' %s %s ORDER BY FID" %(self.tablename, left.name, comparison, right_template)          if self.id_column is None:
822                id = "FID"
823            else:
824                id = self.id_column
825            query = ("SELECT %s FROM %s WHERE %s %s %s ORDER BY %s"
826                    % (id, self.tablename,left.name, comparison,
827                       right_template, id))
828    
829          lay = self.datasource.ExecuteSQL(query)          lay = self.datasource.ExecuteSQL(query)
830          result = []          result = []
831          while 1:          while lay is not None:
832              feature = lay.GetNextFeature()              feature = lay.GetNextFeature()
833              if feature is None:              if feature is None:
834                  break                  break
835              result.append(feature.GetField(0))              result.append(feature.GetField(0))
836          self.datasource.ReleaseResultSet(lay)          if lay is not None:
837                self.datasource.ReleaseResultSet(lay)
838          return result          return result
839    
840        def Id_column(self):
841            """Return the id_column.
842            """
843            return self.id_column
844    
 class OGRColumn:  
845    
846    class OGRColumn:
847      """Column description for a table for an ogr file      """Column description for a table for an ogr file
848      """      """
849    

Legend:
Removed from v.2435  
changed lines
  Added in v.2734

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26