/[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 2437 - (show annotations)
Wed Dec 8 17:37:30 2004 UTC (20 years, 3 months ago) by silke
Original Path: trunk/thuban/Extensions/ogr/ogrshapes.py
File MIME type: text/x-python
File size: 11235 byte(s)
Substituted ogr-method CloseRings because it is not available in all versions of ogr

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