/[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 290 - (show annotations)
Thu Aug 29 14:11:28 2002 UTC (22 years, 6 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 9406 byte(s)
(ScreenRenderer.draw_shape_layer): Handle
arcs with multiple parts.

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 elif shapetype == SHAPETYPE_ARC:
220 self.draw_polygon_shape(layer, index, pen, None)
221 else:
222 self.dc.SetBrush(brush)
223 self.dc.SetPen(pen)
224 if shapetype == SHAPETYPE_POINT:
225 self.draw_point_shape(layer, index)
226 else:
227 raise TypeError("Unhandled shape type %s" % shapetype)
228
229 def layer_ids(self, layer):
230 """Return the shapeids covered by the region that has to be redrawn
231
232 Call the layer's ShapesInRegion method to determine the ids so
233 that it can use the quadtree.
234 """
235 # FIXME: the quad-tree should be built from the projected
236 # coordinates not the lat-long ones because it's not trivial to
237 # determine an appropriate rectangle in lat-long for a given
238 # rectangle in projected coordinates which we have to start from
239 # here.
240 proj = self.map.projection
241 if proj is not None:
242 inverse = proj.Inverse
243 else:
244 inverse = None
245
246 scale = self.scale
247 offx, offy = self.offset
248 xs = []
249 ys = []
250 x, y, width, height = self.update_region
251 for winx, winy in ((x, y), (x + width, y),
252 (x + width, y + height), (x, y + height)):
253 px = (winx - offx) / scale
254 py = -(winy - offy) / scale
255 if inverse:
256 px, py = inverse(px, py)
257 xs.append(px)
258 ys.append(py)
259 left = min(xs)
260 right = max(xs)
261 top = max(ys)
262 bottom = min(ys)
263
264 return layer.ShapesInRegion((left, bottom, right, top))
265
266
267 class PrinterRender(MapRenderer):
268
269 # When printing we want to see all layers
270 honor_visibility = 0
271
272 RenderMap = MapRenderer.render_map
273

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26