/[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 290 - (hide 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 bh 76 # Copyright (c) 2001, 2002 by Intevation GmbH
2 bh 6 # 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 bh 76 stroke_width = layer.stroke_width
76 bh 6 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 bh 76 pen = wxPen(color, stroke_width, wxSOLID)
83 bh 6
84     map_proj = self.map.projection
85     layer_proj = layer.projection
86    
87     shapetype = layer.ShapeType()
88    
89     if shapetype == SHAPETYPE_POLYGON:
90 bh 144 for i in self.layer_ids(layer):
91 bh 6 self.draw_polygon_shape(layer, i, pen, brush)
92 bh 144 elif shapetype == SHAPETYPE_ARC:
93     for i in self.layer_ids(layer):
94     self.draw_polygon_shape(layer, i, pen, None)
95 bh 6 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 bh 144 for i in self.layer_ids(layer):
103 bh 6 f(layer, i)
104    
105 bh 144 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 bh 6 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 bh 144 def RenderMap(self, map, region, selected_layer, selected_shape):
198     """Render the map.
199    
200 bh 148 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 bh 144 """
204     self.update_region = region
205 bh 6 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 bh 290 elif shapetype == SHAPETYPE_ARC:
220     self.draw_polygon_shape(layer, index, pen, None)
221 bh 6 else:
222     self.dc.SetBrush(brush)
223     self.dc.SetPen(pen)
224 bh 290 if shapetype == SHAPETYPE_POINT:
225     self.draw_point_shape(layer, index)
226     else:
227     raise TypeError("Unhandled shape type %s" % shapetype)
228 bh 6
229 bh 144 def layer_ids(self, layer):
230     """Return the shapeids covered by the region that has to be redrawn
231 bh 6
232 bh 144 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 bh 148 x, y, width, height = self.update_region
251 bh 144 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 bh 6 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