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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 686 by bh, Wed Apr 16 13:22:25 2003 UTC revision 1103 by jonathan, Fri May 30 06:29:25 2003 UTC
# Line 2  Line 2 
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
5    # Frank Koormann <[email protected]>
6  #  #
7  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
8  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
9    
10  __version__ = "$Revision$"  __version__ = "$Revision$"
11    
12  from wxPython.wx import wxPoint, wxPen, wxBrush, wxFont, \  import cStringIO
13       wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \  
14       wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL  from Thuban import _
15    
16    from wxPython.wx import wxMemoryDC, wxEmptyBitmap, \
17        wxPoint, wxRect, wxPen, wxBrush, wxFont, \
18        wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \
19        wxBLACK_PEN, wxRED_PEN, wxBLACK, \
20        wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL, \
21        wxBitmap, wxImageFromBitmap, wxBitmapFromImage, \
22        wxImageFromStream, wxBITMAP_TYPE_BMP
23    
24  from wxproj import draw_polygon_shape, draw_polygon_init  from wxproj import draw_polygon_shape, draw_polygon_init
25    from gdalwarp import ProjectRasterFile
26    
27  from Thuban import _  from Thuban.UI.common import Color2wxColour
28  from Thuban.UI.common import *  from Thuban.UI.classifier import ClassDataPreviewer
29    from Thuban.UI.scalebar import ScaleBar
30    
31  from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \  from Thuban.Model.layer import Layer, RasterLayer, \
32       SHAPETYPE_POINT       SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
33  from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \  from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
34       ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE       ALIGN_LEFT, ALIGN_RIGHT, ALIGN_BASELINE
35    
36  from Thuban.Model.classification import Classification  from Thuban.Model.classification import Classification
37  from Thuban.Model.color import Color  from Thuban.Model.color import Color
38    
   
39  class MapRenderer:  class MapRenderer:
40    
41      """Class to render a map onto a wxDC"""      """Class to render a map onto a wxDC"""
# Line 49  class MapRenderer: Line 59  class MapRenderer:
59          """          """
60          # resolution in pixel/inch          # resolution in pixel/inch
61    
         assert scale > 0  
   
62          self.dc = dc          self.dc = dc
63          self.scale = scale          self.scale = scale
64          self.offset = offset          self.offset = offset
# Line 62  class MapRenderer: Line 70  class MapRenderer:
70    
71      def render_map(self, map):      def render_map(self, map):
72          self.map = map          self.map = map
73            seenRaster = True
74    
75            if self.scale == 0:
76                return
77    
78            #
79            # This is only a good optimization if there is only one
80            # raster layer and the image covers the entire window (as
81            # it currently does).
82            #
83            for layer in map.Layers():
84                if isinstance(layer, RasterLayer):
85                    seenRaster = False
86                    break
87    
88          for layer in map.Layers():          for layer in map.Layers():
89              # if honor_visibility is true, only draw visible layers,              # if honor_visibility is true, only draw visible layers,
90              # otherwise draw all layers              # otherwise draw all layers
91              if not self.honor_visibility or layer.Visible():              if not self.honor_visibility or layer.Visible():
92                  self.draw_shape_layer(layer)                  if isinstance(layer, Layer) and seenRaster:
93                        self.draw_shape_layer(layer)
94                    elif isinstance(layer, RasterLayer):
95                        self.draw_raster_layer(layer)
96                        seenRaster = True
97    
98          self.draw_label_layer(map.LabelLayer())          self.draw_label_layer(map.LabelLayer())
99    
100      def draw_shape_layer(self, layer):      def draw_shape_layer(self, layer):
# Line 82  class MapRenderer: Line 110  class MapRenderer:
110          pen   = wxTRANSPARENT_PEN          pen   = wxTRANSPARENT_PEN
111    
112          old_prop = None          old_prop = None
113            old_group = None
114          lc = layer.GetClassification()          lc = layer.GetClassification()
115          field = lc.GetField()          field = lc.GetField()
116            defaultGroup = lc.GetDefaultGroup()
117    
118    
119          if shapetype != SHAPETYPE_POINT:          if shapetype != SHAPETYPE_POINT:
120              polygon_render_param = self.polygon_render_param(layer)              polygon_render_param = self.polygon_render_param(layer)
121    
122            if shapetype == SHAPETYPE_POINT:
123                draw_func = lambda i: \
124                       self.draw_point_shape(layer, i)
125            else:
126                draw_func = lambda i: \
127                       self.draw_polygon_shape(polygon_render_param, i, pen, brush)
128                
129          for i in self.layer_ids(layer):          for i in self.layer_ids(layer):
             value = None  
130    
131              if field is not None:              if field is None:
132                  try:                  group = defaultGroup
                     record = layer.table.read_record(i)  
                     if record is not None:  
                         value = record[field]  
                 except:  
                     pass  
   
                 #  
                 # if the above statements fail 'value' should  
                 # be null, at which point this call will  
                 # at least retreive the NullData  
                 #  
   
                 group = lc.FindGroup(value)  
   
                 #prop = lc.GetProperties(value)  
133              else:              else:
134                  group = lc.GetDefaultGroup()                  record = layer.table.ReadRowAsDict(i)
135                    assert record is not None
136                    group = lc.FindGroup(record[field])
137    
138    
139              if not group.IsVisible():              if not group.IsVisible():
140                  continue                  continue
141    
             prop = group.GetProperties()  
142    
143              # don't recreate new objects if they are the same as before              # don't recreate new objects if they are the same as before
144              if prop != old_prop:              if group is not old_group:
145                  old_prop = prop                  old_group = group
146    
147                  if shapetype == SHAPETYPE_ARC:                  prop = group.GetProperties()
                     fill = Color.Transparent  
                 else:  
                     fill = prop.GetFill()  
   
   
                 if fill is Color.Transparent:  
                     brush = wxTRANSPARENT_BRUSH  
                 else:  
                     color = Color2wxColour(fill)  
                     brush = wxBrush(color, wxSOLID)  
   
                 stroke = prop.GetLineColor()  
                 stroke_width = prop.GetLineWidth()  
                 if stroke is Color.Transparent:  
                     pen = wxTRANSPARENT_PEN  
                 else:  
                     color = Color2wxColour(stroke)  
                     pen = wxPen(color, stroke_width, wxSOLID)  
148    
149                    if prop != old_prop:
150                        old_prop = prop
151    
152              if shapetype == SHAPETYPE_POINT:                      if shapetype == SHAPETYPE_ARC:
153                  self.dc.SetBrush(brush)                          fill = Color.Transparent
154                  self.dc.SetPen(pen)                      else:
155                  self.draw_point_shape(layer, i)                          fill = prop.GetFill()
156              else:  
157                  self.draw_polygon_shape(polygon_render_param, i, pen, brush)  
158                        if fill is Color.Transparent:
159                            brush = wxTRANSPARENT_BRUSH
160                        else:
161                            color = Color2wxColour(fill)
162                            brush = wxBrush(color, wxSOLID)
163    
164                        stroke = prop.GetLineColor()
165                        stroke_width = prop.GetLineWidth()
166                        if stroke is Color.Transparent:
167                            pen = wxTRANSPARENT_PEN
168                        else:
169                            color = Color2wxColour(stroke)
170                            pen = wxPen(color, stroke_width, wxSOLID)
171    
172                        if shapetype == SHAPETYPE_POINT:
173                            self.dc.SetBrush(brush)
174                            self.dc.SetPen(pen)
175    
176                draw_func(i)
177    
178        def draw_raster_layer(self, layer):
179            data = None
180            offx, offy = self.offset
181            width, height = self.dc.GetSizeTuple()
182    
183            inProj = ""
184            proj = layer.GetProjection()
185            if proj is not None:
186                for p in proj.GetAllParameters():
187                    inProj += "+" + p + " "
188    
189            outProj = ""
190            proj = self.map.GetProjection()
191            if proj is not None:
192                for p in proj.GetAllParameters():
193                    outProj += "+" + p + " "
194    
195            xmin = (0 - offx) / self.scale
196            ymin = (offy - height) / self.scale
197            xmax = (width - offx) / self.scale
198            ymax = (offy - 0) / self.scale
199    
200            try:
201                data = ProjectRasterFile(
202                    layer.GetImageFilename(),
203                    inProj,
204                    outProj,
205                    (xmin, ymin, xmax, ymax),
206                    "", (width, height))
207            except IOError, (strerr):
208                print strerr
209            except (AttributeError, ValueError):
210                pass
211            else:
212                if data is not None:
213                    stream = cStringIO.StringIO(data)
214                    image = wxImageFromStream(stream, wxBITMAP_TYPE_BMP)
215                    bitmap = wxBitmapFromImage(image)
216                    self.dc.BeginDrawing()
217                    self.dc.DrawBitmap(bitmap, 0, 0)
218                    self.dc.EndDrawing()
219    
220      def layer_ids(self, layer):      def layer_ids(self, layer):
221          """Return the shape ids of the given layer that have to be drawn.          """Return the shape ids of the given layer that have to be drawn.
# Line 171  class MapRenderer: Line 238  class MapRenderer:
238          draw_polygon_shape(draw_polygon_info, index, pen, brush)          draw_polygon_shape(draw_polygon_info, index, pen, brush)
239    
240      def projected_points(self, layer, index):      def projected_points(self, layer, index):
241          proj = self.map.projection          proj = self.map.GetProjection()
242          if proj is not None:          if proj is not None:
243              forward = proj.Forward              forward = proj.Forward
244          else:          else:
245              forward = None              forward = None
246          proj = layer.projection          proj = layer.GetProjection()
247          if proj is not None:          if proj is not None:
248              inverse = proj.Inverse              inverse = proj.Inverse
249          else:          else:
# Line 331  class ScreenRenderer(MapRenderer): Line 398  class ScreenRenderer(MapRenderer):
398          return layer.ShapesInRegion((left, bottom, right, top))          return layer.ShapesInRegion((left, bottom, right, top))
399    
400    
401  class PrinterRender(MapRenderer):  class ExportRenderer(ScreenRenderer):
402    
403      # When printing we want to see all layers      honor_visibility = 1
     honor_visibility = 0  
   
     RenderMap = MapRenderer.render_map  
404            
405        def RenderMap(self, map, region, mapregion,
406                      selected_layer, selected_shapes ):
407            """Render the map.
408    
409            The rendering device has been specified during initialisation.
410            The device border distance was set in Thuban.UI.view.OutputTranform().
411            
412            RenderMap renders a frame set (one page frame, one around
413            legend/scalebar and one around the map), the map, the legend and the
414            scalebar on the given DC. The map is rendered with the region displayed
415            in the canvas view, centered on the area available for map display.
416            """
417            
418            self.update_region = region
419            self.selected_layer = selected_layer
420            self.selected_shapes = selected_shapes
421    
422            # Get some dimensions
423            llx, lly, urx, ury = region
424            self.mapregion = mapregion
425            mminx, mminy, mmaxx, mmaxy = self.mapregion
426    
427            # Manipulate the offset to position the map
428            offx, offy = self.offset
429            # 1. Shift to corner of map drawing area
430            offx = offx + mminx
431            offy = offy + mminy
432    
433            # 2. Center the map on the map drawing area:
434            # region identifies the region on the canvas view:
435            # center of map drawing area - half the size of region: rendering origin
436            self.shiftx = (mmaxx - mminx)*0.5 - (urx - llx)*0.5
437            self.shifty = (mmaxy - mminy)*0.5 - (ury - lly)*0.5
438    
439            self.offset = (offx+self.shiftx, offy+self.shifty)
440    
441            # Draw the map
442            self.dc.BeginDrawing()
443            self.dc.DestroyClippingRegion()
444            self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty,
445                                      urx, ury)
446            self.render_map(map)
447            self.dc.EndDrawing()
448    
449            # Draw the rest (frames, legend, scalebar)
450            self.dc.BeginDrawing()
451            self.dc.DestroyClippingRegion()
452    
453            # Force the font for Legend drawing
454            font = wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
455            self.dc.SetFont(font)
456    
457            self.render_frame(region)
458            self.render_legend(map)
459            self.render_scalebar(map)
460            self.dc.EndDrawing()
461    
462        def render_frame(self, region):
463            """Render the frames for map and legend/scalebar."""
464    
465            dc = self.dc
466            dc.SetPen(wxBLACK_PEN)
467            dc.SetBrush(wxTRANSPARENT_BRUSH)
468    
469            # Dimension stuff
470            width, height = dc.GetSizeTuple()
471            mminx, mminy, mmaxx, mmaxy = self.mapregion
472    
473            # Page Frame
474            dc.DrawRectangle(15,15,width-30, (mmaxy-mminy)+10)
475            
476            # Map Frame
477            llx, lly, urx, ury = region
478            dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury)
479            
480            # Legend Frame
481            dc.DrawRectangle(mmaxx+10,mminy,(width-20) - (mmaxx+10), mmaxy-mminy)
482    
483            dc.DestroyClippingRegion()
484            dc.SetClippingRegion(mmaxx+10,mminy,
485                                 (width-20) - (mmaxx+10), mmaxy-mminy)
486    
487        def render_legend(self, map):
488            """Render the legend on the Map."""
489    
490            previewer = ClassDataPreviewer()
491            dc = self.dc
492            dc.SetPen(wxBLACK_PEN)
493            dc.SetBrush(wxTRANSPARENT_BRUSH)
494    
495            # Dimension stuff
496            width, height = dc.GetSizeTuple()
497            mminx, mminy, mmaxx, mmaxy = self.mapregion
498            textwidth, textheight = dc.GetTextExtent("0")
499            iconwidth  = textheight
500            iconheight = textheight
501            stepy = textheight+3
502            dx = 10
503            posx = mmaxx + 10 + 5   # 10 pix distance mapframe/legend frame,
504                                    # 5 pix inside legend frame
505            posy = mminy + 5        # 5 pix inside legend frame
506            
507            # Render the legend
508            dc.SetTextForeground(wxBLACK)
509            if map.HasLayers():
510                for l in map.Layers():
511                    if l.Visible():
512                        # Render title
513                        dc.DrawText(l.Title(), posx, posy)
514                        posy+=stepy
515                        # Render classification
516                        clazz = l.GetClassification()
517                        shapeType = l.ShapeType()
518                        for g in clazz:
519                            if g.IsVisible():
520                                previewer.Draw(dc,
521                                    wxRect(posx+dx, posy, iconwidth, iconheight),
522                                    g.GetProperties(), shapeType)
523                                dc.DrawText(g.GetDisplayText(),
524                                            posx+2*dx+iconwidth, posy)
525                                posy+=stepy
526            
527        def render_scalebar(self, map):
528            """Render the scalebar."""
529    
530            scalebar = ScaleBar(map)
531    
532            # Dimension stuff
533            width, height = self.dc.GetSizeTuple()
534            mminx, mminy, mmaxx, mmaxy = self.mapregion
535          
536            # Render the scalebar
537            scalebar.DrawScaleBar(self.scale, self.dc,
538                                 (mmaxx+10+5, mmaxy-25),
539                                 ((width-15-5) - (mmaxx+10+5),20)
540                                )
541            # 10 pix between map and legend frame, 5 pix inside legend frame
542            # 25 pix from the legend frame bottom line
543            # Width: 15 pix from DC border, 5 pix inside frame, 10, 5 as above
544            # Height: 20
545    
546    class PrinterRenderer(ExportRenderer):
547    
548        # Printing as well as Export / Screen display only the visible layer.
549        honor_visibility = 1
550    

Legend:
Removed from v.686  
changed lines
  Added in v.1103

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26