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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2549 - (show 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 # Copyright (C) 2004 by Intevation GmbH
2 # Authors:
3 # Nina Hueffmeyer <[email protected]>
4 #
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 SHAPETYPE_UNKNOWN = "unknown"
30
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 ogr.wkbLineString: SHAPETYPE_ARC,
43 ogr.wkbPoint: SHAPETYPE_POINT,
44 ogr.wkbUnknown: SHAPETYPE_UNKNOWN}
45
46 fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,
47 ogr.OFTInteger: table.FIELDTYPE_INT,
48 ogr.OFTReal: table.FIELDTYPE_DOUBLE}
49
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 shape = self.ogrlayer.GetFeature(self.shapeid)
64 geom = shape.GetGeometryRef()
65 minx, maxx, miny, maxy = geom.GetEnvelope()
66 return (minx, miny, maxx, maxy)
67
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 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 feature = self.ogrlayer.GetFeature(self.shapeid)
83
84 if feature is None:
85 print "feature is none.........................."
86 return shape.append([])
87 geom = feature.GetGeometryRef()
88
89 if geom is None:
90 print "geom is none................................"
91 return shape.append([])
92
93 # 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 print points
101 return [points]
102 # if geometry object is of type polygon or multipolygon
103 for i in range(geom.GetGeometryCount()):
104 points = []
105 geometry = geom.GetGeometryRef(i)
106 # if geometry object is polygon
107 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 else:
115 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 print shape
124 return shape
125
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 """Corresponds to an OGRLayer object, containing features/shapes and
138 providing all methods Thuban needs.
139 """
140
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 self.filename = filename
148 self.layername = layername
149
150 self.ogrdatasource = ogr.Open(filename)
151 self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
152
153 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 self._open_ogrlayer(layername)
162
163 def _open_ogrlayer(self, layername):
164 self.numshapes = self.ogrlayer.GetFeatureCount()
165 self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
166
167 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
173 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
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 """Return the raw data format of the shape data, i.e. RAW_PYTHON"""
201 return RAW_PYTHON
202
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 The method GetFID() returns feature IDs starting from 0.
220 """
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 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 # 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
236 if ogrlayer.GetSpatialRef():
237 bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())
238
239 ogrlayer.ResetReading()
240 #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
241 ogrlayer.SetSpatialFilter(bboxpolygon)
242 numFeatures = ogrlayer.GetFeatureCount()
243 print numFeatures
244 for feature in range(numFeatures):
245 nextFeature = ogrlayer.GetNextFeature()
246 yield cls(ogrlayer, nextFeature.GetFID())
247 ogrlayer.SetSpatialFilter(None)
248 bboxpolygon.Destroy()
249
250 def AllShapes(self):
251 """Return an iterable over the shapes in the shape store."""
252 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
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 def __init__(self, ds, layer, id_column):
281 """Initialize the OGRTable.
282
283 ds should be an instance of OGRDatasource.
284 layer should be an instance of OGRLayer.
285 """
286
287 self.datasource = ds
288 self.layer = layer
289 self.tablename = layer.GetName()
290 self.id_column = id_column
291
292 # Map column names and indices to column objects.
293 self.column_map = {}
294
295 # Map feature ids to ordinals.
296 self._map_ords_and_ids()
297
298 self._fetch_table_information()
299
300 def _fetch_table_information(self):
301 """Internal: Update information about the table"""
302 self.columns = []
303
304 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
314 for col in self.columns:
315 self.column_map[col.name] = col
316 self.column_map[col.index] = col
317
318 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 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 The title is currently
344 """
345 return self.tablename
346
347 def Dependencies(self):
348 """Return an empty tuple."""
349 return ()
350
351 def NumColumns(self):
352 """Return the number of columns."""
353 return len(self.columns)
354
355 def Columns(self):
356 """Return all columns."""
357 return self.columns
358
359 def Column(self, col):
360 """Return the column col. col can be either a string or an integer."""
361 return self.column_map[col]
362
363 def HasColumn(self, col):
364 """Return if column col exists. col can be either a string or an
365 integer.
366 """
367 return self.column_map.has_key(col)
368
369 def NumRows(self):
370 """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
375 def RowIdToOrdinal(self, gid):
376 """Return the row ordinal given its id"""
377 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
389 def RowOrdinalToId(self, num):
390 """Return the rowid for given its ordinal"""
391 # 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
404 def ReadRowAsDict(self, row, row_is_ordinal = 0):
405 """Return a dictionary which contains all the fields."""
406 if row_is_ordinal == 1:
407 rowId = self.RowOrdinalToId(row)
408 else:
409 rowId = row
410 layerdef = self.layer.GetLayerDefn()
411 feature = self.layer.GetFeature(rowId)
412 result = {}
413 for i in range(len(self.columns)):
414 fielddef = layerdef.GetFieldDefn(i)
415 if feature is not None:
416 result[self.columns[i].name] = feature.GetField(i)
417 else:
418 result[fielddef.GetName()] = None
419 return result
420
421 def ReadValue(self, row, col, row_is_ordinal = 0):
422 """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
429 def ValueRange(self, col):
430 """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 return (min, max)
443
444 def UniqueValues(self, col):
445 """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 return values
458
459 def SimpleQuery(self, left, comparison, right):
460 """Return the FIDs resulting from the given query."""
461 if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
462 raise ValueError("Comparison operator %r not allowed" %comparison)
463
464 if comparison == "==":
465 comparison = "="
466
467 if isinstance(right, OGRColumn):
468 right_template = right.name
469 else:
470 right_template = right
471
472 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
476 lay = self.datasource.ExecuteSQL(query)
477 result = []
478 while lay is not None:
479 feature = lay.GetNextFeature()
480 if feature is None:
481 break
482 result.append(feature.GetField(0))
483 if lay is not None:
484 self.datasource.ReleaseResultSet(lay)
485 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