/[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 442 - (hide annotations)
Thu Feb 27 15:55:25 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10043 byte(s)
Use new Classification and Group functions.  Use common.py functions.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26