/[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 374 - (hide annotations)
Mon Jan 27 14:20:02 2003 UTC (22 years, 1 month ago) by jan
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10043 byte(s)
Replace user string by _() for i18n.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26