/[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 416 - (hide annotations)
Wed Feb 19 16:53:08 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10208 byte(s)
Use new Color and Classification methods.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26