/[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 394 - (hide annotations)
Mon Feb 10 15:27:13 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10106 byte(s)
* Thuban/UI/renderer.py (MapRenderer): Use the Get*() methods
        of the ClassData class.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26