/[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 1927 - (hide annotations)
Mon Nov 10 16:57:35 2003 UTC (21 years, 4 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 12122 byte(s)
(raster_format_map): New. Mapping form the
strings of the format parameter of draw_raster_data method to wx
constants
(MapRenderer.draw_raster_data): Add the format parameter and use
raster_format_map to map it to the right wxwindows constant for
wxImageFromStream

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26