/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/renderer.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/renderer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 394 - (show annotations)
Mon Feb 10 15:27:13 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10106 byte(s)
* Thuban/UI/renderer.py (MapRenderer): Use the Get*() methods
        of the ClassData class.

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 wxPython.wx import wxPoint, wxColour, wxPen, wxBrush, wxFont, \
11 wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \
12 wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL
13
14 from wxproj import draw_polygon_shape
15
16 from Thuban import _
17
18 from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
19 SHAPETYPE_POINT
20 from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
21 ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE
22
23 from Thuban.Model.classification import Classification
24
25
26 class MapRenderer:
27
28 """Class to render a map onto a wxDC"""
29
30 honor_visibility = 1
31
32 def __init__(self, dc, scale, offset, resolution = 72.0,
33 honor_visibility = None):
34 """Inititalize the renderer.
35
36 dc -- the wxPython DC to render on
37 scale, offset -- the scale factor and translation to convert
38 between projected coordinates and the DC coordinates
39
40 resolution -- the assumed resolution of the DC. Used to convert
41 absolute lengths like font sizes to DC coordinates
42
43 honor_visibility -- boolean. If true, honor the visibility flag
44 of the layers, otherwise draw all layers. If None, use
45 the renderer's default.
46 """
47 # resolution in pixel/inch
48 self.dc = dc
49 self.scale = scale
50 self.offset = offset
51 if honor_visibility is not None:
52 self.honor_visibility = honor_visibility
53 # store the resolution in pixel/point because it's more useful
54 # later.
55 self.resolution = resolution / 72.0
56
57 def render_map(self, map):
58 self.map = map
59 for layer in map.Layers():
60 # if honor_visibility is true, only draw visible layers,
61 # otherwise draw all layers
62 if not self.honor_visibility or layer.Visible():
63 self.draw_shape_layer(layer)
64 self.draw_label_layer(map.LabelLayer())
65
66 def draw_shape_layer(self, layer):
67 scale = self.scale
68 offx, offy = self.offset
69
70 map_proj = self.map.projection
71 layer_proj = layer.projection
72
73 shapetype = layer.ShapeType()
74
75 brush = wxTRANSPARENT_BRUSH
76 pen = wxTRANSPARENT_PEN
77
78 old_prop = None
79 for i in self.layer_ids(layer):
80 value = None
81 shape = layer.Shape(i)
82 lc = layer.classification
83 field = lc.field
84
85 if field is not None:
86 record = layer.table.read_record(i)
87 if record is not None:
88 value = record[field]
89
90 #
91 # if the above statements fail 'value' should
92 # be null, at which point this call will
93 # at least retreive the NullData
94 #
95 prop = lc.GetProperties(value)
96
97 if prop != old_prop:
98 old_prop = prop
99
100 if shapetype == SHAPETYPE_ARC:
101 fill = None
102 else:
103 fill = prop.GetFill()
104
105 if fill is None:
106 brush = wxTRANSPARENT_BRUSH
107 else:
108 color = wxColour(fill.red * 255,
109 fill.green * 255,
110 fill.blue * 255)
111 brush = wxBrush(color, wxSOLID)
112
113 stroke = prop.GetStroke()
114 stroke_width = prop.GetStrokeWidth()
115 if stroke is None:
116 pen = wxTRANSPARENT_PEN
117 else:
118 color = wxColour(stroke.red * 255,
119 stroke.green * 255,
120 stroke.blue * 255)
121 pen = wxPen(color, stroke_width, wxSOLID)
122
123 if shapetype == SHAPETYPE_POINT:
124 self.dc.SetBrush(brush)
125 self.dc.SetPen(pen)
126 self.draw_point_shape(layer, i)
127 else:
128 self.draw_polygon_shape(layer, i, pen, brush)
129
130 def layer_ids(self, layer):
131 """Return the shape ids of the given layer that have to be drawn.
132
133 The default implementation simply returns all ids in the layer.
134 Override in derived classes to be more precise.
135 """
136 return range(layer.NumShapes())
137
138 def draw_polygon_shape(self, layer, index, pen, brush):
139 offx, offy = self.offset
140 draw_polygon_shape(layer.shapefile.cobject(), index,
141 self.dc, pen, brush,
142 self.map.projection, layer.projection,
143 self.scale, -self.scale, offx, offy)
144
145 def projected_points(self, layer, index):
146 proj = self.map.projection
147 if proj is not None:
148 forward = proj.Forward
149 else:
150 forward = None
151 proj = layer.projection
152 if proj is not None:
153 inverse = proj.Inverse
154 else:
155 inverse = None
156 shape = layer.Shape(index)
157 points = []
158 scale = self.scale
159 offx, offy = self.offset
160 for x, y in shape.Points():
161 if inverse:
162 x, y = inverse(x, y)
163 if forward:
164 x, y = forward(x, y)
165 points.append(wxPoint(x * scale + offx,
166 -y * scale + offy))
167 return points
168
169 def draw_arc_shape(self, layer, index):
170 points = self.projected_points(layer, index)
171 self.dc.DrawLines(points)
172
173 def draw_point_shape(self, layer, index):
174 p = self.projected_points(layer, index)[0]
175 radius = self.resolution * 5
176 self.dc.DrawEllipse(p.x - radius, p.y - radius, 2*radius, 2*radius)
177
178 def draw_label_layer(self, layer):
179 scale = self.scale
180 offx, offy = self.offset
181
182 font = wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
183 self.dc.SetFont(font)
184
185 map_proj = self.map.projection
186 if map_proj is not None:
187 forward = map_proj.Forward
188 else:
189 forward = None
190
191 for label in layer.Labels():
192 x = label.x
193 y = label.y
194 text = label.text
195 if forward:
196 x, y = forward(x, y)
197 x = x * scale + offx
198 y = -y * scale + offy
199 width, height = self.dc.GetTextExtent(text)
200 if label.halign == ALIGN_LEFT:
201 # nothing to be done
202 pass
203 elif label.halign == ALIGN_RIGHT:
204 x = x - width
205 elif label.halign == ALIGN_CENTER:
206 x = x - width/2
207 if label.valign == ALIGN_TOP:
208 # nothing to be done
209 pass
210 elif label.valign == ALIGN_BOTTOM:
211 y = y - height
212 elif label.valign == ALIGN_CENTER:
213 y = y - height/2
214 self.dc.DrawText(text, x, y)
215
216
217 class ScreenRenderer(MapRenderer):
218
219 # On the screen we want to see only visible layers by default
220 honor_visibility = 1
221
222 def RenderMap(self, map, region, selected_layer, selected_shape):
223 """Render the map.
224
225 Only the given region (a tuple in window coordinates as returned
226 by a wxrect's asTuple method) needs to be redrawn. Highlight the
227 shape with id selected_shape in the selected_layer.
228 """
229 self.update_region = region
230 self.selected_layer = selected_layer
231 self.selected_shape = selected_shape
232 self.render_map(map)
233
234 def draw_shape_layer(self, layer):
235 MapRenderer.draw_shape_layer(self, layer)
236 if layer is self.selected_layer and self.selected_shape is not None:
237 pen = wxPen(wxBLACK, 3, wxSOLID)
238 brush = wxBrush(wxBLACK, wxCROSS_HATCH)
239
240 shapetype = layer.ShapeType()
241 index = self.selected_shape
242 if shapetype == SHAPETYPE_POLYGON:
243 self.draw_polygon_shape(layer, index, pen, brush)
244 elif shapetype == SHAPETYPE_ARC:
245 self.draw_polygon_shape(layer, index, pen, None)
246 else:
247 self.dc.SetBrush(brush)
248 self.dc.SetPen(pen)
249 if shapetype == SHAPETYPE_POINT:
250 self.draw_point_shape(layer, index)
251 else:
252 raise TypeError(_("Unhandled shape type %s") % shapetype)
253
254 def layer_ids(self, layer):
255 """Return the shapeids covered by the region that has to be redrawn
256
257 Call the layer's ShapesInRegion method to determine the ids so
258 that it can use the quadtree.
259 """
260 # FIXME: the quad-tree should be built from the projected
261 # coordinates not the lat-long ones because it's not trivial to
262 # determine an appropriate rectangle in lat-long for a given
263 # rectangle in projected coordinates which we have to start from
264 # here.
265 proj = self.map.projection
266 if proj is not None:
267 inverse = proj.Inverse
268 else:
269 inverse = None
270
271 scale = self.scale
272 offx, offy = self.offset
273 xs = []
274 ys = []
275 x, y, width, height = self.update_region
276 for winx, winy in ((x, y), (x + width, y),
277 (x + width, y + height), (x, y + height)):
278 px = (winx - offx) / scale
279 py = -(winy - offy) / scale
280 if inverse:
281 px, py = inverse(px, py)
282 xs.append(px)
283 ys.append(py)
284 left = min(xs)
285 right = max(xs)
286 top = max(ys)
287 bottom = min(ys)
288
289 return layer.ShapesInRegion((left, bottom, right, top))
290
291
292 class PrinterRender(MapRenderer):
293
294 # When printing we want to see all layers
295 honor_visibility = 0
296
297 RenderMap = MapRenderer.render_map
298

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26