/[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 676 - (hide annotations)
Tue Apr 15 19:20:40 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: 10901 byte(s)
(MapRenderer.draw_shape_layer): Make drawing initialization call to
        draw_polygon_init()
(MapRenderer.draw_polygon_shape): Use new signature of draw_polygon_shape.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26