/[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 148 - (show annotations)
Tue May 7 16:40:29 2002 UTC (22 years, 10 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 9314 byte(s)
	* Thuban/UI/renderer.py
	(ScreenRenderer.layer_ids, ScreenRenderer.draw_shape_layer): The
	update box is now directly a tuple, not a wxRect anymore.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26