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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 642 - (hide annotations)
Thu Apr 10 14:41:50 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10577 byte(s)
fixed bug where if there was no classification and the default was hidden,
the default was still being drawn.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26