/[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 771 - (hide annotations)
Tue Apr 29 14:34:02 2003 UTC (21 years, 10 months ago) by jonathan
File MIME type: text/x-python
File size: 9594 byte(s)
(BaseLayer.__init__): Change default value of visible from 1 to True.
(Layer.__init__): Change default value of visible from 1 to True.

1 bh 701 # Copyright (c) 2001, 2002, 2003 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 171 from math import log, ceil
12    
13 jan 374 from Thuban import _
14    
15 bh 143 import shapelib, shptree
16 bh 6
17 bh 701 from messages import LAYER_PROJECTION_CHANGED, LAYER_VISIBILITY_CHANGED, \
18     LAYER_CHANGED
19 bh 6
20     from color import Color
21    
22 jonathan 437 import classification
23 bh 6
24     from base import TitledObject, Modifiable
25    
26 bh 723
27 bh 6 class Shape:
28    
29     """Represent one shape"""
30    
31     def __init__(self, points):
32     self.points = points
33     #self.compute_bbox()
34    
35     def compute_bbox(self):
36     xs = []
37     ys = []
38     for x, y in self.points:
39     xs.append(x)
40     ys.append(y)
41     self.llx = min(xs)
42     self.lly = min(ys)
43     self.urx = max(xs)
44     self.ury = max(ys)
45    
46     def Points(self):
47     return self.points
48    
49    
50    
51     # Shape type constants
52     SHAPETYPE_POLYGON = "polygon"
53     SHAPETYPE_ARC = "arc"
54     SHAPETYPE_POINT = "point"
55    
56     # mapping from shapelib shapetype constants to our constants
57     shapelib_shapetypes = {shapelib.SHPT_POLYGON: SHAPETYPE_POLYGON,
58     shapelib.SHPT_ARC: SHAPETYPE_ARC,
59     shapelib.SHPT_POINT: SHAPETYPE_POINT}
60    
61     shapetype_names = {SHAPETYPE_POINT: "Point",
62     SHAPETYPE_ARC: "Arc",
63     SHAPETYPE_POLYGON: "Polygon"}
64    
65     class BaseLayer(TitledObject, Modifiable):
66    
67     """Base class for the layers."""
68    
69 jonathan 771 def __init__(self, title, visible = True):
70 bh 6 """Initialize the layer.
71    
72     title -- the title
73     visible -- boolean. If true the layer is visible.
74     """
75     TitledObject.__init__(self, title)
76     Modifiable.__init__(self)
77     self.visible = visible
78    
79     def Visible(self):
80     """Return true if layer is visible"""
81     return self.visible
82    
83     def SetVisible(self, visible):
84     """Set the layer's visibility."""
85     self.visible = visible
86     self.issue(LAYER_VISIBILITY_CHANGED, self)
87 bh 276
88    
89 bh 6 class Layer(BaseLayer):
90    
91     """Represent the information of one geodata file (currently a shapefile)
92    
93     All children of the layer have the same type.
94    
95     A layer has fill and stroke colors. Colors should be instances of
96     Color. They can also be None, indicating no fill or no stroke.
97    
98     The layer objects send the following events, all of which have the
99     layer object as parameter:
100    
101     TITLE_CHANGED -- The title has changed.
102     LAYER_PROJECTION_CHANGED -- the projection has changed.
103     """
104    
105 bh 723 def __init__(self, title, data, projection = None,
106 jonathan 610 fill = Color.Transparent,
107 jonathan 412 stroke = Color.Black,
108 jonathan 464 lineWidth = 1,
109 jonathan 771 visible = True):
110 bh 6 """Initialize the layer.
111    
112     title -- the title
113 bh 723 data -- datastore object for the shape data shown by the layer
114 bh 6 projection -- the projection object. Its Inverse method is
115     assumed to map the layer's coordinates to lat/long
116     coordinates
117 jonathan 610 fill -- the fill color or Color.Transparent if the shapes are
118     not filled
119     stroke -- the stroke color or Color.Transparent if the shapes
120     are not stroked
121 bh 6 visible -- boolean. If true the layer is visible.
122    
123     colors are expected to be instances of Color class
124     """
125     BaseLayer.__init__(self, title, visible = visible)
126 bh 276
127 bh 6 self.projection = projection
128    
129 jonathan 481 #
130     # this is really important so that when the classification class
131     # tries to set its parent layer the variable will exist
132     #
133 bh 723 self.__classification = None
134 jonathan 529 self.__setClassLock = False
135 jonathan 481
136 bh 723 self.SetShapeStore(data)
137 jonathan 492
138     self.SetClassification(None)
139    
140 jonathan 464 self.__classification.SetDefaultLineColor(stroke)
141     self.__classification.SetDefaultLineWidth(lineWidth)
142 jonathan 412 self.__classification.SetDefaultFill(fill)
143 jonathan 492 self.__classification.SetLayer(self)
144 jonathan 364
145 jonathan 389 self.UnsetModified()
146    
147 bh 6
148 bh 723 def SetShapeStore(self, store):
149     self.store = store
150     self.shapefile = self.store.Shapefile()
151     self.shapetable = self.store.Table()
152     self.filename = self.store.filename
153     self.table = self.shapetable
154 bh 179
155 bh 723 numshapes, shapetype, mins, maxs = self.shapefile.info()
156     self.numshapes = numshapes
157     self.shapetype = shapelib_shapetypes[shapetype]
158 bh 171
159 bh 723 # if there are shapes, set the bbox accordingly. Otherwise
160     # set it to None.
161     if self.numshapes:
162     self.bbox = mins[:2] + maxs[:2]
163     else:
164     self.bbox = None
165 bh 171
166 bh 723 # 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     if self.__classification is not None:
178     fieldname = self.__classification.GetField()
179     if not self.store.Table().field_info_by_name(fieldname):
180     self.SetClassification(None)
181     self.changed(LAYER_CHANGED, self)
182    
183     def ShapeStore(self):
184     return self.store
185    
186 bh 258 def Destroy(self):
187 bh 260 BaseLayer.Destroy(self)
188 jonathan 529 self.SetClassification(None)
189 bh 258
190 bh 6 def BoundingBox(self):
191 bh 179 """Return the layer's bounding box in the intrinsic coordinate system.
192    
193     If the layer has no shapes, return None.
194     """
195 bh 6 return self.bbox
196    
197     def LatLongBoundingBox(self):
198 bh 179 """Return the layer's bounding box in lat/long coordinates.
199 bh 6
200 bh 179 Return None, if the layer doesn't contain any shapes.
201     """
202     bbox = self.BoundingBox()
203     if bbox is not None:
204     llx, lly, urx, ury = bbox
205     if self.projection is not None:
206     llx, lly = self.projection.Inverse(llx, lly)
207     urx, ury = self.projection.Inverse(urx, ury)
208     return llx, lly, urx, ury
209     else:
210     return None
211    
212 jonathan 464 def GetFieldType(self, fieldName):
213     info = self.table.field_info_by_name(fieldName)
214     if info is not None:
215     return info[0]
216     else:
217     return None
218    
219 bh 6 def NumShapes(self):
220     """Return the number of shapes in the layer"""
221     return self.numshapes
222    
223     def ShapeType(self):
224     """Return the type of the shapes in the layer.
225     This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
226     """
227     return self.shapetype
228    
229     def Shape(self, index):
230     """Return the shape with index index"""
231     shape = self.shapefile.read_object(index)
232 jonathan 364
233 bh 6 if self.shapetype == SHAPETYPE_POINT:
234     points = shape.vertices()
235     else:
236     #for poly in shape.vertices():
237     poly = shape.vertices()[0]
238     points = []
239     for x, y in poly:
240 bh 82 points.append((x, y))
241 jonathan 364
242 bh 6 return Shape(points)
243    
244 bh 143 def ShapesInRegion(self, box):
245     """Return the ids of the shapes that overlap the box.
246    
247     Box is a tuple (left, bottom, right, top) in the coordinate
248     system used by the layer's shapefile.
249     """
250     left, bottom, right, top = box
251 bh 147 return self.shapetree.find_shapes((left, bottom), (right, top))
252 bh 143
253 jonathan 725 def GetProjection(self):
254     return self.projection
255    
256 bh 6 def SetProjection(self, projection):
257     """Set the layer's projection"""
258     self.projection = projection
259     self.changed(LAYER_PROJECTION_CHANGED, self)
260    
261 jonathan 412 def GetClassification(self):
262     return self.__classification
263    
264     def SetClassification(self, clazz):
265 jonathan 492 """Set the classification to 'clazz'
266 jonathan 481
267 jonathan 492 If 'clazz' is None a default classification is created
268     """
269 jonathan 481
270 jonathan 529 # prevent infinite recursion when calling SetLayer()
271     if self.__setClassLock: return
272    
273     self.__setClassLock = True
274    
275 jonathan 492 if clazz is None:
276 jonathan 529 if self.__classification is not None:
277     self.__classification.SetLayer(None)
278 jonathan 492 self.__classification = classification.Classification()
279     else:
280     self.__classification = clazz
281 jonathan 529 try:
282     self.__classification.SetLayer(self)
283     except ValueError:
284     self.__setClassLock = False
285     raise ValueError
286 jonathan 492
287 jonathan 545 self.changed(LAYER_CHANGED, self)
288 jonathan 412
289 jonathan 529 self.__setClassLock = False
290    
291 jonathan 492 def ClassChanged(self):
292     """Called from the classification object when it has changed."""
293 jonathan 558 self.changed(LAYER_CHANGED, self)
294 jonathan 492
295 bh 217 def TreeInfo(self):
296     items = []
297    
298     if self.Visible():
299 jan 374 items.append(_("Shown"))
300 bh 217 else:
301 jan 374 items.append(_("Hidden"))
302     items.append(_("Shapes: %d") % self.NumShapes())
303 bh 217
304     bbox = self.LatLongBoundingBox()
305     if bbox is not None:
306 jan 374 items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
307 bh 217 else:
308 jan 374 items.append(_("Extent (lat-lon):"))
309     items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
310 bh 217
311 jonathan 736 if self.projection and len(self.projection.params) > 0:
312     items.append((_("Projection"),
313     [str(param) for param in self.projection.params]))
314    
315 jonathan 412 items.append(self.__classification)
316 bh 217
317 jan 374 return (_("Layer '%s'") % self.Title(), items)
318 jonathan 382
319 jonathan 736

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26