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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 258 - (show annotations)
Thu Aug 15 12:48:03 2002 UTC (22 years, 6 months ago) by bh
File MIME type: text/x-python
File size: 8737 byte(s)
(Layer.Destroy): New. Explicitly close the
shapefile and destroy the table.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26