/[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 723 by bh, Thu Apr 24 15:31:53 2003 UTC revision 1921 by bh, Mon Nov 3 18:42:27 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
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 28  class ShapefileStore: Line 125  class ShapefileStore:
125          self.filename = os.path.abspath(filename)          self.filename = os.path.abspath(filename)
126    
127          self.shapefile = shapelib.ShapeFile(self.filename)          self.shapefile = shapelib.ShapeFile(self.filename)
128          self.table = table.Table(filename)          self.dbftable = table.DBFTable(filename)
129            self.table = ShapeTable(self, session.TransientDB(), self.dbftable)
130    
131            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      def Table(self):      def Table(self):
150            """Return the table containing the attribute data"""
151          return self.table          return self.table
152    
153      def Shapefile(self):      def Shapefile(self):
154            """Return the shapefile object"""
155          return self.shapefile          return self.shapefile
156    
157        def FileName(self):
158            """Return the filename used to open the shapefile"""
159            return self.filename
160    
161        def FileType(self):
162            """Return the filetype. This is always the string 'shapefile'"""
163            return "shapefile"
164    
165        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        def RawShapeFormat(self):
173            """Return the raw data format of the shape data, i.e. RAW_SHAPEFILE"""
174            return RAW_SHAPEFILE
175    
176        def NumShapes(self):
177            """Return the number of shapes in the shape store"""
178            return self.numshapes
179    
180        def Dependencies(self):
181            """Return the empty tuple.
182    
183            The ShapefileStore doesn't depend on anything else.
184            """
185            return ()
186    
187        def OrigShapeStore(self):
188            """Return None.
189    
190            The ShapefileStore was not derived from another shapestore.
191            """
192            return None
193    
194        def BoundingBox(self):
195            """Return the bounding box of the shapes in the shapestore.
196    
197            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        def ShapesInRegion(self, bbox):
203            """Return an iterable over the shapes that overlap the bounding box.
204    
205            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            """
209            # Bind a few globals to locals to make it a bit faster
210            cls = ShapefileShape
211            shapefile = self.shapefile
212    
213            left, bottom, right, top = bbox
214            for i in self.shapetree.find_shapes((left, bottom), (right, top)):
215                yield cls(shapefile, i)
216    
217        def AllShapes(self):
218            """Return an iterable over the shapes in the shape store."""
219            for i in xrange(self.NumShapes()):
220                yield ShapefileShape(self.shapefile, i)
221    
222        def Shape(self, index):
223            """Return the shape with index index"""
224            return ShapefileShape(self.shapefile, index)
225    
226    
227    
228    class DerivedShapeStore:
229    
230        """A ShapeStore derived from other shapestores or tables"""
231    
232        def __init__(self, shapestore, table):
233            """Initialize the derived shapestore.
234    
235            The arguments are a shapestore for the shapedata and a table for
236            the tabular data.
237    
238            Raises ValueError if the number of shapes in the shapestore
239            is different from the number of rows in the table.
240            """
241    
242            numShapes = shapestore.Shapefile().info()[0]
243            if numShapes != table.NumRows():
244                raise ValueError(_("Table not compatible with shapestore."))
245    
246            self.shapestore = shapestore
247            self.table = table
248    
249        def Table(self):
250            """Return the table"""
251            return self.table
252    
253        def Shapefile(self):
254            """Return the shapefile of the underlying shapestore"""
255            return self.shapestore.Shapefile()
256    
257        def Dependencies(self):
258            """Return a tuple containing the shapestore and the table"""
259            return (self.shapestore, self.table)
260    
261        def OrigShapeStore(self):
262            """
263            Return the original shapestore the derived store was instantiated with
264            """
265            return self.shapestore
266    
267        def Shape(self, index):
268            """Return the shape with index index"""
269            return self.shapestore.Shape(index)
270    
271        def ShapesInRegion(self, bbox):
272            """Return the ids of the shapes that overlap the box.
273    
274            This method is simply delegated to the shapestore the
275            DerivedShapeStore was instantiated with.
276            """
277            return self.shapestore.ShapesInRegion(bbox)
278    
279        def AllShapes(self):
280            """Return an iterable over the shapes in the shape store.
281    
282            This method is simply delegated to the shapestore the
283            DerivedShapeStore was instantiated with.
284            """
285            return self.shapestore.AllShapes()
286    
287        def ShapeType(self):
288            """Return the type of the shapes in the layer.
289    
290            This method is simply delegated to the shapestore the
291            DerivedShapeStore was instantiated with.
292            """
293            return self.shapestore.ShapeType()
294    
295        def RawShapeFormat(self):
296            """Return the raw data format of the shapes.
297    
298            This method is simply delegated to the shapestore the
299            DerivedShapeStore was instantiated with.
300            """
301            return self.shapestore.RawShapeFormat()
302    
303        def NumShapes(self):
304            """Return the number of shapes in the shapestore."""
305            return self.shapestore.NumShapes()
306    
307        def BoundingBox(self):
308            """Return the bounding box of the shapes in the shapestore.
309    
310            This method is simply delegated to the shapestore the
311            DerivedShapeStore was instantiated with.
312            """
313            return self.shapestore.BoundingBox()

Legend:
Removed from v.723  
changed lines
  Added in v.1921

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26