/[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 2549 - (hide annotations)
Wed Jan 26 09:17:01 2005 UTC (20 years, 1 month ago) by nhueffme
Original Path: trunk/thuban/Extensions/ogr/ogrshapes.py
File MIME type: text/x-python
File size: 16036 byte(s)
Ogr extension works now for shapefiles, GML files and DGN files. Files can be viewed and tables can be shown. For unknown shapetypes the identify mode does not work yet.

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