/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/renderer.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/renderer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1562 - (show 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 # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 # Jonathan Coles <[email protected]>
5 # Frank Koormann <[email protected]>
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 import cStringIO
13
14 from Thuban import _
15
16 from wxPython.wx import wxPoint, wxRect, wxPen, wxBrush, wxFont, \
17 wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \
18 wxBLACK_PEN, wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL, \
19 wxBitmapFromImage, wxImageFromStream, wxBITMAP_TYPE_BMP
20
21 from wxproj import draw_polygon_shape, draw_polygon_init
22
23 from Thuban.UI.common import Color2wxColour
24 from Thuban.UI.classifier import ClassDataPreviewer
25 from Thuban.UI.scalebar import ScaleBar
26
27 from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
28 SHAPETYPE_POINT, RAW_SHAPEFILE
29
30 from Thuban.Model.color import Transparent
31 import Thuban.Model.resource
32
33 from baserenderer import BaseRenderer
34
35 class MapRenderer(BaseRenderer):
36
37 """Class to render a map onto a wxDC"""
38
39 TRANSPARENT_PEN = wxTRANSPARENT_PEN
40 TRANSPARENT_BRUSH = wxTRANSPARENT_BRUSH
41
42 make_point = wxPoint
43
44 def tools_for_property(self, prop):
45 fill = prop.GetFill()
46 if fill is Transparent:
47 brush = self.TRANSPARENT_BRUSH
48 else:
49 brush = wxBrush(Color2wxColour(fill), wxSOLID)
50
51 stroke = prop.GetLineColor()
52 if stroke is Transparent:
53 pen = self.TRANSPARENT_PEN
54 else:
55 pen = wxPen(Color2wxColour(stroke), prop.GetLineWidth(), wxSOLID)
56 return pen, brush
57
58 def low_level_renderer(self, layer):
59 """Override inherited method to provide more efficient renderers
60
61 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 """
69 if (layer.ShapeStore().RawShapeFormat() == RAW_SHAPEFILE
70 and layer.ShapeType() in (SHAPETYPE_ARC, SHAPETYPE_POLYGON)):
71 offx, offy = self.offset
72 return (draw_polygon_shape,
73 draw_polygon_init(layer.ShapeStore().Shapefile(),
74 self.dc, self.map.projection,
75 layer.projection,
76 self.scale, -self.scale, offx, offy))
77 else:
78 return BaseRenderer.low_level_renderer(self, layer)
79
80 def label_font(self):
81 return wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
82
83 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
89
90 class ScreenRenderer(MapRenderer):
91
92 # On the screen we want to see only visible layers by default
93 honor_visibility = 1
94
95 def RenderMap(self, map, region, selected_layer, selected_shapes):
96 """Render the map.
97
98 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 shapes given by the ids in selected_shapes in the
101 selected_layer.
102 """
103 self.update_region = region
104 self.selected_layer = selected_layer
105 self.selected_shapes = selected_shapes
106 self.render_map(map)
107
108 def draw_shape_layer(self, layer):
109 MapRenderer.draw_shape_layer(self, layer)
110 if layer is self.selected_layer and self.selected_shapes:
111 pen = wxPen(wxBLACK, 3, wxSOLID)
112 brush = wxBrush(wxBLACK, wxCROSS_HATCH)
113
114 shapetype = layer.ShapeType()
115 func, param = self.low_level_renderer(layer)
116 args = (pen, brush)
117 for index in self.selected_shapes:
118 func(param, index, *args)
119
120 def layer_ids(self, layer):
121 """Return the shapeids covered by the region that has to be redrawn
122
123 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 x, y, width, height = self.update_region
142 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 class ExportRenderer(ScreenRenderer):
159
160 honor_visibility = 1
161
162 def RenderMap(self, map, region, mapregion,
163 selected_layer, selected_shapes ):
164 """Render the map.
165
166 The rendering device has been specified during initialisation.
167 The device border distance was set in Thuban.UI.view.OutputTranform().
168
169 RenderMap renders a frame set (one page frame, one around
170 legend/scalebar and one around the map), the map, the legend and the
171 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
175 self.update_region = region
176 self.selected_layer = selected_layer
177 self.selected_shapes = selected_shapes
178
179 # Get some dimensions
180 llx, lly, urx, ury = region
181 self.mapregion = mapregion
182 mminx, mminy, mmaxx, mmaxy = self.mapregion
183
184 # Manipulate the offset to position the map
185 offx, offy = self.offset
186 # 1. Shift to corner of map drawing area
187 offx = offx + mminx
188 offy = offy + mminy
189
190 # 2. Center the map on the map drawing area:
191 # region identifies the region on the canvas view:
192 # 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 self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty,
202 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
233 # Map Frame
234 llx, lly, urx, ury = region
235 dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury)
236
237 # 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 posx = mmaxx + 10 + 5 # 10 pix distance mapframe/legend frame,
261 # 5 pix inside legend frame
262 posy = mminy + 5 # 5 pix inside legend frame
263
264 # Render the legend
265 dc.SetTextForeground(wxBLACK)
266 if map.HasLayers():
267 layers = map.Layers()
268 layers.reverse()
269 for l in layers:
270 if l.Visible():
271 # Render title
272 dc.DrawText(l.Title(), posx, posy)
273 posy+=stepy
274 if l.HasClassification():
275 # Render classification
276 clazz = l.GetClassification()
277 shapeType = l.ShapeType()
278 for g in clazz:
279 if g.IsVisible():
280 previewer.Draw(dc,
281 wxRect(posx+dx, posy,
282 iconwidth, iconheight),
283 g.GetProperties(), shapeType)
284 dc.DrawText(g.GetDisplayText(),
285 posx+2*dx+iconwidth, posy)
286 posy+=stepy
287
288 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
297 # Render the scalebar
298 scalebar.DrawScaleBar(self.scale, self.dc,
299 (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