/[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 2493 - (hide 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 nhueffme 2435 # Copyright (C) 2004 by Intevation GmbH
2     # Authors:
3 nhueffme 2493 # Nina Hueffmeyer <[email protected]>
4 nhueffme 2435 #
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 nhueffme 2493 ogr.wkbLineString: SHAPETYPE_ARC,
42     ogr.wkbPoint: SHAPETYPE_POINT}
43 nhueffme 2435
44     fieldtype_map = {ogr.OFTString: table.FIELDTYPE_STRING,
45 nhueffme 2493 ogr.OFTInteger: table.FIELDTYPE_INT,
46     ogr.OFTReal: table.FIELDTYPE_DOUBLE}
47 nhueffme 2435
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 nhueffme 2493 shape = self.ogrlayer.GetFeature(self.shapeid)
62     geom = shape.GetGeometryRef()
63     minx, maxx, miny, maxy = geom.GetEnvelope()
64     return (minx, miny, maxx, maxy)
65 nhueffme 2435
66     def ShapeID(self):
67     return self.shapeid
68    
69 nhueffme 2493 # diese Methode funktioniert vielleicht noch nicht für andere Formate
70     #als shp
71 nhueffme 2435 #(wenn ein polygon aus mehreren
72 nhueffme 2493 # Ringen besteht o.ä., hat ein Geometry-Objekt mehr als einen
73     #GeometryRef().---------
74 nhueffme 2435 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 nhueffme 2493 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 nhueffme 2435
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 nhueffme 2493 """Corresponds to an OGRLayer object, containing features/shapes and
122     providing all methods Thuban needs.
123     """
124 nhueffme 2435
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 nhueffme 2493 self.filename = os.path.abspath(filename)
132     self.layername = layername
133 nhueffme 2435
134 nhueffme 2493 self.ogrdatasource = ogr.Open(self.filename)
135     self.ogrlayer = (self.ogrdatasource).GetLayerByName(layername)
136     self.table = OGRTable(self.ogrdatasource, self.ogrlayer)
137 nhueffme 2435
138     self._open_ogrlayer(layername)
139    
140     def _open_ogrlayer(self, layername):
141 nhueffme 2493 self.numshapes = self.ogrlayer.GetFeatureCount()
142     self.shapetype = self.ogrlayer.GetLayerDefn().GetGeomType()
143     extent = self.ogrlayer.GetExtent()
144 nhueffme 2435
145 nhueffme 2493 if extent:
146     self.bbox = [extent[0], extent[2], extent[1], extent[3]]
147     else:
148     self.bbox = None
149 nhueffme 2435
150 nhueffme 2493 self.shapetype = ogrlib_shapetypes[self.shapetype]
151 nhueffme 2435
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 nhueffme 2493 """Return the raw data format of the shape data, i.e. RAW_PYTHON"""
173     return RAW_PYTHON
174 nhueffme 2435
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 nhueffme 2493 The method GetFID() returns feature IDs starting from 0.
192 nhueffme 2435 """
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 nhueffme 2493 # 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 nhueffme 2435
205 nhueffme 2493 if ogrlayer.GetSpatialRef():
206     bboxpolygon.AssignSpatialReference(ogrlayer.GetSpatialRef())
207 nhueffme 2435
208 nhueffme 2493 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 nhueffme 2435
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 nhueffme 2493 ds should be an instance of OGRDatasource.
248     layer should be an instance of OGRLayer.
249 nhueffme 2435 """
250    
251     self.datasource = ds
252     self.layer = layer
253 nhueffme 2493 self.tablename = layer.GetName()
254 nhueffme 2435
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 nhueffme 2493 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 nhueffme 2435
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 nhueffme 2493 """Return the number of columns."""
295 nhueffme 2435 return len(self.columns)
296    
297     def Columns(self):
298 nhueffme 2493 """Return all columns."""
299 nhueffme 2435 return self.columns
300    
301     def Column(self, col):
302 nhueffme 2493 """Return the column col. col can be either a string or an integer."""
303 nhueffme 2435 return self.column_map[col]
304    
305     def HasColumn(self, col):
306 nhueffme 2493 """Return if column col exists. col can be either a string or an
307     integer.
308     """
309 nhueffme 2435 return self.column_map.has_key(col)
310    
311     def NumRows(self):
312 nhueffme 2493 """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 nhueffme 2435
317     def RowIdToOrdinal(self, gid):
318     """Return the row ordinal given its id"""
319 nhueffme 2493 return self.layer.GetFeature(gid).GetFID()
320 nhueffme 2435
321     def RowOrdinalToId(self, num):
322     """Return the rowid for given its ordinal"""
323 nhueffme 2493 return self.layer.GetFeature(num).GetFID()
324 nhueffme 2435
325     def ReadRowAsDict(self, row, row_is_ordinal = 0):
326 nhueffme 2493 """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 nhueffme 2435 return result
334    
335     def ReadValue(self, row, col, row_is_ordinal = 0):
336 nhueffme 2493 """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 nhueffme 2435
343     def ValueRange(self, col):
344 nhueffme 2493 """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 nhueffme 2435 return (min, max)
357    
358     def UniqueValues(self, col):
359 nhueffme 2493 """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 nhueffme 2435 return values
372    
373     def SimpleQuery(self, left, comparison, right):
374 nhueffme 2493 """Return the FIDs resulting from the given query."""
375 nhueffme 2435 if comparison not in ("==", "!=", "<", "<=", ">=", ">"):
376 nhueffme 2493 raise ValueError("Comparison operator %r not allowed" %comparison)
377 nhueffme 2435
378     if comparison == "==":
379     comparison = "="
380    
381     if isinstance(right, OGRColumn):
382     right_template = right.name
383     else:
384     right_template = right
385    
386 nhueffme 2493 query = ("SELECT FID FROM %s WHERE '%s' %s %s ORDER BY FID"
387     % (self.tablename,left.name, comparison, right_template))
388 nhueffme 2435
389     lay = self.datasource.ExecuteSQL(query)
390 nhueffme 2493 result = []
391     while lay is not None:
392 nhueffme 2435 feature = lay.GetNextFeature()
393     if feature is None:
394     break
395     result.append(feature.GetField(0))
396 nhueffme 2493 self.datasource.ReleaseResultSet(lay)
397 nhueffme 2435 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