/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/data.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/Model/data.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1972 - (hide annotations)
Mon Nov 24 19:23:08 2003 UTC (21 years, 3 months ago) by bh
Original Path: trunk/thuban/Thuban/Model/data.py
File MIME type: text/x-python
File size: 9345 byte(s)
(ShapefileStore._open_shapefile)
(ShapefileStore.__init__): Factor opening the shapefile into a
separate method (the new _open_shapefile). This makes the code a
bit more readable but the real reason is that it makes some evil
hacks easier. :-)

1 bh 723 # Copyright (C) 2003 by Intevation GmbH
2     # Authors:
3     # Bernhard Herzog <[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     """Data source abstractions"""
9    
10 bh 1593 from __future__ import generators
11    
12 bh 723 __version__ = "$Revision$"
13     # $Source$
14     # $Id$
15    
16     import os
17 bh 984 import weakref
18 bh 1535 from math import ceil, log
19 bh 723
20     import shapelib
21 bh 1535 import shptree
22 bh 723 import table
23 bh 765 import transientdb
24 bh 723
25 jonathan 1261 from Thuban import _
26 bh 765
27 bh 1535 # Shape type constants
28     SHAPETYPE_POLYGON = "polygon"
29     SHAPETYPE_ARC = "arc"
30     SHAPETYPE_POINT = "point"
31 jonathan 1261
32 bh 1535 # mapping from shapelib shapetype constants to our constants
33     shapelib_shapetypes = {shapelib.SHPT_POLYGON: SHAPETYPE_POLYGON,
34     shapelib.SHPT_ARC: SHAPETYPE_ARC,
35     shapelib.SHPT_POINT: SHAPETYPE_POINT}
36    
37 bh 1559 #
38     # Raw shape data formats
39     #
40 bh 1535
41 bh 1559 # Raw data is the same as that returned by the points method.
42     RAW_PYTHON = "RAW_PYTHON"
43 bh 1535
44 bh 1559 # Raw data is a shapefile. The Shape object will use the shapeid as the
45     # raw data.
46     RAW_SHAPEFILE = "RAW_SHAPEFILE"
47 bh 1535
48 bh 1605 # Raw data in well-known text format
49     RAW_WKT = "RAW_WKT"
50 bh 1535
51 bh 1605
52 bh 1559 class ShapefileShape:
53    
54     """Represent one shape of a shapefile"""
55    
56     def __init__(self, shapefile, shapeid):
57     self.shapefile = shapefile
58     self.shapeid = shapeid
59    
60 bh 1535 def compute_bbox(self):
61 bh 1559 """
62     Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
63     """
64 bh 1535 xs = []
65     ys = []
66 bh 1559 for part in self.Points():
67 bh 1551 for x, y in part:
68     xs.append(x)
69     ys.append(y)
70 bh 1559 return (min(xs), min(ys), max(xs), max(ys))
71 bh 1535
72 bh 1593 def ShapeID(self):
73     return self.shapeid
74    
75 bh 1559 def Points(self):
76     """Return the coordinates of the shape as a list of lists of pairs"""
77     shape = self.shapefile.read_object(self.shapeid)
78     points = shape.vertices()
79     if self.shapefile.info()[1] == shapelib.SHPT_POINT:
80     points = [points]
81     return points
82 bh 1535
83 bh 1559 def RawData(self):
84     """Return the shape id to use with the shapefile"""
85     return self.shapeid
86 bh 1535
87 bh 1559 def Shapefile(self):
88     """Return the shapefile object"""
89     return self.shapefile
90 bh 1535
91    
92 bh 984 class ShapeTable(transientdb.AutoTransientTable):
93    
94     """A Table that depends on a ShapefileStore
95    
96     Intended use is by the ShapefileStore for the table associated with
97     the shapefiles.
98     """
99    
100     def __init__(self, store, db, table):
101     """Initialize the ShapeTable.
102    
103     Parameters:
104     store -- the ShapefileStore the table is to depend on
105     db -- The transient database to use
106     table -- the table
107     """
108     transientdb.AutoTransientTable.__init__(self, db, table)
109     self.store = weakref.ref(store)
110    
111     def Dependencies(self):
112     """Return a tuple containing the shapestore"""
113     return (self.store(),)
114    
115    
116 bh 723 class ShapefileStore:
117    
118     """Combine a shapefile and the corresponding DBF file into one object"""
119    
120     def __init__(self, session, filename):
121     # Make the filename absolute. The filename will be
122     # interpreted relative to that anyway, but when saving a
123     # session we need to compare absolute paths and it's usually
124     # safer to always work with absolute paths.
125     self.filename = os.path.abspath(filename)
126    
127 bh 765 self.dbftable = table.DBFTable(filename)
128 bh 984 self.table = ShapeTable(self, session.TransientDB(), self.dbftable)
129 bh 1972 self._open_shapefile()
130 bh 723
131 bh 1972 def _open_shapefile(self):
132     self.shapefile = shapelib.ShapeFile(self.filename)
133 bh 1535 self.numshapes, shapetype, mins, maxs = self.shapefile.info()
134     if self.numshapes:
135     self.bbox = mins[:2] + maxs[:2]
136     else:
137     self.bbox = None
138     self.shapetype = shapelib_shapetypes[shapetype]
139    
140     # estimate a good depth for the quad tree. Each depth multiplies
141     # the number of nodes by four, therefore we basically take the
142     # base 4 logarithm of the number of shapes.
143     if self.numshapes < 4:
144     maxdepth = 1
145     else:
146     maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
147    
148     self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
149     maxdepth)
150    
151 bh 723 def Table(self):
152 bh 984 """Return the table containing the attribute data"""
153 bh 723 return self.table
154    
155     def Shapefile(self):
156 bh 984 """Return the shapefile object"""
157 bh 723 return self.shapefile
158 bh 765
159 bh 984 def FileName(self):
160     """Return the filename used to open the shapefile"""
161     return self.filename
162 bh 765
163 bh 984 def FileType(self):
164     """Return the filetype. This is always the string 'shapefile'"""
165     return "shapefile"
166    
167 bh 1535 def ShapeType(self):
168     """Return the type of the shapes in the shapestore.
169    
170     This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
171     """
172     return self.shapetype
173    
174 bh 1559 def RawShapeFormat(self):
175     """Return the raw data format of the shape data, i.e. RAW_SHAPEFILE"""
176     return RAW_SHAPEFILE
177    
178 bh 1535 def NumShapes(self):
179     """Return the number of shapes in the shape store"""
180     return self.numshapes
181    
182 bh 984 def Dependencies(self):
183     """Return the empty tuple.
184    
185     The ShapefileStore doesn't depend on anything else.
186     """
187     return ()
188    
189 bh 1074 def OrigShapeStore(self):
190     """Return None.
191 bh 984
192 bh 1074 The ShapefileStore was not derived from another shapestore.
193     """
194     return None
195    
196 bh 1535 def BoundingBox(self):
197     """Return the bounding box of the shapes in the shapestore.
198 bh 1074
199 bh 1535 The coordinate system used is whatever was used in the shapefile.
200     If the shapefile is empty, return None.
201     """
202     return self.bbox
203    
204 bh 1593 def ShapesInRegion(self, bbox):
205     """Return an iterable over the shapes that overlap the bounding box.
206 bh 1535
207 bh 1593 The bbox parameter should be the bounding box as a tuple in the
208     form (minx, miny, maxx, maxy) in the coordinate system of the
209     shape store.
210 bh 1535 """
211 bh 1921 # Bind a few globals to locals to make it a bit faster
212     cls = ShapefileShape
213     shapefile = self.shapefile
214    
215 bh 1593 left, bottom, right, top = bbox
216     for i in self.shapetree.find_shapes((left, bottom), (right, top)):
217 bh 1921 yield cls(shapefile, i)
218 bh 1535
219 bh 1593 def AllShapes(self):
220     """Return an iterable over the shapes in the shape store."""
221     for i in xrange(self.NumShapes()):
222     yield ShapefileShape(self.shapefile, i)
223    
224 bh 1535 def Shape(self, index):
225     """Return the shape with index index"""
226 bh 1559 return ShapefileShape(self.shapefile, index)
227 bh 1535
228    
229    
230 bh 984 class DerivedShapeStore:
231    
232     """A ShapeStore derived from other shapestores or tables"""
233    
234     def __init__(self, shapestore, table):
235     """Initialize the derived shapestore.
236    
237     The arguments are a shapestore for the shapedata and a table for
238     the tabular data.
239 jonathan 1261
240     Raises ValueError if the number of shapes in the shapestore
241     is different from the number of rows in the table.
242 bh 984 """
243 jonathan 1261
244     numShapes = shapestore.Shapefile().info()[0]
245     if numShapes != table.NumRows():
246     raise ValueError(_("Table not compatible with shapestore."))
247    
248 bh 984 self.shapestore = shapestore
249     self.table = table
250    
251     def Table(self):
252     """Return the table"""
253     return self.table
254    
255     def Shapefile(self):
256 bh 1074 """Return the shapefile of the underlying shapestore"""
257 bh 984 return self.shapestore.Shapefile()
258    
259     def Dependencies(self):
260     """Return a tuple containing the shapestore and the table"""
261     return (self.shapestore, self.table)
262    
263 bh 1074 def OrigShapeStore(self):
264     """
265     Return the original shapestore the derived store was instantiated with
266     """
267     return self.shapestore
268 bh 1535
269     def Shape(self, index):
270     """Return the shape with index index"""
271     return self.shapestore.Shape(index)
272    
273     def ShapesInRegion(self, bbox):
274     """Return the ids of the shapes that overlap the box.
275    
276     This method is simply delegated to the shapestore the
277     DerivedShapeStore was instantiated with.
278     """
279     return self.shapestore.ShapesInRegion(bbox)
280    
281 bh 1593 def AllShapes(self):
282     """Return an iterable over the shapes in the shape store.
283    
284     This method is simply delegated to the shapestore the
285     DerivedShapeStore was instantiated with.
286     """
287     return self.shapestore.AllShapes()
288    
289 bh 1535 def ShapeType(self):
290     """Return the type of the shapes in the layer.
291    
292     This method is simply delegated to the shapestore the
293     DerivedShapeStore was instantiated with.
294     """
295     return self.shapestore.ShapeType()
296    
297 bh 1564 def RawShapeFormat(self):
298     """Return the raw data format of the shapes.
299    
300     This method is simply delegated to the shapestore the
301     DerivedShapeStore was instantiated with.
302     """
303     return self.shapestore.RawShapeFormat()
304    
305 bh 1535 def NumShapes(self):
306     """Return the number of shapes in the shapestore."""
307     return self.shapestore.NumShapes()
308    
309     def BoundingBox(self):
310     """Return the bounding box of the shapes in the shapestore.
311    
312     This method is simply delegated to the shapestore the
313     DerivedShapeStore was instantiated with.
314     """
315     return self.shapestore.BoundingBox()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26