/[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 2559 - (show annotations)
Tue Feb 8 09:52:56 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: 15966 byte(s)
Changed the GUI. OGR support can now be accessed via the Map menu.
Removed some print commands.

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 = ogr.wkbUnknown
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.feature = self.ogrlayer.GetFeature(shapeid)
58 self.shapeid = shapeid
59 self.geom = self.feature.GetGeometryRef()
60 self.shapetype = self.geom.GetGeometryType()
61
62 def compute_bbox(self):
63 """
64 Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
65 """
66 minx, maxx, miny, maxy = self.geom.GetEnvelope()
67 return (minx, miny, maxx, maxy)
68
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 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 # return shape.append([])
86 #geom = feature.GetGeometryRef()
87
88 if self.geom is None:
89 return shape.append([])
90
91 # if geometry object is of type point or line
92 if self.geom.GetGeometryCount() == 0:
93 points =[]
94 for point in range(self.geom.GetPointCount()):
95 x = self.geom.GetX(point)
96 y = self.geom.GetY(point)
97 points.append((x, y))
98 return [points]
99 # if geometry object is of type polygon or multipolygon
100 for i in range(self.geom.GetGeometryCount()):
101 points = []
102 geometry = self.geom.GetGeometryRef(i)
103 # if geometry object is polygon
104 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 else:
112 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
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 def ShapeType(self):
131 return self.shapetype
132
133
134 class OGRShapeStore:
135
136 """Corresponds to an OGRLayer object, containing features/shapes and
137 providing all methods Thuban needs.
138 """
139
140 def __init__(self, filename, layername, id_column = None):
141 # 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 self.filename = filename
147 self.layername = layername
148
149 self.ogrdatasource = ogr.Open(filename)
150 self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
151
152 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 self._open_ogrlayer(layername)
161
162 def _open_ogrlayer(self, layername):
163 self.numshapes = self.ogrlayer.GetFeatureCount()
164 self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
165
166 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
172 if self.shapetype is not ogr.wkbUnknown:
173 self.shapetype = ogrlib_shapetypes[self.shapetype]
174 #else:
175 # this should be ogr.wkbUnknown, but Thuban does not know how
176 # to handle an unknown shapetype (e.g. Session Tree)
177 #self.shapetype = ogrlib_shapetypes[ogr.wkbPoint]
178
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 """Return the raw data format of the shape data, i.e. RAW_PYTHON"""
200 return RAW_PYTHON
201
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 The method GetFID() returns feature IDs starting from 0.
219 """
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 # 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
231 if ogrlayer.GetSpatialRef():
232 bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())
233
234 ogrlayer.ResetReading()
235 #ogrlayer.SetSpatialFilterRect(left, bottom, right, top)
236 ogrlayer.SetSpatialFilter(bboxpolygon)
237
238 numFeatures = ogrlayer.GetFeatureCount()
239 for feature in range(numFeatures):
240 nextFeature = ogrlayer.GetNextFeature()
241 yield cls(ogrlayer, nextFeature.GetFID())
242
243 ogrlayer.SetSpatialFilter(None)
244 bboxpolygon.Destroy()
245
246 def AllShapes(self):
247 """Return an iterable over the shapes in the shape store."""
248 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
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 def Id_column(self):
271 """Return the id_column."""
272 return self.id_column
273
274 class OGRTable:
275
276 """A Table for an ogr file
277 """
278
279 def __init__(self, ds, layer, id_column):
280 """Initialize the OGRTable.
281
282 ds should be an instance of OGRDatasource.
283 layer should be an instance of OGRLayer.
284 """
285
286 self.datasource = ds
287 self.layer = layer
288 self.tablename = layer.GetName()
289 self.id_column = id_column
290
291 # Map column names and indices to column objects.
292 self.column_map = {}
293
294 # Map feature ids to ordinals.
295 self._map_ords_and_ids()
296
297 self._fetch_table_information()
298
299 def _fetch_table_information(self):
300 """Internal: Update information about the table"""
301 self.columns = []
302
303 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
313 for col in self.columns:
314 self.column_map[col.name] = col
315 self.column_map[col.index] = col
316
317 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 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 The title is currently
343 """
344 return self.tablename
345
346 def Dependencies(self):
347 """Return an empty tuple."""
348 return ()
349
350 def NumColumns(self):
351 """Return the number of columns."""
352 return len(self.columns)
353
354 def Columns(self):
355 """Return all columns."""
356 return self.columns
357
358 def Column(self, col):
359 """Return the column col. col can be either a string or an integer."""
360 return self.column_map[col]
361
362 def HasColumn(self, col):
363 """Return if column col exists. col can be either a string or an
364 integer.
365 """
366 return self.column_map.has_key(col)
367
368 def NumRows(self):
369 """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
374 def RowIdToOrdinal(self, gid):
375 """Return the row ordinal given its id"""
376 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
388 def RowOrdinalToId(self, num):
389 """Return the rowid for given its ordinal"""
390 # 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
403 def ReadRowAsDict(self, row, row_is_ordinal = 0):
404 """Return a dictionary which contains all the fields."""
405 if row_is_ordinal == 1:
406 rowId = self.RowOrdinalToId(row)
407 else:
408 rowId = row
409 layerdef = self.layer.GetLayerDefn()
410 feature = self.layer.GetFeature(rowId)
411 result = {}
412 for i in range(len(self.columns)):
413 fielddef = layerdef.GetFieldDefn(i)
414 if feature is not None:
415 result[self.columns[i].name] = feature.GetField(i)
416 else:
417 result[fielddef.GetName()] = None
418 return result
419
420 def ReadValue(self, row, col, row_is_ordinal = 0):
421 """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
428 def ValueRange(self, col):
429 """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 return (min, max)
442
443 def UniqueValues(self, col):
444 """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 return values
457
458 def SimpleQuery(self, left, comparison, right):
459 """Return the FIDs resulting from the given query."""
460 if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
461 raise ValueError("Comparison operator %r not allowed" %comparison)
462
463 if comparison == "==":
464 comparison = "="
465
466 if isinstance(right, OGRColumn):
467 right_template = right.name
468 else:
469 right_template = right
470
471 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
475 lay = self.datasource.ExecuteSQL(query)
476 result = []
477 while lay is not None:
478 feature = lay.GetNextFeature()
479 if feature is None:
480 break
481 result.append(feature.GetField(0))
482 if lay is not None:
483 self.datasource.ReleaseResultSet(lay)
484 return result
485
486 def Id_column(self):
487 """Return the id_column."""
488 return self.id_column
489
490
491 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