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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2559 - (hide annotations)
Tue Feb 8 09:52:56 2005 UTC (20 years ago) by nhueffme
Original Path: trunk/thuban/Extensions/ogr/ogrshapes.py
File MIME type: text/x-python
File size: 15966 byte(s)
Changed the GUI. OGR support can now be accessed via the Map menu.
Removed some print commands.

1 nhueffme 2435 # Copyright (C) 2004 by Intevation GmbH
2     # Authors:
3 nhueffme 2493 # Nina Hueffmeyer <[email protected]>
4 nhueffme 2435 #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with the software for details.
7    
8     __version__ = "$Revision$"
9     # $Source$
10     # $Id$
11    
12     from __future__ import generators
13    
14     try:
15     import ogr
16     except ImportError:
17     ogr = None
18    
19     import os
20     import weakref
21     from math import ceil, log
22    
23     from Thuban import _
24     from Thuban.Model import table
25    
26     from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
27     from Thuban.Model.data import RAW_PYTHON, RAW_SHAPEFILE, RAW_WKT
28    
29 nhueffme 2559 SHAPETYPE_UNKNOWN = ogr.wkbUnknown
30 nhueffme 2435
31     def has_ogr_support():
32     """Return whether this Thuban instance supports ogr file formats
33    
34     Having OGR support means that the ogr module can be
35     imported.
36     """
37     return ogr is not None
38    
39     if ogr is not None:
40     # mapping from ogr-lib shapetype and table constants to our constants
41     ogrlib_shapetypes = {ogr.wkbPolygon: SHAPETYPE_POLYGON,
42 nhueffme 2493 ogr.wkbLineString: SHAPETYPE_ARC,
43 nhueffme 2549 ogr.wkbPoint: SHAPETYPE_POINT,
44     ogr.wkbUnknown: SHAPETYPE_UNKNOWN}
45 nhueffme 2435
46     fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,
47 nhueffme 2493 ogr.OFTInteger: table.FIELDTYPE_INT,
48     ogr.OFTReal: table.FIELDTYPE_DOUBLE}
49 nhueffme 2435
50    
51     class OGRShape:
52    
53     """Represent one shape of an OGRShapeStore"""
54    
55     def __init__(self, ogrlayer, shapeid):
56     self.ogrlayer = ogrlayer
57 nhueffme 2559 self.feature = self.ogrlayer.GetFeature(shapeid)
58 nhueffme 2435 self.shapeid = shapeid
59 nhueffme 2559 self.geom = self.feature.GetGeometryRef()
60     self.shapetype = self.geom.GetGeometryType()
61 nhueffme 2435
62     def compute_bbox(self):
63     """
64     Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
65     """
66 nhueffme 2559 minx, maxx, miny, maxy = self.geom.GetEnvelope()
67 nhueffme 2493 return (minx, miny, maxx, maxy)
68 nhueffme 2435
69     def ShapeID(self):
70     return self.shapeid
71    
72     def Points(self):
73     """Return the coordinates of the shape as a list of lists of pairs"""
74 nhueffme 2549 shape = []
75     #spatialFilter = self.ogrlayer.GetSpatialFilter()
76    
77 nhueffme 2559 #if spatialFilter is not None:
78     #self.ogrlayer.SetSpatialFilter(None)
79     #feature = self.ogrlayer.GetFeature(self.shapeid)
80     #self.ogrlayer.SetSpatialFilter(spatialFilter)
81     #else:
82     #feature = self.ogrlayer.GetFeature(self.shapeid)
83    
84     #if feature is None:
85     # return shape.append([])
86     #geom = feature.GetGeometryRef()
87    
88     if self.geom is None:
89 nhueffme 2549 return shape.append([])
90    
91 nhueffme 2493 # if geometry object is of type point or line
92 nhueffme 2559 if self.geom.GetGeometryCount() == 0:
93 nhueffme 2493 points =[]
94 nhueffme 2559 for point in range(self.geom.GetPointCount()):
95     x = self.geom.GetX(point)
96     y = self.geom.GetY(point)
97 nhueffme 2493 points.append((x, y))
98     return [points]
99     # if geometry object is of type polygon or multipolygon
100 nhueffme 2559 for i in range(self.geom.GetGeometryCount()):
101 nhueffme 2493 points = []
102 nhueffme 2559 geometry = self.geom.GetGeometryRef(i)
103 nhueffme 2549 # if geometry object is polygon
104 nhueffme 2493 if geometry.GetGeometryCount() == 0:
105     for point in range(geometry.GetPointCount()):
106     x = geometry.GetX(point)
107     y = geometry.GetY(point)
108     points.append((x, y))
109     shape.append(points)
110     # if geometry object is of type multipolygon
111 nhueffme 2549 else:
112 nhueffme 2493 for j in range(geometry.GetGeometryCount()):
113     points = []
114     subgeom = geometry.GetGeometryRef(j)
115     for point in range(subgeom.GetPointCount()):
116     x = subgeom.GetX(point)
117     y = subgeom.GetY(point)
118     points.append((x, y))
119     shape.append(points)
120     return shape
121 nhueffme 2435
122     def RawData(self):
123     """Return the shape id to use with the shapestore"""
124     return self.shapeid
125    
126     def OGRLayer(self):
127     """Return the ogrlayer object"""
128     return self.ogrlayer
129    
130 nhueffme 2559 def ShapeType(self):
131     return self.shapetype
132 nhueffme 2435
133 nhueffme 2559
134 nhueffme 2435 class OGRShapeStore:
135    
136 nhueffme 2493 """Corresponds to an OGRLayer object, containing features/shapes and
137     providing all methods Thuban needs.
138     """
139 nhueffme 2435
140 nhueffme 2559 def __init__(self, filename, layername, id_column = None):
141 nhueffme 2435 # Make the filename absolute. The filename will be
142     # interpreted relative to that anyway, but when saving a
143     # session we need to compare absolute paths and it's usually
144     # safer to always work with absolute paths.
145    
146 nhueffme 2549 self.filename = filename
147 nhueffme 2493 self.layername = layername
148 nhueffme 2435
149 nhueffme 2549 self.ogrdatasource = ogr.Open(filename)
150 nhueffme 2493 self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
151 nhueffme 2435
152 nhueffme 2549 driver = self.ogrdatasource.GetDriver().GetName()
153     if driver == 'PostgreSQL':
154     self.id_column = 'gid'
155     else:
156     self.id_column = 'fid'
157    
158     self.table = OGRTable(self.ogrdatasource, self.ogrlayer, self.id_column)
159    
160 nhueffme 2435 self._open_ogrlayer(layername)
161    
162     def _open_ogrlayer(self, layername):
163 nhueffme 2493 self.numshapes = self.ogrlayer.GetFeatureCount()
164     self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
165 nhueffme 2549
166 nhueffme 2493 extent = self.ogrlayer.GetExtent()
167     if extent:
168     self.bbox = [extent[0], extent[2], extent[1], extent[3]]
169     else:
170     self.bbox = None
171 nhueffme 2435
172 nhueffme 2549 if self.shapetype is not ogr.wkbUnknown:
173     self.shapetype = ogrlib_shapetypes[self.shapetype]
174     #else:
175 nhueffme 2559 # this should be ogr.wkbUnknown, but Thuban does not know how
176     # to handle an unknown shapetype (e.g. Session Tree)
177 nhueffme 2549 #self.shapetype = ogrlib_shapetypes[ogr.wkbPoint]
178 nhueffme 2435
179     def OGRLayer(self):
180     """Return the OGRLayer object"""
181     return self.ogrlayer
182    
183     def FileName(self):
184     """Return the filename used to open the file"""
185     return self.filename
186    
187     def FileType(self):
188     """Return the filetype. This is always the string 'ogr-file'"""
189     return "ogr-file"
190    
191     def ShapeType(self):
192     """Return the type of the shapes in the shapestore.
193    
194     This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
195     """
196     return self.shapetype
197    
198     def RawShapeFormat(self):
199 nhueffme 2493 """Return the raw data format of the shape data, i.e. RAW_PYTHON"""
200     return RAW_PYTHON
201 nhueffme 2435
202     def NumShapes(self):
203     """Return the number of shapes in the shape store"""
204     return self.numshapes
205    
206     def BoundingBox(self):
207     """Return the bounding box of the shapes in the shapestore.
208     """
209     return self.bbox
210    
211     def ShapesInRegion(self, bbox):
212     """Return an iterable over the shapes that overlap the bounding box.
213    
214     The bbox parameter should be the bounding box as a tuple in the
215     form (minx, miny, maxx, maxy) in the coordinate system of the
216     shape store.
217    
218 nhueffme 2493 The method GetFID() returns feature IDs starting from 0.
219 nhueffme 2435 """
220     # Bind a few globals to locals to make it a bit faster
221     cls = OGRShape
222     ogrlayer = self.ogrlayer
223    
224     left, bottom, right, top = bbox
225 nhueffme 2493 # create a geometry which can be passed to the layer as spatial filter
226     bboxpolygon = ogr.CreateGeometryFromWkt(
227     ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
228     %(left, bottom, left, top, right, top,
229     right, bottom, left, bottom)))
230 nhueffme 2435
231 nhueffme 2493 if ogrlayer.GetSpatialRef():
232     bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())
233 nhueffme 2435
234 nhueffme 2493 ogrlayer.ResetReading()
235 nhueffme 2549 #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
236 nhueffme 2493 ogrlayer.SetSpatialFilter(bboxpolygon)
237 nhueffme 2559
238 nhueffme 2493 numFeatures = ogrlayer.GetFeatureCount()
239     for feature in range(numFeatures):
240     nextFeature = ogrlayer.GetNextFeature()
241     yield cls(ogrlayer, nextFeature.GetFID())
242 nhueffme 2559
243 nhueffme 2493 ogrlayer.SetSpatialFilter(None)
244     bboxpolygon.Destroy()
245 nhueffme 2435
246     def AllShapes(self):
247     """Return an iterable over the shapes in the shape store."""
248 nhueffme 2549 self.ogrlayer.ResetReading()
249     nextFeature = self.ogrlayer.GetNextFeature()
250     while nextFeature is not None:
251     yield OGRShape(self.ogrlayer, nextFeature.GetFID())
252     nextFeature = self.ogrlayer.GetNextFeature()
253 nhueffme 2435
254     def Shape(self, index):
255     """Return the shape with index index"""
256     return OGRShape(self.ogrlayer, index)
257    
258     def Table(self):
259     """Return the table containing the attribute data"""
260     return self.table
261    
262     def Dependencies(self):
263     """Return the empty tuple."""
264     return ()
265    
266     def OrigShapeStore(self):
267     """Return None."""
268     return None
269    
270 nhueffme 2559 def Id_column(self):
271     """Return the id_column."""
272     return self.id_column
273 nhueffme 2435
274     class OGRTable:
275    
276     """A Table for an ogr file
277     """
278    
279 nhueffme 2549 def __init__(self, ds, layer, id_column):
280 nhueffme 2435 """Initialize the OGRTable.
281    
282 nhueffme 2493 ds should be an instance of OGRDatasource.
283     layer should be an instance of OGRLayer.
284 nhueffme 2435 """
285    
286     self.datasource = ds
287     self.layer = layer
288 nhueffme 2493 self.tablename = layer.GetName()
289 nhueffme 2549 self.id_column = id_column
290 nhueffme 2435
291     # Map column names and indices to column objects.
292     self.column_map = {}
293    
294 nhueffme 2549 # Map feature ids to ordinals.
295     self._map_ords_and_ids()
296    
297 nhueffme 2435 self._fetch_table_information()
298    
299     def _fetch_table_information(self):
300     """Internal: Update information about the table"""
301     self.columns = []
302    
303 nhueffme 2493 layerdefn = self.layer.GetLayerDefn()
304     for i in range(layerdefn.GetFieldCount()):
305     fielddef = layerdefn.GetFieldDefn(i)
306     fieldname = fielddef.GetName()
307     fieldtype = fieldtype_map[fielddef.GetType()]
308     fieldindex = layerdefn.GetFieldIndex(fieldname)
309     col = OGRColumn(fieldname, fieldtype, fieldindex)
310     if col is not None:
311     self.columns.append(col)
312 nhueffme 2435
313     for col in self.columns:
314     self.column_map[col.name] = col
315     self.column_map[col.index] = col
316    
317 nhueffme 2549 def _map_ords_and_ids(self):
318     self.ordinals = {}
319     self.ids = {}
320    
321     lay = self.datasource.ExecuteSQL(
322     "SELECT %s from %s"
323     %(self.id_column, self.tablename))
324     lay.ResetReading()
325     nextFeature = lay.GetNextFeature()
326     ord = 0
327     while nextFeature is not None:
328     id = nextFeature.GetFID()
329     self.ordinals[ord] = id
330     self.ids[id] = ord
331     nextFeature = lay.GetNextFeature()
332     ord = ord + 1
333     self.datasource.ReleaseResultSet(lay)
334    
335 nhueffme 2435 def TableName(self):
336     """Return the name of the table, which is the name of the layer"""
337     return self.tablename
338    
339     def Title(self):
340     """Return the title of the table.
341    
342 nhueffme 2549 The title is currently
343 nhueffme 2435 """
344     return self.tablename
345    
346     def Dependencies(self):
347     """Return an empty tuple."""
348     return ()
349    
350     def NumColumns(self):
351 nhueffme 2493 """Return the number of columns."""
352 nhueffme 2435 return len(self.columns)
353    
354     def Columns(self):
355 nhueffme 2493 """Return all columns."""
356 nhueffme 2435 return self.columns
357    
358     def Column(self, col):
359 nhueffme 2493 """Return the column col. col can be either a string or an integer."""
360 nhueffme 2435 return self.column_map[col]
361    
362     def HasColumn(self, col):
363 nhueffme 2493 """Return if column col exists. col can be either a string or an
364     integer.
365     """
366 nhueffme 2435 return self.column_map.has_key(col)
367    
368     def NumRows(self):
369 nhueffme 2493 """Return the number of rows in the table, which equals the number of
370     features in the layer.
371     """
372     return self.layer.GetFeatureCount()
373 nhueffme 2435
374     def RowIdToOrdinal(self, gid):
375     """Return the row ordinal given its id"""
376 nhueffme 2549 if gid < 0:
377     return gid
378     else:
379     ord = self.ids[gid]
380     return ord
381     # lay = self.datasource.ExecuteSQL(
382     # "SELECT COUNT(%s) From %s where FID < %s"
383     # %(self.id_column, self.tablename, gid))
384     # ord = lay.GetFeature(0).GetField(0)
385     # self.datasource.ReleaseResultSet(lay)
386     # return ord
387 nhueffme 2435
388     def RowOrdinalToId(self, num):
389     """Return the rowid for given its ordinal"""
390 nhueffme 2549 # lay = self.datasource.ExecuteSQL(
391     # "SELECT FID From %s"
392     # %(self.tablename))
393     # for i in range(num):
394     # lay.GetNextFeature()
395     # id = lay.GetNextFeature().GetField(0)
396     # self.datasource.ReleaseResultSet(lay)
397     if num >= 0:
398     id = self.ordinals[num]
399     return id
400     else:
401     return num
402 nhueffme 2435
403     def ReadRowAsDict(self, row, row_is_ordinal = 0):
404 nhueffme 2493 """Return a dictionary which contains all the fields."""
405 nhueffme 2549 if row_is_ordinal == 1:
406     rowId = self.RowOrdinalToId(row)
407     else:
408     rowId = row
409 nhueffme 2493 layerdef = self.layer.GetLayerDefn()
410 nhueffme 2549 feature = self.layer.GetFeature(rowId)
411 nhueffme 2493 result = {}
412 nhueffme 2549 for i in range(len(self.columns)):
413 nhueffme 2493 fielddef = layerdef.GetFieldDefn(i)
414 nhueffme 2549 if feature is not None:
415     result[self.columns[i].name] = feature.GetField(i)
416     else:
417     result[fielddef.GetName()] = None
418 nhueffme 2435 return result
419    
420     def ReadValue(self, row, col, row_is_ordinal = 0):
421 nhueffme 2493 """Return the requested value."""
422     if col is None:
423     return None
424     else:
425     feature = self.layer.GetFeature(row)
426     return feature.GetField(col)
427 nhueffme 2435
428     def ValueRange(self, col):
429 nhueffme 2493 """Return the value range of the given column (given as string)."""
430     result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"
431     %(col, col, self.layer.GetName()))
432     result.ResetReading()
433     feature = result.GetNextFeature()
434     try:
435     min = feature.GetField(0)
436     max = feature.GetField(1)
437     except:
438     min = 0
439     max = 0
440     self.datasource.ReleaseResultSet(result)
441 nhueffme 2435 return (min, max)
442    
443     def UniqueValues(self, col):
444 nhueffme 2493 """Return all the values being found in the column (given as string).
445     """
446     result = self.datasource.ExecuteSQL((
447     "SELECT DISTINCT %s FROM %s ORDER BY %s"
448     %(col,self.layer.GetName(),col)))
449     values = []
450     while 1:
451     feature = result.GetNextFeature()
452     if feature is None:
453     break
454     values.append(feature.GetField(0))
455     self.datasource.ReleaseResultSet(result)
456 nhueffme 2435 return values
457    
458     def SimpleQuery(self, left, comparison, right):
459 nhueffme 2493 """Return the FIDs resulting from the given query."""
460 nhueffme 2435 if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
461 nhueffme 2493 raise ValueError("Comparison operator %r not allowed" %comparison)
462 nhueffme 2435
463     if comparison == "==":
464     comparison = "="
465    
466     if isinstance(right, OGRColumn):
467     right_template = right.name
468     else:
469     right_template = right
470    
471 nhueffme 2549 query = ("SELECT %s FROM %s WHERE '%s' %s %s ORDER BY FID"
472     % (self.id_column, self.tablename,left.name, comparison,
473     right_template))
474 nhueffme 2435
475     lay = self.datasource.ExecuteSQL(query)
476 nhueffme 2493 result = []
477     while lay is not None:
478 nhueffme 2435 feature = lay.GetNextFeature()
479     if feature is None:
480     break
481     result.append(feature.GetField(0))
482 nhueffme 2549 if lay is not None:
483     self.datasource.ReleaseResultSet(lay)
484 nhueffme 2435 return result
485    
486 nhueffme 2559 def Id_column(self):
487     """Return the id_column."""
488     return self.id_column
489 nhueffme 2435
490 nhueffme 2559
491 nhueffme 2435 class OGRColumn:
492    
493     """Column description for a table for an ogr file
494     """
495    
496     def __init__(self, name, type, index):
497     self.name = name
498     self.type = type
499     self.index = index

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26