/[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 2493 by nhueffme, Mon Dec 20 14:13:57 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 Hueffmeyer <[email protected]>  # Nina H�ffmeyer <[email protected]>
4  #  #
5  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
6  # Read the file COPYING coming with the software for details.  # Read the file COPYING coming with the software for details.
# 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
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 36  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          geom = feature.GetGeometryRef()          return self.points
130    
131        def _points(self):
132            """Get the coordinates of the shape as a list of lists of pairs
133            """
134          shape = []          shape = []
135    
136            if self.geom is None:
137                return shape.append([])
138    
139          # if geometry object is of type point or line          # if geometry object is of type point or line
140          if geom.GetGeometryCount() == 0:          if self.geom.GetGeometryCount() == 0:
141              points =[]              points =[]
142              for point in range(geom.GetPointCount()):              for point in range(self.geom.GetPointCount()):
143                  x = geom.GetX(point)                  x = self.geom.GetX(point)
144                  y = geom.GetY(point)                  y = self.geom.GetY(point)
145                  points.append((x, y))                  points.append((x, y))
146              return [points]              return [points]
147          # if geometry object is of type polygon or multipolygon          # if geometry object is of type polygon or multipolygon
148          for i in range(geom.GetGeometryCount()):          for i in range(self.geom.GetGeometryCount()):
149              points = []              points = []
150              geometry = geom.GetGeometryRef(i)              geometry = self.geom.GetGeometryRef(i)
151              # if geometry object is polygon              # if geometry object is polygon
152              if geometry.GetGeometryCount() == 0:              if geometry.GetGeometryCount() == 0:
153                  for point in range(geometry.GetPointCount()):                  for point in range(geometry.GetPointCount()):
154                      x = geometry.GetX(point)                      x = geometry.GetX(point)
155                      y = geometry.GetY(point)                      y = geometry.GetY(point)
156                      points.append((x, y))                      points.append((x, y))
157                  shape.append(points)                  shape.append(points)
158              # if geometry object is of type multipolygon              # if geometry object is of type multipolygon or geometry collection
159              else:              else:
160                  for j in range(geometry.GetGeometryCount()):                  for j in range(geometry.GetGeometryCount()):
161                      points = []                      points = []
162                      subgeom = geometry.GetGeometryRef(j)                      subgeom = geometry.GetGeometryRef(j)
# Line 108  class OGRShape: Line 168  class OGRShape:
168          return shape          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      """Corresponds to an OGRLayer object, containing features/shapes and         In fact, for all file based shape stores, the class OGRFileShapeStore
235         providing all methods Thuban needs.         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      def __init__(self, session, filename, layername):      # TODO: re-factor this class to be not responsible for file-based
241          # Make the filename absolute. The filename will be      # stores anymore.
         # interpreted relative to that anyway, but when saving a  
         # session we need to compare absolute paths and it's usually  
         # safer to always work with absolute paths.  
242    
243          self.filename = os.path.abspath(filename)      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          self.layername = layername
255    
256          self.ogrdatasource = ogr.Open(self.filename)          self.ogrdatasource = ogr.Open(filename)
257          self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)          self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
258          self.table = OGRTable(self.ogrdatasource, self.ogrlayer)  
259            if id_column is not None:
260                self.id_column = id_column
261            else:
262                self.id_column = None
263    
264            self.table = OGRTable(session, self.ogrdatasource, self.ogrlayer,
265                                    self.id_column)
266    
267          self._open_ogrlayer(layername)          self._open_ogrlayer(layername)
268    
269      def _open_ogrlayer(self, layername):      def _open_ogrlayer(self, layername):
270            """Get all required information from the datasource.
271            """
272          self.numshapes = self.ogrlayer.GetFeatureCount()          self.numshapes = self.ogrlayer.GetFeatureCount()
273          self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()          self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
         extent = self.ogrlayer.GetExtent()  
274    
275            extent = self.ogrlayer.GetExtent()
276          if extent:          if extent:
277              self.bbox = [extent[0], extent[2], extent[1], extent[3]]              self.bbox = [extent[0], extent[2], extent[1], extent[3]]
278          else:          else:
279              self.bbox = None              self.bbox = None
280    
281          self.shapetype = ogrlib_shapetypes[self.shapetype]          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.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_PYTHON"""          """Return the raw data format of the shape data, i.e. RAW_PYTHON
342            """
343          return RAW_PYTHON          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 187  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.  
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(          bboxpolygon = ogr.CreateGeometryFromWkt(
366                        ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'                        ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
367                                   %(left, bottom, left, top, right, top,                                   %(left, bottom, left, top, right, top,
368                                    right, bottom, left, bottom)))                                    right, bottom, left, bottom)))
369    
370          if ogrlayer.GetSpatialRef():          if self.ogrlayer.GetSpatialRef():
371              bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())              bboxpolygon.AssignSpatialReference(self.ogrlayer.GetSpatialRef())
372    
373          ogrlayer.ResetReading()          self.ogrlayer.ResetReading()
374          ogrlayer.SetSpatialFilter(bboxpolygon)          #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
375          numFeatures = ogrlayer.GetFeatureCount()          self.ogrlayer.SetSpatialFilter(bboxpolygon)
376    
377            numFeatures = self.ogrlayer.GetFeatureCount()
378            # if no features are in bbox, return all features as shapesInRegion
379            # (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):          for feature in range(numFeatures):
385              nextFeature = ogrlayer.GetNextFeature()              nextFeature = self.ogrlayer.GetNextFeature()
386              yield cls(ogrlayer, nextFeature.GetFID())              if self.id_column is None:
387          ogrlayer.SetSpatialFilter(None)                  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()          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  class OGRTable:      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      """A Table for an ogr file          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        def Id_column(self):
589            """Return the id_column.
590            """
591            return None
592    
593    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            # if FID column is of interest
629            #col = OGRColumn("FID", table.FIELDTYPE_INT, layerdefn.GetFieldCount())
630            #self.columns.append(col)
631          for i in range(layerdefn.GetFieldCount()):          for i in range(layerdefn.GetFieldCount()):
632              fielddef = layerdefn.GetFieldDefn(i)              fielddef = layerdefn.GetFieldDefn(i)
633              fieldname = fielddef.GetName()              fieldname = fielddef.GetName()
# Line 275  class OGRTable: Line 641  class OGRTable:
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          """Return if column col exists. col can be either a string or an
724          integer.          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          """Return the number of rows in the table, which equals the number of
730          features in the layer.          features in the layer.
731          """          """
732          return self.layer.GetFeatureCount()          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                rowId = self.RowIdToOrdinal(row)
757            else:
758                rowId = row
759          result = {}          result = {}
760          for i in range(feature.GetFieldCount()):          for i in range(self.NumColumns()):
761              fielddef = layerdef.GetFieldDefn(i)              result[self.Column(i).name] = self.content[rowId][i]
             result[fielddef.GetName()] = feature.GetField(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                rowId = self.RowIdToOrdinal(row)
769          else:          else:
770              feature = self.layer.GetFeature(row)              rowId = row
771          return feature.GetField(col)          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            """
777    
778          result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"          result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"
779                  %(col, col, self.layer.GetName()))                  %(col, col, self.layer.GetName()))
780          result.ResetReading()          result.ResetReading()
# Line 371  class OGRTable: Line 804  class OGRTable:
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    
# Line 383  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"          if self.id_column is None:
822                  % (self.tablename,left.name, comparison, right_template))              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 = []
# Line 393  class OGRTable: Line 833  class OGRTable:
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.2493  
changed lines
  Added in v.2734

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26