/[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 1605 - (hide annotations)
Tue Aug 19 11:00:40 2003 UTC (21 years, 6 months ago) by bh
Original Path: trunk/thuban/Thuban/Model/data.py
File MIME type: text/x-python
File size: 9171 byte(s)
Add very basic postgis database support and the corresponding test
cases. The test cases require a PostgreSQL + postgis installation
but no existing database. The database will be created
automatically by the test cases

* test/README: Add note about skipped tests and the requirements
of the postgis tests.

* Thuban/Model/postgisdb.py: New. Basic postgis database support.

* test/test_postgis_db.py: New. Test cases for the postgis
support.

* Thuban/Model/wellknowntext.py: New. Parser for well-known-text
format

* test/test_wellknowntext.py: New. Test cases for the
wellknowntext parser

* test/postgissupport.py: New. Support module for tests involving
a postgis database.

* test/support.py (execute_as_testsuite): Shut down the postmaster
if it's still running after the tests

* Thuban/Model/data.py (RAW_WKT): New constant for raw data in
well known text format

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     self.shapefile = shapelib.ShapeFile(self.filename)
128 bh 765 self.dbftable = table.DBFTable(filename)
129 bh 984 self.table = ShapeTable(self, session.TransientDB(), self.dbftable)
130 bh 723
131 bh 1535 self.numshapes, shapetype, mins, maxs = self.shapefile.info()
132     if self.numshapes:
133     self.bbox = mins[:2] + maxs[:2]
134     else:
135     self.bbox = None
136     self.shapetype = shapelib_shapetypes[shapetype]
137    
138     # estimate a good depth for the quad tree. Each depth multiplies
139     # the number of nodes by four, therefore we basically take the
140     # base 4 logarithm of the number of shapes.
141     if self.numshapes < 4:
142     maxdepth = 1
143     else:
144     maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
145    
146     self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
147     maxdepth)
148    
149 bh 723 def Table(self):
150 bh 984 """Return the table containing the attribute data"""
151 bh 723 return self.table
152    
153     def Shapefile(self):
154 bh 984 """Return the shapefile object"""
155 bh 723 return self.shapefile
156 bh 765
157 bh 984 def FileName(self):
158     """Return the filename used to open the shapefile"""
159     return self.filename
160 bh 765
161 bh 984 def FileType(self):
162     """Return the filetype. This is always the string 'shapefile'"""
163     return "shapefile"
164    
165 bh 1535 def ShapeType(self):
166     """Return the type of the shapes in the shapestore.
167    
168     This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
169     """
170     return self.shapetype
171    
172 bh 1559 def RawShapeFormat(self):
173     """Return the raw data format of the shape data, i.e. RAW_SHAPEFILE"""
174     return RAW_SHAPEFILE
175    
176 bh 1535 def NumShapes(self):
177     """Return the number of shapes in the shape store"""
178     return self.numshapes
179    
180 bh 984 def Dependencies(self):
181     """Return the empty tuple.
182    
183     The ShapefileStore doesn't depend on anything else.
184     """
185     return ()
186    
187 bh 1074 def OrigShapeStore(self):
188     """Return None.
189 bh 984
190 bh 1074 The ShapefileStore was not derived from another shapestore.
191     """
192     return None
193    
194 bh 1535 def BoundingBox(self):
195     """Return the bounding box of the shapes in the shapestore.
196 bh 1074
197 bh 1535 The coordinate system used is whatever was used in the shapefile.
198     If the shapefile is empty, return None.
199     """
200     return self.bbox
201    
202 bh 1593 def ShapesInRegion(self, bbox):
203     """Return an iterable over the shapes that overlap the bounding box.
204 bh 1535
205 bh 1593 The bbox parameter should be the bounding box as a tuple in the
206     form (minx, miny, maxx, maxy) in the coordinate system of the
207     shape store.
208 bh 1535 """
209 bh 1593 left, bottom, right, top = bbox
210     for i in self.shapetree.find_shapes((left, bottom), (right, top)):
211     yield ShapefileShape(self.shapefile, i)
212 bh 1535
213 bh 1593 def AllShapes(self):
214     """Return an iterable over the shapes in the shape store."""
215     for i in xrange(self.NumShapes()):
216     yield ShapefileShape(self.shapefile, i)
217    
218 bh 1535 def Shape(self, index):
219     """Return the shape with index index"""
220 bh 1559 return ShapefileShape(self.shapefile, index)
221 bh 1535
222    
223    
224 bh 984 class DerivedShapeStore:
225    
226     """A ShapeStore derived from other shapestores or tables"""
227    
228     def __init__(self, shapestore, table):
229     """Initialize the derived shapestore.
230    
231     The arguments are a shapestore for the shapedata and a table for
232     the tabular data.
233 jonathan 1261
234     Raises ValueError if the number of shapes in the shapestore
235     is different from the number of rows in the table.
236 bh 984 """
237 jonathan 1261
238     numShapes = shapestore.Shapefile().info()[0]
239     if numShapes != table.NumRows():
240     raise ValueError(_("Table not compatible with shapestore."))
241    
242 bh 984 self.shapestore = shapestore
243     self.table = table
244    
245     def Table(self):
246     """Return the table"""
247     return self.table
248    
249     def Shapefile(self):
250 bh 1074 """Return the shapefile of the underlying shapestore"""
251 bh 984 return self.shapestore.Shapefile()
252    
253     def Dependencies(self):
254     """Return a tuple containing the shapestore and the table"""
255     return (self.shapestore, self.table)
256    
257 bh 1074 def OrigShapeStore(self):
258     """
259     Return the original shapestore the derived store was instantiated with
260     """
261     return self.shapestore
262 bh 1535
263     def Shape(self, index):
264     """Return the shape with index index"""
265     return self.shapestore.Shape(index)
266    
267     def ShapesInRegion(self, bbox):
268     """Return the ids of the shapes that overlap the box.
269    
270     This method is simply delegated to the shapestore the
271     DerivedShapeStore was instantiated with.
272     """
273     return self.shapestore.ShapesInRegion(bbox)
274    
275 bh 1593 def AllShapes(self):
276     """Return an iterable over the shapes in the shape store.
277    
278     This method is simply delegated to the shapestore the
279     DerivedShapeStore was instantiated with.
280     """
281     return self.shapestore.AllShapes()
282    
283 bh 1535 def ShapeType(self):
284     """Return the type of the shapes in the layer.
285    
286     This method is simply delegated to the shapestore the
287     DerivedShapeStore was instantiated with.
288     """
289     return self.shapestore.ShapeType()
290    
291 bh 1564 def RawShapeFormat(self):
292     """Return the raw data format of the shapes.
293    
294     This method is simply delegated to the shapestore the
295     DerivedShapeStore was instantiated with.
296     """
297     return self.shapestore.RawShapeFormat()
298    
299 bh 1535 def NumShapes(self):
300     """Return the number of shapes in the shapestore."""
301     return self.shapestore.NumShapes()
302    
303     def BoundingBox(self):
304     """Return the bounding box of the shapes in the shapestore.
305    
306     This method is simply delegated to the shapestore the
307     DerivedShapeStore was instantiated with.
308     """
309     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