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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 765 by bh, Tue Apr 29 12:42:14 2003 UTC revision 1972 by bh, Mon Nov 24 19:23:08 2003 UTC
# Line 7  Line 7 
7    
8  """Data source abstractions"""  """Data source abstractions"""
9    
10    from __future__ import generators
11    
12  __version__ = "$Revision$"  __version__ = "$Revision$"
13  # $Source$  # $Source$
14  # $Id$  # $Id$
15    
16  import os  import os
17    import weakref
18    from math import ceil, log
19    
20  import shapelib  import shapelib
21    import shptree
22  import table  import table
23  import transientdb  import transientdb
24    
25    from Thuban import _
26    
27    # Shape type constants
28    SHAPETYPE_POLYGON = "polygon"
29    SHAPETYPE_ARC = "arc"
30    SHAPETYPE_POINT = "point"
31    
32    # 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    #
38    # Raw shape data formats
39    #
40    
41    # Raw data is the same as that returned by the points method.
42    RAW_PYTHON = "RAW_PYTHON"
43    
44    # Raw data is a shapefile. The Shape object will use the shapeid as the
45    # raw data.
46    RAW_SHAPEFILE = "RAW_SHAPEFILE"
47    
48    # Raw data in well-known text format
49    RAW_WKT = "RAW_WKT"
50    
51    
52    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        def compute_bbox(self):
61            """
62            Return the bounding box of the shape as a tuple (minx,miny,maxx,maxy)
63            """
64            xs = []
65            ys = []
66            for part in self.Points():
67                for x, y in part:
68                    xs.append(x)
69                    ys.append(y)
70            return (min(xs), min(ys), max(xs), max(ys))
71    
72        def ShapeID(self):
73            return self.shapeid
74    
75        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    
83        def RawData(self):
84            """Return the shape id to use with the shapefile"""
85            return self.shapeid
86    
87        def Shapefile(self):
88            """Return the shapefile object"""
89            return self.shapefile
90    
91    
92    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  class ShapefileStore:  class ShapefileStore:
117    
# Line 29  class ShapefileStore: Line 124  class ShapefileStore:
124          # safer to always work with absolute paths.          # safer to always work with absolute paths.
125          self.filename = os.path.abspath(filename)          self.filename = os.path.abspath(filename)
126    
         self.shapefile = shapelib.ShapeFile(self.filename)  
127          self.dbftable = table.DBFTable(filename)          self.dbftable = table.DBFTable(filename)
128          self.table = transientdb.AutoTransientTable(session.TransientDB(),          self.table = ShapeTable(self, session.TransientDB(), self.dbftable)
129                                                      self.dbftable)          self._open_shapefile()
130    
131        def _open_shapefile(self):
132            self.shapefile = shapelib.ShapeFile(self.filename)
133            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      def Table(self):      def Table(self):
152            """Return the table containing the attribute data"""
153          return self.table          return self.table
154    
155      def Shapefile(self):      def Shapefile(self):
156            """Return the shapefile object"""
157          return self.shapefile          return self.shapefile
158    
159        def FileName(self):
160            """Return the filename used to open the shapefile"""
161            return self.filename
162    
163  class SimpleStore:      def FileType(self):
164            """Return the filetype. This is always the string 'shapefile'"""
165            return "shapefile"
166    
167      """Combine a shapefile and a table object"""      def ShapeType(self):
168            """Return the type of the shapes in the shapestore.
169    
170      def __init__(self, shapefile, table):          This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
171          self.shapefile = shapefile          """
172            return self.shapetype
173    
174        def RawShapeFormat(self):
175            """Return the raw data format of the shape data, i.e. RAW_SHAPEFILE"""
176            return RAW_SHAPEFILE
177    
178        def NumShapes(self):
179            """Return the number of shapes in the shape store"""
180            return self.numshapes
181    
182        def Dependencies(self):
183            """Return the empty tuple.
184    
185            The ShapefileStore doesn't depend on anything else.
186            """
187            return ()
188    
189        def OrigShapeStore(self):
190            """Return None.
191    
192            The ShapefileStore was not derived from another shapestore.
193            """
194            return None
195    
196        def BoundingBox(self):
197            """Return the bounding box of the shapes in the shapestore.
198    
199            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        def ShapesInRegion(self, bbox):
205            """Return an iterable over the shapes that overlap the bounding box.
206    
207            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            """
211            # Bind a few globals to locals to make it a bit faster
212            cls = ShapefileShape
213            shapefile = self.shapefile
214    
215            left, bottom, right, top = bbox
216            for i in self.shapetree.find_shapes((left, bottom), (right, top)):
217                yield cls(shapefile, i)
218    
219        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        def Shape(self, index):
225            """Return the shape with index index"""
226            return ShapefileShape(self.shapefile, index)
227    
228    
229    
230    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    
240            Raises ValueError if the number of shapes in the shapestore
241            is different from the number of rows in the table.
242            """
243    
244            numShapes = shapestore.Shapefile().info()[0]
245            if numShapes != table.NumRows():
246                raise ValueError(_("Table not compatible with shapestore."))
247    
248            self.shapestore = shapestore
249          self.table = table          self.table = table
         self.filename = None  
250    
251      def Table(self):      def Table(self):
252            """Return the table"""
253          return self.table          return self.table
254    
255      def Shapefile(self):      def Shapefile(self):
256          return self.shapefile          """Return the shapefile of the underlying shapestore"""
257            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        def OrigShapeStore(self):
264            """
265            Return the original shapestore the derived store was instantiated with
266            """
267            return self.shapestore
268    
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        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        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        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        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()

Legend:
Removed from v.765  
changed lines
  Added in v.1972

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26