/[thuban]/trunk/thuban/Thuban/Model/layer.py
ViewVC logotype

Annotation of /trunk/thuban/Thuban/Model/layer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 412 - (hide annotations)
Wed Feb 19 16:51:50 2003 UTC (22 years ago) by jonathan
File MIME type: text/x-python
File size: 8690 byte(s)
(Layer): Removed references to fill, stroke,
        stroke_width attributes. Made the 'classification' attribute private.
        New methods for setting/getting the classification.

1 bh 73 # Copyright (c) 2001, 2002 by Intevation GmbH
2 bh 6 # Authors:
3     # Bernhard Herzog <[email protected]>
4 jonathan 412 # Jonathan Coles <[email protected]>
5 bh 6 #
6     # This program is free software under the GPL (>=v2)
7     # Read the file COPYING coming with Thuban for details.
8    
9     __version__ = "$Revision$"
10    
11 bh 276 import os
12 bh 171 from math import log, ceil
13    
14 jan 374 from Thuban import _
15    
16 bh 143 import shapelib, shptree
17 bh 6
18     from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
19     LAYER_VISIBILITY_CHANGED
20    
21     from color import Color
22    
23 jonathan 364 from classification import Classification
24 bh 6
25     from table import Table
26    
27     from base import TitledObject, Modifiable
28    
29     class Shape:
30    
31     """Represent one shape"""
32    
33     def __init__(self, points):
34     self.points = points
35     #self.compute_bbox()
36    
37     def compute_bbox(self):
38     xs = []
39     ys = []
40     for x, y in self.points:
41     xs.append(x)
42     ys.append(y)
43     self.llx = min(xs)
44     self.lly = min(ys)
45     self.urx = max(xs)
46     self.ury = max(ys)
47    
48     def Points(self):
49     return self.points
50    
51    
52    
53     # Shape type constants
54     SHAPETYPE_POLYGON = "polygon"
55     SHAPETYPE_ARC = "arc"
56     SHAPETYPE_POINT = "point"
57    
58     # mapping from shapelib shapetype constants to our constants
59     shapelib_shapetypes = {shapelib.SHPT_POLYGON: SHAPETYPE_POLYGON,
60     shapelib.SHPT_ARC: SHAPETYPE_ARC,
61     shapelib.SHPT_POINT: SHAPETYPE_POINT}
62    
63     shapetype_names = {SHAPETYPE_POINT: "Point",
64     SHAPETYPE_ARC: "Arc",
65     SHAPETYPE_POLYGON: "Polygon"}
66    
67     class BaseLayer(TitledObject, Modifiable):
68    
69     """Base class for the layers."""
70    
71     def __init__(self, title, visible = 1):
72     """Initialize the layer.
73    
74     title -- the title
75     visible -- boolean. If true the layer is visible.
76     """
77     TitledObject.__init__(self, title)
78     Modifiable.__init__(self)
79     self.visible = visible
80    
81     def Visible(self):
82     """Return true if layer is visible"""
83     return self.visible
84    
85     def SetVisible(self, visible):
86     """Set the layer's visibility."""
87     self.visible = visible
88     self.issue(LAYER_VISIBILITY_CHANGED, self)
89 bh 276
90    
91 bh 6 class Layer(BaseLayer):
92    
93     """Represent the information of one geodata file (currently a shapefile)
94    
95     All children of the layer have the same type.
96    
97     A layer has fill and stroke colors. Colors should be instances of
98     Color. They can also be None, indicating no fill or no stroke.
99    
100     The layer objects send the following events, all of which have the
101     layer object as parameter:
102    
103     TITLE_CHANGED -- The title has changed.
104     LAYER_PROJECTION_CHANGED -- the projection has changed.
105     LAYER_LEGEND_CHANGED -- the fill or stroke attributes have changed
106    
107     """
108    
109     def __init__(self, title, filename, projection = None,
110 jonathan 412 fill = Color.None,
111     stroke = Color.Black,
112     stroke_width = 1,
113     visible = 1):
114 bh 6 """Initialize the layer.
115    
116     title -- the title
117     filename -- the name of the shapefile
118     projection -- the projection object. Its Inverse method is
119     assumed to map the layer's coordinates to lat/long
120     coordinates
121     fill -- the fill color or None if the shapes are not filled
122     stroke -- the stroke color or None if the shapes are not stroked
123     visible -- boolean. If true the layer is visible.
124    
125     colors are expected to be instances of Color class
126     """
127     BaseLayer.__init__(self, title, visible = visible)
128 bh 276
129     # Make the filename absolute. The filename will be
130     # interpreted relative to that anyway, but when saving a
131     # session we need to compare absolute paths and it's usually
132     # safer to always work with absolute paths.
133     self.filename = os.path.abspath(filename)
134    
135 bh 6 self.projection = projection
136     self.shapefile = None
137 bh 143 self.shapetree = None
138 bh 21 self.open_shapefile()
139 bh 6 # shapetable is the table associated with the shapefile, while
140     # table is the default table used to look up attributes for
141     # display
142     self.shapetable = Table(filename)
143     self.table = self.shapetable
144    
145 jonathan 412 self.__classification = Classification(self)
146     self.__classification.SetDefaultStroke(stroke)
147     self.__classification.SetDefaultStrokeWidth(stroke_width)
148     self.__classification.SetDefaultFill(fill)
149 jonathan 364
150 jonathan 389 self.UnsetModified()
151    
152 bh 6 def open_shapefile(self):
153     if self.shapefile is None:
154     self.shapefile = shapelib.ShapeFile(self.filename)
155     numshapes, shapetype, mins, maxs = self.shapefile.info()
156     self.numshapes = numshapes
157     self.shapetype = shapelib_shapetypes[shapetype]
158    
159 bh 179 # if there are shapes, set the bbox accordinly. Otherwise
160     # set it to None.
161     if self.numshapes:
162     self.bbox = mins[:2] + maxs[:2]
163     else:
164     self.bbox = None
165    
166 bh 171 # estimate a good depth for the quad tree. Each depth
167     # multiplies the number of nodes by four, therefore we
168     # basically take the base 4 logarithm of the number of
169     # shapes.
170     if self.numshapes < 4:
171     maxdepth = 1
172     else:
173     maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
174    
175     self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
176     maxdepth)
177    
178 bh 258 def Destroy(self):
179 bh 260 BaseLayer.Destroy(self)
180 bh 258 if self.shapefile is not None:
181     self.shapefile.close()
182     self.shapefile = None
183     self.shapetree = None
184     self.table.Destroy()
185    
186 bh 6 def BoundingBox(self):
187 bh 179 """Return the layer's bounding box in the intrinsic coordinate system.
188    
189     If the layer has no shapes, return None.
190     """
191     # The bbox will be set by open_shapefile just as we need it
192     # here.
193 bh 6 self.open_shapefile()
194     return self.bbox
195    
196     def LatLongBoundingBox(self):
197 bh 179 """Return the layer's bounding box in lat/long coordinates.
198 bh 6
199 bh 179 Return None, if the layer doesn't contain any shapes.
200     """
201     bbox = self.BoundingBox()
202     if bbox is not None:
203     llx, lly, urx, ury = bbox
204     if self.projection is not None:
205     llx, lly = self.projection.Inverse(llx, lly)
206     urx, ury = self.projection.Inverse(urx, ury)
207     return llx, lly, urx, ury
208     else:
209     return None
210    
211 bh 6 def NumShapes(self):
212     """Return the number of shapes in the layer"""
213     self.open_shapefile()
214     return self.numshapes
215    
216     def ShapeType(self):
217     """Return the type of the shapes in the layer.
218     This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
219     """
220     self.open_shapefile()
221     return self.shapetype
222    
223     def Shape(self, index):
224     """Return the shape with index index"""
225     self.open_shapefile()
226     shape = self.shapefile.read_object(index)
227 jonathan 364
228 bh 6 if self.shapetype == SHAPETYPE_POINT:
229     points = shape.vertices()
230     else:
231     #for poly in shape.vertices():
232     poly = shape.vertices()[0]
233     points = []
234     for x, y in poly:
235 bh 82 points.append((x, y))
236 jonathan 364
237 bh 6 return Shape(points)
238    
239 bh 143 def ShapesInRegion(self, box):
240     """Return the ids of the shapes that overlap the box.
241    
242     Box is a tuple (left, bottom, right, top) in the coordinate
243     system used by the layer's shapefile.
244     """
245     left, bottom, right, top = box
246 bh 147 return self.shapetree.find_shapes((left, bottom), (right, top))
247 bh 143
248 bh 6 def SetProjection(self, projection):
249     """Set the layer's projection"""
250     self.projection = projection
251     self.changed(LAYER_PROJECTION_CHANGED, self)
252    
253 jonathan 412 def GetClassification(self):
254     return self.__classification
255    
256     def SetClassification(self, clazz):
257     self.__classification = clazz
258     self.changed(LAYER_LEGEND_CHANGED, self)
259    
260 bh 217 def TreeInfo(self):
261     items = []
262    
263     if self.Visible():
264 jan 374 items.append(_("Shown"))
265 bh 217 else:
266 jan 374 items.append(_("Hidden"))
267     items.append(_("Shapes: %d") % self.NumShapes())
268 bh 217
269     bbox = self.LatLongBoundingBox()
270     if bbox is not None:
271 jan 374 items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
272 bh 217 else:
273 jan 374 items.append(_("Extent (lat-lon):"))
274     items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
275 bh 217
276 jonathan 412 items.append(self.__classification)
277 bh 217
278 jan 374 return (_("Layer '%s'") % self.Title(), items)
279 jonathan 382

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26