/[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 1750 - (hide annotations)
Wed Sep 24 15:46:27 2003 UTC (21 years, 5 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 11108 byte(s)
(ExportRenderer.render_legend): Do not
modify the list returned by map.Layers() in place since it is the
actual list of layers used by the map.

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 frank 909 # Frank Koormann <[email protected]>
6 bh 6 #
7     # This program is free software under the GPL (>=v2)
8     # Read the file COPYING coming with Thuban for details.
9    
10     __version__ = "$Revision$"
11    
12 jonathan 938 import cStringIO
13    
14 jonathan 882 from Thuban import _
15    
16 bh 1552 from wxPython.wx import wxPoint, wxRect, wxPen, wxBrush, wxFont, \
17 frank 909 wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \
18 bh 1552 wxBLACK_PEN, wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL, \
19     wxBitmapFromImage, wxImageFromStream, wxBITMAP_TYPE_BMP
20 bh 6
21 jonathan 676 from wxproj import draw_polygon_shape, draw_polygon_init
22 bh 6
23 jonathan 882 from Thuban.UI.common import Color2wxColour
24 frank 909 from Thuban.UI.classifier import ClassDataPreviewer
25     from Thuban.UI.scalebar import ScaleBar
26 jan 374
27 bh 1562 from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
28     SHAPETYPE_POINT, RAW_SHAPEFILE
29 bh 6
30 jonathan 1343 from Thuban.Model.color import Transparent
31 jonathan 1165 import Thuban.Model.resource
32 bh 6
33 bh 1552 from baserenderer import BaseRenderer
34 jonathan 1234
35 bh 1552 class MapRenderer(BaseRenderer):
36 bh 6
37     """Class to render a map onto a wxDC"""
38    
39 bh 1552 TRANSPARENT_PEN = wxTRANSPARENT_PEN
40     TRANSPARENT_BRUSH = wxTRANSPARENT_BRUSH
41 bh 6
42 bh 1552 make_point = wxPoint
43 bh 6
44 bh 1552 def tools_for_property(self, prop):
45     fill = prop.GetFill()
46     if fill is Transparent:
47     brush = self.TRANSPARENT_BRUSH
48 jonathan 798 else:
49 bh 1552 brush = wxBrush(Color2wxColour(fill), wxSOLID)
50 bh 1219
51 bh 1552 stroke = prop.GetLineColor()
52     if stroke is Transparent:
53     pen = self.TRANSPARENT_PEN
54 jonathan 938 else:
55 bh 1552 pen = wxPen(Color2wxColour(stroke), prop.GetLineWidth(), wxSOLID)
56     return pen, brush
57 jonathan 938
58 bh 1552 def low_level_renderer(self, layer):
59     """Override inherited method to provide more efficient renderers
60 bh 686
61 bh 1562 If the underlying data format is not a shapefile or the layer
62     contains points shapes, simply use what the inherited method
63     returns.
64    
65     Otherwise, i.e. for arc and polygon use the more efficient
66     wxproj.draw_polygon_shape and its corresponding parameter
67     created with wxproj.draw_polygon_init.
68 bh 144 """
69 bh 1562 if (layer.ShapeStore().RawShapeFormat() == RAW_SHAPEFILE
70     and layer.ShapeType() in (SHAPETYPE_ARC, SHAPETYPE_POLYGON)):
71 bh 1552 offx, offy = self.offset
72 bh 1591 return (True, draw_polygon_shape,
73 bh 1562 draw_polygon_init(layer.ShapeStore().Shapefile(),
74     self.dc, self.map.projection,
75 bh 1552 layer.projection,
76 bh 1562 self.scale, -self.scale, offx, offy))
77     else:
78     return BaseRenderer.low_level_renderer(self, layer)
79 bh 6
80 bh 1552 def label_font(self):
81     return wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
82 bh 6
83 bh 1552 def draw_raster_data(self, data):
84     stream = cStringIO.StringIO(data)
85     image = wxImageFromStream(stream, wxBITMAP_TYPE_BMP)
86     bitmap = wxBitmapFromImage(image)
87     self.dc.DrawBitmap(bitmap, 0, 0)
88 jonathan 588
89    
90 bh 6 class ScreenRenderer(MapRenderer):
91    
92     # On the screen we want to see only visible layers by default
93     honor_visibility = 1
94 bh 1552
95 bh 535 def RenderMap(self, map, region, selected_layer, selected_shapes):
96 bh 144 """Render the map.
97    
98 bh 148 Only the given region (a tuple in window coordinates as returned
99     by a wxrect's asTuple method) needs to be redrawn. Highlight the
100 bh 535 shapes given by the ids in selected_shapes in the
101     selected_layer.
102 bh 144 """
103     self.update_region = region
104 bh 6 self.selected_layer = selected_layer
105 bh 535 self.selected_shapes = selected_shapes
106 bh 6 self.render_map(map)
107    
108     def draw_shape_layer(self, layer):
109     MapRenderer.draw_shape_layer(self, layer)
110 bh 535 if layer is self.selected_layer and self.selected_shapes:
111 bh 6 pen = wxPen(wxBLACK, 3, wxSOLID)
112     brush = wxBrush(wxBLACK, wxCROSS_HATCH)
113 bh 535
114 bh 6 shapetype = layer.ShapeType()
115 bh 1591 useraw, func, param = self.low_level_renderer(layer)
116 bh 1552 args = (pen, brush)
117 bh 535 for index in self.selected_shapes:
118 bh 1591 shape = layer.Shape(index)
119     if useraw:
120     data = shape.RawData()
121     else:
122     data = shape.Points()
123     func(param, data, *args)
124 bh 535
125 bh 1593 def layer_shapes(self, layer):
126 bh 144 """Return the shapeids covered by the region that has to be redrawn
127 bh 6
128 bh 144 Call the layer's ShapesInRegion method to determine the ids so
129     that it can use the quadtree.
130     """
131     # FIXME: the quad-tree should be built from the projected
132     # coordinates not the lat-long ones because it's not trivial to
133     # determine an appropriate rectangle in lat-long for a given
134     # rectangle in projected coordinates which we have to start from
135     # here.
136     proj = self.map.projection
137     if proj is not None:
138     inverse = proj.Inverse
139     else:
140     inverse = None
141    
142     scale = self.scale
143     offx, offy = self.offset
144     xs = []
145     ys = []
146 bh 148 x, y, width, height = self.update_region
147 bh 144 for winx, winy in ((x, y), (x + width, y),
148     (x + width, y + height), (x, y + height)):
149     px = (winx - offx) / scale
150     py = -(winy - offy) / scale
151     if inverse:
152     px, py = inverse(px, py)
153     xs.append(px)
154     ys.append(py)
155     left = min(xs)
156     right = max(xs)
157     top = max(ys)
158     bottom = min(ys)
159    
160     return layer.ShapesInRegion((left, bottom, right, top))
161    
162    
163 frank 909 class ExportRenderer(ScreenRenderer):
164 bh 6
165 frank 909 honor_visibility = 1
166 bh 1552
167     def RenderMap(self, map, region, mapregion,
168 frank 909 selected_layer, selected_shapes ):
169     """Render the map.
170 bh 6
171 frank 909 The rendering device has been specified during initialisation.
172     The device border distance was set in Thuban.UI.view.OutputTranform().
173 bh 1552
174 frank 909 RenderMap renders a frame set (one page frame, one around
175 bh 1552 legend/scalebar and one around the map), the map, the legend and the
176 frank 909 scalebar on the given DC. The map is rendered with the region displayed
177     in the canvas view, centered on the area available for map display.
178     """
179 bh 1552
180 frank 909 self.update_region = region
181     self.selected_layer = selected_layer
182     self.selected_shapes = selected_shapes
183    
184 bh 1552 # Get some dimensions
185 frank 909 llx, lly, urx, ury = region
186     self.mapregion = mapregion
187     mminx, mminy, mmaxx, mmaxy = self.mapregion
188    
189 bh 1552 # Manipulate the offset to position the map
190 frank 909 offx, offy = self.offset
191     # 1. Shift to corner of map drawing area
192 bh 1552 offx = offx + mminx
193 frank 909 offy = offy + mminy
194    
195     # 2. Center the map on the map drawing area:
196 bh 1552 # region identifies the region on the canvas view:
197 frank 909 # center of map drawing area - half the size of region: rendering origin
198     self.shiftx = (mmaxx - mminx)*0.5 - (urx - llx)*0.5
199     self.shifty = (mmaxy - mminy)*0.5 - (ury - lly)*0.5
200    
201     self.offset = (offx+self.shiftx, offy+self.shifty)
202    
203     # Draw the map
204     self.dc.BeginDrawing()
205     self.dc.DestroyClippingRegion()
206 bh 1552 self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty,
207 frank 909 urx, ury)
208     self.render_map(map)
209     self.dc.EndDrawing()
210    
211     # Draw the rest (frames, legend, scalebar)
212     self.dc.BeginDrawing()
213     self.dc.DestroyClippingRegion()
214    
215     # Force the font for Legend drawing
216     font = wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
217     self.dc.SetFont(font)
218    
219     self.render_frame(region)
220     self.render_legend(map)
221     self.render_scalebar(map)
222     self.dc.EndDrawing()
223    
224     def render_frame(self, region):
225     """Render the frames for map and legend/scalebar."""
226    
227     dc = self.dc
228     dc.SetPen(wxBLACK_PEN)
229     dc.SetBrush(wxTRANSPARENT_BRUSH)
230    
231     # Dimension stuff
232     width, height = dc.GetSizeTuple()
233     mminx, mminy, mmaxx, mmaxy = self.mapregion
234    
235     # Page Frame
236     dc.DrawRectangle(15,15,width-30, (mmaxy-mminy)+10)
237 bh 1552
238 frank 909 # Map Frame
239     llx, lly, urx, ury = region
240     dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury)
241 bh 1552
242 frank 909 # Legend Frame
243     dc.DrawRectangle(mmaxx+10,mminy,(width-20) - (mmaxx+10), mmaxy-mminy)
244    
245     dc.DestroyClippingRegion()
246     dc.SetClippingRegion(mmaxx+10,mminy,
247     (width-20) - (mmaxx+10), mmaxy-mminy)
248    
249     def render_legend(self, map):
250     """Render the legend on the Map."""
251    
252     previewer = ClassDataPreviewer()
253     dc = self.dc
254     dc.SetPen(wxBLACK_PEN)
255     dc.SetBrush(wxTRANSPARENT_BRUSH)
256    
257     # Dimension stuff
258     width, height = dc.GetSizeTuple()
259     mminx, mminy, mmaxx, mmaxy = self.mapregion
260     textwidth, textheight = dc.GetTextExtent("0")
261     iconwidth = textheight
262     iconheight = textheight
263     stepy = textheight+3
264     dx = 10
265 bh 1552 posx = mmaxx + 10 + 5 # 10 pix distance mapframe/legend frame,
266 frank 909 # 5 pix inside legend frame
267     posy = mminy + 5 # 5 pix inside legend frame
268 bh 1552
269 frank 909 # Render the legend
270     dc.SetTextForeground(wxBLACK)
271     if map.HasLayers():
272 bh 1750 layers = map.Layers()[:]
273 frank 1324 layers.reverse()
274     for l in layers:
275 frank 909 if l.Visible():
276     # Render title
277     dc.DrawText(l.Title(), posx, posy)
278     posy+=stepy
279 jonathan 1298 if l.HasClassification():
280     # Render classification
281     clazz = l.GetClassification()
282     shapeType = l.ShapeType()
283     for g in clazz:
284     if g.IsVisible():
285 bh 1552 previewer.Draw(dc,
286     wxRect(posx+dx, posy,
287     iconwidth, iconheight),
288 jonathan 1298 g.GetProperties(), shapeType)
289 bh 1552 dc.DrawText(g.GetDisplayText(),
290 jonathan 1298 posx+2*dx+iconwidth, posy)
291     posy+=stepy
292 bh 1552
293 frank 909 def render_scalebar(self, map):
294     """Render the scalebar."""
295    
296     scalebar = ScaleBar(map)
297    
298     # Dimension stuff
299     width, height = self.dc.GetSizeTuple()
300     mminx, mminy, mmaxx, mmaxy = self.mapregion
301 bh 1552
302 frank 909 # Render the scalebar
303 bh 1552 scalebar.DrawScaleBar(self.scale, self.dc,
304 frank 909 (mmaxx+10+5, mmaxy-25),
305     ((width-15-5) - (mmaxx+10+5),20)
306     )
307     # 10 pix between map and legend frame, 5 pix inside legend frame
308     # 25 pix from the legend frame bottom line
309     # Width: 15 pix from DC border, 5 pix inside frame, 10, 5 as above
310     # Height: 20
311    
312     class PrinterRenderer(ExportRenderer):
313    
314     # Printing as well as Export / Screen display only the visible layer.
315     honor_visibility = 1
316    

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26