/[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 1562 - (hide annotations)
Thu Aug 7 17:53:37 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/renderer.py
File MIME type: text/x-python
File size: 10912 byte(s)
(MapRenderer.low_level_renderer): Check
the raw data format and only use an optimized version of its a
shapefile.

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 1562 return (draw_polygon_shape,
73     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 1552 func, param = self.low_level_renderer(layer)
116     args = (pen, brush)
117 bh 535 for index in self.selected_shapes:
118 bh 1552 func(param, index, *args)
119 bh 535
120 bh 144 def layer_ids(self, layer):
121     """Return the shapeids covered by the region that has to be redrawn
122 bh 6
123 bh 144 Call the layer's ShapesInRegion method to determine the ids so
124     that it can use the quadtree.
125     """
126     # FIXME: the quad-tree should be built from the projected
127     # coordinates not the lat-long ones because it's not trivial to
128     # determine an appropriate rectangle in lat-long for a given
129     # rectangle in projected coordinates which we have to start from
130     # here.
131     proj = self.map.projection
132     if proj is not None:
133     inverse = proj.Inverse
134     else:
135     inverse = None
136    
137     scale = self.scale
138     offx, offy = self.offset
139     xs = []
140     ys = []
141 bh 148 x, y, width, height = self.update_region
142 bh 144 for winx, winy in ((x, y), (x + width, y),
143     (x + width, y + height), (x, y + height)):
144     px = (winx - offx) / scale
145     py = -(winy - offy) / scale
146     if inverse:
147     px, py = inverse(px, py)
148     xs.append(px)
149     ys.append(py)
150     left = min(xs)
151     right = max(xs)
152     top = max(ys)
153     bottom = min(ys)
154    
155     return layer.ShapesInRegion((left, bottom, right, top))
156    
157    
158 frank 909 class ExportRenderer(ScreenRenderer):
159 bh 6
160 frank 909 honor_visibility = 1
161 bh 1552
162     def RenderMap(self, map, region, mapregion,
163 frank 909 selected_layer, selected_shapes ):
164     """Render the map.
165 bh 6
166 frank 909 The rendering device has been specified during initialisation.
167     The device border distance was set in Thuban.UI.view.OutputTranform().
168 bh 1552
169 frank 909 RenderMap renders a frame set (one page frame, one around
170 bh 1552 legend/scalebar and one around the map), the map, the legend and the
171 frank 909 scalebar on the given DC. The map is rendered with the region displayed
172     in the canvas view, centered on the area available for map display.
173     """
174 bh 1552
175 frank 909 self.update_region = region
176     self.selected_layer = selected_layer
177     self.selected_shapes = selected_shapes
178    
179 bh 1552 # Get some dimensions
180 frank 909 llx, lly, urx, ury = region
181     self.mapregion = mapregion
182     mminx, mminy, mmaxx, mmaxy = self.mapregion
183    
184 bh 1552 # Manipulate the offset to position the map
185 frank 909 offx, offy = self.offset
186     # 1. Shift to corner of map drawing area
187 bh 1552 offx = offx + mminx
188 frank 909 offy = offy + mminy
189    
190     # 2. Center the map on the map drawing area:
191 bh 1552 # region identifies the region on the canvas view:
192 frank 909 # center of map drawing area - half the size of region: rendering origin
193     self.shiftx = (mmaxx - mminx)*0.5 - (urx - llx)*0.5
194     self.shifty = (mmaxy - mminy)*0.5 - (ury - lly)*0.5
195    
196     self.offset = (offx+self.shiftx, offy+self.shifty)
197    
198     # Draw the map
199     self.dc.BeginDrawing()
200     self.dc.DestroyClippingRegion()
201 bh 1552 self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty,
202 frank 909 urx, ury)
203     self.render_map(map)
204     self.dc.EndDrawing()
205    
206     # Draw the rest (frames, legend, scalebar)
207     self.dc.BeginDrawing()
208     self.dc.DestroyClippingRegion()
209    
210     # Force the font for Legend drawing
211     font = wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
212     self.dc.SetFont(font)
213    
214     self.render_frame(region)
215     self.render_legend(map)
216     self.render_scalebar(map)
217     self.dc.EndDrawing()
218    
219     def render_frame(self, region):
220     """Render the frames for map and legend/scalebar."""
221    
222     dc = self.dc
223     dc.SetPen(wxBLACK_PEN)
224     dc.SetBrush(wxTRANSPARENT_BRUSH)
225    
226     # Dimension stuff
227     width, height = dc.GetSizeTuple()
228     mminx, mminy, mmaxx, mmaxy = self.mapregion
229    
230     # Page Frame
231     dc.DrawRectangle(15,15,width-30, (mmaxy-mminy)+10)
232 bh 1552
233 frank 909 # Map Frame
234     llx, lly, urx, ury = region
235     dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury)
236 bh 1552
237 frank 909 # Legend Frame
238     dc.DrawRectangle(mmaxx+10,mminy,(width-20) - (mmaxx+10), mmaxy-mminy)
239    
240     dc.DestroyClippingRegion()
241     dc.SetClippingRegion(mmaxx+10,mminy,
242     (width-20) - (mmaxx+10), mmaxy-mminy)
243    
244     def render_legend(self, map):
245     """Render the legend on the Map."""
246    
247     previewer = ClassDataPreviewer()
248     dc = self.dc
249     dc.SetPen(wxBLACK_PEN)
250     dc.SetBrush(wxTRANSPARENT_BRUSH)
251    
252     # Dimension stuff
253     width, height = dc.GetSizeTuple()
254     mminx, mminy, mmaxx, mmaxy = self.mapregion
255     textwidth, textheight = dc.GetTextExtent("0")
256     iconwidth = textheight
257     iconheight = textheight
258     stepy = textheight+3
259     dx = 10
260 bh 1552 posx = mmaxx + 10 + 5 # 10 pix distance mapframe/legend frame,
261 frank 909 # 5 pix inside legend frame
262     posy = mminy + 5 # 5 pix inside legend frame
263 bh 1552
264 frank 909 # Render the legend
265     dc.SetTextForeground(wxBLACK)
266     if map.HasLayers():
267 frank 1324 layers = map.Layers()
268     layers.reverse()
269     for l in layers:
270 frank 909 if l.Visible():
271     # Render title
272     dc.DrawText(l.Title(), posx, posy)
273     posy+=stepy
274 jonathan 1298 if l.HasClassification():
275     # Render classification
276     clazz = l.GetClassification()
277     shapeType = l.ShapeType()
278     for g in clazz:
279     if g.IsVisible():
280 bh 1552 previewer.Draw(dc,
281     wxRect(posx+dx, posy,
282     iconwidth, iconheight),
283 jonathan 1298 g.GetProperties(), shapeType)
284 bh 1552 dc.DrawText(g.GetDisplayText(),
285 jonathan 1298 posx+2*dx+iconwidth, posy)
286     posy+=stepy
287 bh 1552
288 frank 909 def render_scalebar(self, map):
289     """Render the scalebar."""
290    
291     scalebar = ScaleBar(map)
292    
293     # Dimension stuff
294     width, height = self.dc.GetSizeTuple()
295     mminx, mminy, mmaxx, mmaxy = self.mapregion
296 bh 1552
297 frank 909 # Render the scalebar
298 bh 1552 scalebar.DrawScaleBar(self.scale, self.dc,
299 frank 909 (mmaxx+10+5, mmaxy-25),
300     ((width-15-5) - (mmaxx+10+5),20)
301     )
302     # 10 pix between map and legend frame, 5 pix inside legend frame
303     # 25 pix from the legend frame bottom line
304     # Width: 15 pix from DC border, 5 pix inside frame, 10, 5 as above
305     # Height: 20
306    
307     class PrinterRenderer(ExportRenderer):
308    
309     # Printing as well as Export / Screen display only the visible layer.
310     honor_visibility = 1
311    

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26