/[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 144 - (hide annotations)
Tue May 7 14:54:02 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: 9284 byte(s)
	* Thuban/UI/renderer.py (MapRenderer.layer_ids): New method to
	return the shape ids to be rendered in a given layer.
	(MapRenderer.draw_shape_layer): Call layer_ids to get the list of
	ids.
	(ScreenRenderer.RenderMap): New parameter
	for the rectangle that has to be updated
	(ScreenRenderer.layer_ids): Make use of the layer's quadtree by
	calling it's ShapesInRegion method.

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     Only the given region (a wxRect in window coordinates) needs to
201     be redrawn. Highlight the shape with id selected_shape in the
202     selected_layer.
203     """
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     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 bh 144 def layer_ids(self, layer):
229     """Return the shapeids covered by the region that has to be redrawn
230 bh 6
231 bh 144 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.asTuple()
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 bh 6 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