/[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 2493 - (show annotations)
Mon Dec 20 14:13:57 2004 UTC (20 years, 2 months ago) by nhueffme
Original Path: trunk/thuban/Extensions/ogr/ogrshapes.py
File MIME type: text/x-python
File size: 13034 byte(s)
Fixed some issues from Bernhard.

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
30 def has_ogr_support():
31 """Return whether this Thuban instance supports ogr file formats
32
33 Having OGR support means that the ogr module can be
34 imported.
35 """
36 return ogr is not None
37
38 if ogr is not None:
39 # mapping from ogr-lib shapetype and table constants to our constants
40 ogrlib_shapetypes = {ogr.wkbPolygon: SHAPETYPE_POLYGON,
41 ogr.wkbLineString: SHAPETYPE_ARC,
42 ogr.wkbPoint: SHAPETYPE_POINT}
43
44 fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,
45 ogr.OFTInteger: table.FIELDTYPE_INT,
46 ogr.OFTReal: table.FIELDTYPE_DOUBLE}
47
48
49 class OGRShape:
50
51 """Represent one shape of an OGRShapeStore"""
52
53 def __init__(self, ogrlayer, shapeid):
54 self.ogrlayer = ogrlayer
55 self.shapeid = shapeid
56
57 def compute_bbox(self):
58 """
59 Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
60 """
61 shape = self.ogrlayer.GetFeature(self.shapeid)
62 geom = shape.GetGeometryRef()
63 minx, maxx, miny, maxy = geom.GetEnvelope()
64 return (minx, miny, maxx, maxy)
65
66 def ShapeID(self):
67 return self.shapeid
68
69 # diese Methode funktioniert vielleicht noch nicht für andere Formate
70 #als shp
71 #(wenn ein polygon aus mehreren
72 # Ringen besteht o.ä., hat ein Geometry-Objekt mehr als einen
73 #GeometryRef().---------
74 def Points(self):
75 """Return the coordinates of the shape as a list of lists of pairs"""
76 feature = self.ogrlayer.GetFeature(self.shapeid)
77 geom = feature.GetGeometryRef()
78 shape = []
79 # if geometry object is of type point or line
80 if geom.GetGeometryCount() == 0:
81 points =[]
82 for point in range(geom.GetPointCount()):
83 x = geom.GetX(point)
84 y = geom.GetY(point)
85 points.append((x, y))
86 return [points]
87 # if geometry object is of type polygon or multipolygon
88 for i in range(geom.GetGeometryCount()):
89 points = []
90 geometry = geom.GetGeometryRef(i)
91 # if geometry object is polygon
92 if geometry.GetGeometryCount() == 0:
93 for point in range(geometry.GetPointCount()):
94 x = geometry.GetX(point)
95 y = geometry.GetY(point)
96 points.append((x, y))
97 shape.append(points)
98 # if geometry object is of type multipolygon
99 else:
100 for j in range(geometry.GetGeometryCount()):
101 points = []
102 subgeom = geometry.GetGeometryRef(j)
103 for point in range(subgeom.GetPointCount()):
104 x = subgeom.GetX(point)
105 y = subgeom.GetY(point)
106 points.append((x, y))
107 shape.append(points)
108 return shape
109
110 def RawData(self):
111 """Return the shape id to use with the shapestore"""
112 return self.shapeid
113
114 def OGRLayer(self):
115 """Return the ogrlayer object"""
116 return self.ogrlayer
117
118
119 class OGRShapeStore:
120
121 """Corresponds to an OGRLayer object, containing features/shapes and
122 providing all methods Thuban needs.
123 """
124
125 def __init__(self, session, filename, layername):
126 # Make the filename absolute. The filename will be
127 # interpreted relative to that anyway, but when saving a
128 # session we need to compare absolute paths and it's usually
129 # safer to always work with absolute paths.
130
131 self.filename = os.path.abspath(filename)
132 self.layername = layername
133
134 self.ogrdatasource = ogr.Open(self.filename)
135 self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
136 self.table = OGRTable(self.ogrdatasource, self.ogrlayer)
137
138 self._open_ogrlayer(layername)
139
140 def _open_ogrlayer(self, layername):
141 self.numshapes = self.ogrlayer.GetFeatureCount()
142 self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
143 extent = self.ogrlayer.GetExtent()
144
145 if extent:
146 self.bbox = [extent[0], extent[2], extent[1], extent[3]]
147 else:
148 self.bbox = None
149
150 self.shapetype = ogrlib_shapetypes[self.shapetype]
151
152 def OGRLayer(self):
153 """Return the OGRLayer object"""
154 return self.ogrlayer
155
156 def FileName(self):
157 """Return the filename used to open the file"""
158 return self.filename
159
160 def FileType(self):
161 """Return the filetype. This is always the string 'ogr-file'"""
162 return "ogr-file"
163
164 def ShapeType(self):
165 """Return the type of the shapes in the shapestore.
166
167 This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
168 """
169 return self.shapetype
170
171 def RawShapeFormat(self):
172 """Return the raw data format of the shape data, i.e. RAW_PYTHON"""
173 return RAW_PYTHON
174
175 def NumShapes(self):
176 """Return the number of shapes in the shape store"""
177 return self.numshapes
178
179 def BoundingBox(self):
180 """Return the bounding box of the shapes in the shapestore.
181 """
182 return self.bbox
183
184 def ShapesInRegion(self, bbox):
185 """Return an iterable over the shapes that overlap the bounding box.
186
187 The bbox parameter should be the bounding box as a tuple in the
188 form (minx, miny, maxx, maxy) in the coordinate system of the
189 shape store.
190
191 The method GetFID() returns feature IDs starting from 0.
192 """
193 # Bind a few globals to locals to make it a bit faster
194 cls = OGRShape
195 ogrlayer = self.ogrlayer
196
197 left, bottom, right, top = bbox
198
199 # create a geometry which can be passed to the layer as spatial filter
200 bboxpolygon = ogr.CreateGeometryFromWkt(
201 ('Polygon((%s %s, %s %s, %s %s,%s %s, %s %s))'
202 %(left, bottom, left, top, right, top,
203 right, bottom, left, bottom)))
204
205 if ogrlayer.GetSpatialRef():
206 bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())
207
208 ogrlayer.ResetReading()
209 ogrlayer.SetSpatialFilter(bboxpolygon)
210 numFeatures = ogrlayer.GetFeatureCount()
211 for feature in range(numFeatures):
212 nextFeature = ogrlayer.GetNextFeature()
213 yield cls(ogrlayer, nextFeature.GetFID())
214 ogrlayer.SetSpatialFilter(None)
215 bboxpolygon.Destroy()
216
217 def AllShapes(self):
218 """Return an iterable over the shapes in the shape store."""
219 for i in xrange(self.NumShapes()):
220 yield OGRShape(self.ogrlayer, i)
221
222 def Shape(self, index):
223 """Return the shape with index index"""
224 return OGRShape(self.ogrlayer, index)
225
226 def Table(self):
227 """Return the table containing the attribute data"""
228 return self.table
229
230 def Dependencies(self):
231 """Return the empty tuple."""
232 return ()
233
234 def OrigShapeStore(self):
235 """Return None."""
236 return None
237
238
239 class OGRTable:
240
241 """A Table for an ogr file
242 """
243
244 def __init__(self, ds, layer):
245 """Initialize the OGRTable.
246
247 ds should be an instance of OGRDatasource.
248 layer should be an instance of OGRLayer.
249 """
250
251 self.datasource = ds
252 self.layer = layer
253 self.tablename = layer.GetName()
254
255 # Map column names and indices to column objects.
256 self.column_map = {}
257
258 self._fetch_table_information()
259
260 def _fetch_table_information(self):
261 """Internal: Update information about the table"""
262 self.columns = []
263
264 layerdefn = self.layer.GetLayerDefn()
265 for i in range(layerdefn.GetFieldCount()):
266 fielddef = layerdefn.GetFieldDefn(i)
267 fieldname = fielddef.GetName()
268 fieldtype = fieldtype_map[fielddef.GetType()]
269 fieldindex = layerdefn.GetFieldIndex(fieldname)
270 col = OGRColumn(fieldname, fieldtype, fieldindex)
271 if col is not None:
272 self.columns.append(col)
273
274 for col in self.columns:
275 self.column_map[col.name] = col
276 self.column_map[col.index] = col
277
278 def TableName(self):
279 """Return the name of the table, which is the name of the layer"""
280 return self.tablename
281
282 def Title(self):
283 """Return the title of the table.
284
285 The title is currently fixed and equal to the tablename
286 """
287 return self.tablename
288
289 def Dependencies(self):
290 """Return an empty tuple."""
291 return ()
292
293 def NumColumns(self):
294 """Return the number of columns."""
295 return len(self.columns)
296
297 def Columns(self):
298 """Return all columns."""
299 return self.columns
300
301 def Column(self, col):
302 """Return the column col. col can be either a string or an integer."""
303 return self.column_map[col]
304
305 def HasColumn(self, col):
306 """Return if column col exists. col can be either a string or an
307 integer.
308 """
309 return self.column_map.has_key(col)
310
311 def NumRows(self):
312 """Return the number of rows in the table, which equals the number of
313 features in the layer.
314 """
315 return self.layer.GetFeatureCount()
316
317 def RowIdToOrdinal(self, gid):
318 """Return the row ordinal given its id"""
319 return self.layer.GetFeature(gid).GetFID()
320
321 def RowOrdinalToId(self, num):
322 """Return the rowid for given its ordinal"""
323 return self.layer.GetFeature(num).GetFID()
324
325 def ReadRowAsDict(self, row, row_is_ordinal = 0):
326 """Return a dictionary which contains all the fields."""
327 layerdef = self.layer.GetLayerDefn()
328 feature = self.layer.GetFeature(row)
329 result = {}
330 for i in range(feature.GetFieldCount()):
331 fielddef = layerdef.GetFieldDefn(i)
332 result[fielddef.GetName()] = feature.GetField(i)
333 return result
334
335 def ReadValue(self, row, col, row_is_ordinal = 0):
336 """Return the requested value."""
337 if col is None:
338 return None
339 else:
340 feature = self.layer.GetFeature(row)
341 return feature.GetField(col)
342
343 def ValueRange(self, col):
344 """Return the value range of the given column (given as string)."""
345 result = self.datasource.ExecuteSQL("SELECT min(%s), max(%s) FROM %s"
346 %(col, col, self.layer.GetName()))
347 result.ResetReading()
348 feature = result.GetNextFeature()
349 try:
350 min = feature.GetField(0)
351 max = feature.GetField(1)
352 except:
353 min = 0
354 max = 0
355 self.datasource.ReleaseResultSet(result)
356 return (min, max)
357
358 def UniqueValues(self, col):
359 """Return all the values being found in the column (given as string).
360 """
361 result = self.datasource.ExecuteSQL((
362 "SELECT DISTINCT %s FROM %s ORDER BY %s"
363 %(col,self.layer.GetName(),col)))
364 values = []
365 while 1:
366 feature = result.GetNextFeature()
367 if feature is None:
368 break
369 values.append(feature.GetField(0))
370 self.datasource.ReleaseResultSet(result)
371 return values
372
373 def SimpleQuery(self, left, comparison, right):
374 """Return the FIDs resulting from the given query."""
375 if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
376 raise ValueError("Comparison operator %r not allowed" %comparison)
377
378 if comparison == "==":
379 comparison = "="
380
381 if isinstance(right, OGRColumn):
382 right_template = right.name
383 else:
384 right_template = right
385
386 query = ("SELECT FID FROM %s WHERE '%s' %s %s ORDER BY FID"
387 % (self.tablename,left.name, comparison, right_template))
388
389 lay = self.datasource.ExecuteSQL(query)
390 result = []
391 while lay is not None:
392 feature = lay.GetNextFeature()
393 if feature is None:
394 break
395 result.append(feature.GetField(0))
396 self.datasource.ReleaseResultSet(lay)
397 return result
398
399
400 class OGRColumn:
401
402 """Column description for a table for an ogr file
403 """
404
405 def __init__(self, name, type, index):
406 self.name = name
407 self.type = type
408 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