/[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 2437 - (hide 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 nhueffme 2435 # 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 silke 2437 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 nhueffme 2435
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