/[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 610 by jonathan, Fri Apr 4 13:56:59 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
      wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \  
      wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL  
   
 from wxproj import draw_polygon_shape  
13    
14  from Thuban import _  from Thuban import _
 from Thuban.UI.common import *  
15    
16  from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \  from wxPython.wx import wxMemoryDC, wxEmptyBitmap, \
17       SHAPETYPE_POINT      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
25    from gdalwarp import ProjectRasterFile
26    
27    from Thuban.UI.common import Color2wxColour
28    from Thuban.UI.classifier import ClassDataPreviewer
29    from Thuban.UI.scalebar import ScaleBar
30    
31    from Thuban.Model.layer import Layer, RasterLayer, \
32         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    
         defaultProps = lc.GetDefaultGroup().GetProperties()  
118    
119            if shapetype != SHAPETYPE_POINT:
120                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  
                 #  
                 prop = lc.GetProperties(value)  
133              else:              else:
134                  prop = defaultProps                  record = layer.table.ReadRowAsDict(i)
135                    assert record is not None
136                    group = lc.FindGroup(record[field])
137    
138    
139                if not group.IsVisible():
140                    continue
141    
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()
148                      fill = Color.Transparent  
149                  else:                  if prop != old_prop:
150                      fill = prop.GetFill()                      old_prop = prop
151        
152                  if fill is Color.Transparent:                      if shapetype == SHAPETYPE_ARC:
153                      brush = wxTRANSPARENT_BRUSH                          fill = Color.Transparent
154                  else:                      else:
155                      color = Color2wxColour(fill)                          fill = prop.GetFill()
156                      brush = wxBrush(color, wxSOLID)  
157        
158                  stroke = prop.GetLineColor()                      if fill is Color.Transparent:
159                  stroke_width = prop.GetLineWidth()                          brush = wxTRANSPARENT_BRUSH
160                  if stroke is Color.Transparent:                      else:
161                      pen = wxTRANSPARENT_PEN                          color = Color2wxColour(fill)
162                  else:                          brush = wxBrush(color, wxSOLID)
163                      color = Color2wxColour(stroke)  
164                      pen = wxPen(color, stroke_width, wxSOLID)                      stroke = prop.GetLineColor()
165                            stroke_width = prop.GetLineWidth()
166              if shapetype == SHAPETYPE_POINT:                      if stroke is Color.Transparent:
167                  self.dc.SetBrush(brush)                          pen = wxTRANSPARENT_PEN
168                  self.dc.SetPen(pen)                      else:
169                  self.draw_point_shape(layer, i)                          color = Color2wxColour(stroke)
170              else:                          pen = wxPen(color, stroke_width, wxSOLID)
171                  self.draw_polygon_shape(layer, i, pen, brush)  
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.
222            
223          The default implementation simply returns all ids in the layer.          The default implementation simply returns all ids in the layer.
224          Override in derived classes to be more precise.          Override in derived classes to be more precise.
225          """          """
226          return range(layer.NumShapes())          return range(layer.NumShapes())
227    
228      def draw_polygon_shape(self, layer, index, pen, brush):      def polygon_render_param(self, layer):
229          offx, offy = self.offset                  """Return the low-lever render parameter for the layer"""
230          draw_polygon_shape(layer.shapefile.cobject(), index,          offx, offy = self.offset
231                             self.dc, pen, brush,          return draw_polygon_init(layer.shapefile, self.dc,
232                             self.map.projection, layer.projection,                                   self.map.projection,
233                             self.scale, -self.scale, offx, offy)                                   layer.projection,
234                                     self.scale, -self.scale,
235                                     offx, offy)
236    
237        def draw_polygon_shape(self, draw_polygon_info, index, pen, brush):
238            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 254  class ScreenRenderer(MapRenderer): Line 339  class ScreenRenderer(MapRenderer):
339    
340              shapetype = layer.ShapeType()              shapetype = layer.ShapeType()
341              if shapetype == SHAPETYPE_POLYGON:              if shapetype == SHAPETYPE_POLYGON:
342                    offx, offy = self.offset
343                    renderparam = self.polygon_render_param(layer)
344                  func = self.draw_polygon_shape                  func = self.draw_polygon_shape
345                  args = (pen, brush)                  args = (pen, brush)
346              elif shapetype == SHAPETYPE_ARC:              elif shapetype == SHAPETYPE_ARC:
347                    renderparam = self.polygon_render_param(layer)
348                  func = self.draw_polygon_shape                  func = self.draw_polygon_shape
349                  args = (pen, None)                  args = (pen, None)
350              elif shapetype == SHAPETYPE_POINT:              elif shapetype == SHAPETYPE_POINT:
351                    renderparam = layer
352                  self.dc.SetBrush(brush)                  self.dc.SetBrush(brush)
353                  self.dc.SetPen(pen)                  self.dc.SetPen(pen)
354                  func = self.draw_point_shape                  func = self.draw_point_shape
# Line 268  class ScreenRenderer(MapRenderer): Line 357  class ScreenRenderer(MapRenderer):
357                  raise TypeError(_("Unhandled shape type %s") % shapetype)                  raise TypeError(_("Unhandled shape type %s") % shapetype)
358    
359              for index in self.selected_shapes:              for index in self.selected_shapes:
360                  func(layer, index, *args)                  func(renderparam, index, *args)
361    
362    
363      def layer_ids(self, layer):      def layer_ids(self, layer):
364          """Return the shapeids covered by the region that has to be redrawn          """Return the shapeids covered by the region that has to be redrawn
# Line 308  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.610  
changed lines
  Added in v.1103

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26