/[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 588 by jonathan, Tue Apr 1 15:58:02 2003 UTC revision 1219 by bh, Mon Jun 16 17:42:54 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    import Thuban.Model.resource
39    
40  class MapRenderer:  class MapRenderer:
41    
# Line 49  class MapRenderer: Line 60  class MapRenderer:
60          """          """
61          # resolution in pixel/inch          # resolution in pixel/inch
62    
         assert(scale > 0)  
   
63          self.dc = dc          self.dc = dc
64          self.scale = scale          self.scale = scale
65          self.offset = offset          self.offset = offset
# Line 62  class MapRenderer: Line 71  class MapRenderer:
71    
72      def render_map(self, map):      def render_map(self, map):
73          self.map = map          self.map = map
74            seenRaster = True
75    
76            if self.scale == 0:
77                return
78    
79            #
80            # This is only a good optimization if there is only one
81            # raster layer and the image covers the entire window (as
82            # it currently does). We note if there is a raster layer
83            # and only begin drawing layers once we have drawn it.
84            # That way we avoid drawing layers that won't be seen.
85            #
86            for layer in map.Layers():
87                if isinstance(layer, RasterLayer) and layer.Visible():
88                    seenRaster = False
89                    break
90    
91          for layer in map.Layers():          for layer in map.Layers():
92              # if honor_visibility is true, only draw visible layers,              # if honor_visibility is true, only draw visible layers,
93              # otherwise draw all layers              # otherwise draw all layers
94              if not self.honor_visibility or layer.Visible():              if not self.honor_visibility or layer.Visible():
95                  self.draw_shape_layer(layer)                  if isinstance(layer, Layer) and seenRaster:
96                        self.draw_shape_layer(layer)
97                    elif isinstance(layer, RasterLayer) \
98                        and Thuban.Model.resource.has_gdal_support():
99                        self.draw_raster_layer(layer)
100                        seenRaster = True
101    
102          self.draw_label_layer(map.LabelLayer())          self.draw_label_layer(map.LabelLayer())
103    
104      def draw_shape_layer(self, layer):      def draw_shape_layer(self, layer):
# Line 82  class MapRenderer: Line 114  class MapRenderer:
114          pen   = wxTRANSPARENT_PEN          pen   = wxTRANSPARENT_PEN
115    
116          old_prop = None          old_prop = None
117            old_group = None
118          lc = layer.GetClassification()          lc = layer.GetClassification()
119          field = lc.GetField()          field = lc.GetField()
120            defaultGroup = lc.GetDefaultGroup()
121    
         defaultProps = lc.GetDefaultGroup().GetProperties()  
122    
123            if shapetype != SHAPETYPE_POINT:
124                polygon_render_param = self.polygon_render_param(layer)
125    
126            if shapetype == SHAPETYPE_POINT:
127                draw_func = lambda i: \
128                       self.draw_point_shape(layer, i)
129            else:
130                draw_func = lambda i: \
131                       self.draw_polygon_shape(polygon_render_param, i, pen, brush)
132    
133            table = layer.ShapeStore().Table()
134          for i in self.layer_ids(layer):          for i in self.layer_ids(layer):
             value = None  
135    
136              if field is not None:              if field is None:
137                  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)  
138              else:              else:
139                  prop = defaultProps                  record = table.ReadRowAsDict(i)
140                    assert record is not None
141                    group = lc.FindGroup(record[field])
142    
143    
144                if not group.IsVisible():
145                    continue
146    
147    
148              # don't recreate new objects if they are the same as before              # don't recreate new objects if they are the same as before
149              if prop != old_prop:              if group is not old_group:
150                  old_prop = prop                  old_group = group
151    
152                  if shapetype == SHAPETYPE_ARC:                  prop = group.GetProperties()
153                      fill = Color.None  
154                  else:                  if prop != old_prop:
155                      fill = prop.GetFill()                      old_prop = prop
156        
157                  if fill is Color.None:                      if shapetype == SHAPETYPE_ARC:
158                      brush = wxTRANSPARENT_BRUSH                          fill = Color.Transparent
159                  else:                      else:
160                      color = Color2wxColour(fill)                          fill = prop.GetFill()
161                      brush = wxBrush(color, wxSOLID)  
162        
163                  stroke = prop.GetLineColor()                      if fill is Color.Transparent:
164                  stroke_width = prop.GetLineWidth()                          brush = wxTRANSPARENT_BRUSH
165                  if stroke is Color.None:                      else:
166                      pen = wxTRANSPARENT_PEN                          color = Color2wxColour(fill)
167                  else:                          brush = wxBrush(color, wxSOLID)
168                      color = Color2wxColour(stroke)  
169                      pen = wxPen(color, stroke_width, wxSOLID)                      stroke = prop.GetLineColor()
170                            stroke_width = prop.GetLineWidth()
171              if shapetype == SHAPETYPE_POINT:                      if stroke is Color.Transparent:
172                  self.dc.SetBrush(brush)                          pen = wxTRANSPARENT_PEN
173                  self.dc.SetPen(pen)                      else:
174                  self.draw_point_shape(layer, i)                          color = Color2wxColour(stroke)
175              else:                          pen = wxPen(color, stroke_width, wxSOLID)
176                  self.draw_polygon_shape(layer, i, pen, brush)  
177                        if shapetype == SHAPETYPE_POINT:
178                            self.dc.SetBrush(brush)
179                            self.dc.SetPen(pen)
180    
181                draw_func(i)
182    
183        def draw_raster_layer(self, layer):
184            data = None
185            offx, offy = self.offset
186            width, height = self.dc.GetSizeTuple()
187    
188            inProj = ""
189            proj = layer.GetProjection()
190            if proj is not None:
191                for p in proj.GetAllParameters():
192                    inProj += "+" + p + " "
193    
194            outProj = ""
195            proj = self.map.GetProjection()
196            if proj is not None:
197                for p in proj.GetAllParameters():
198                    outProj += "+" + p + " "
199    
200            xmin = (0 - offx) / self.scale
201            ymin = (offy - height) / self.scale
202            xmax = (width - offx) / self.scale
203            ymax = (offy - 0) / self.scale
204    
205            try:
206                data = ProjectRasterFile(
207                    layer.GetImageFilename(),
208                    inProj,
209                    outProj,
210                    (xmin, ymin, xmax, ymax),
211                    "", (width, height))
212            except IOError, (strerr):
213                print strerr
214            except (AttributeError, ValueError):
215                pass
216            else:
217                if data is not None:
218                    stream = cStringIO.StringIO(data)
219                    image = wxImageFromStream(stream, wxBITMAP_TYPE_BMP)
220                    bitmap = wxBitmapFromImage(image)
221                    self.dc.BeginDrawing()
222                    self.dc.DrawBitmap(bitmap, 0, 0)
223                    self.dc.EndDrawing()
224    
225      def layer_ids(self, layer):      def layer_ids(self, layer):
226          """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.
227            
228          The default implementation simply returns all ids in the layer.          The default implementation simply returns all ids in the layer.
229          Override in derived classes to be more precise.          Override in derived classes to be more precise.
230          """          """
231          return range(layer.NumShapes())          return range(layer.NumShapes())
232    
233      def draw_polygon_shape(self, layer, index, pen, brush):      def polygon_render_param(self, layer):
234          offx, offy = self.offset                  """Return the low-lever render parameter for the layer"""
235          draw_polygon_shape(layer.shapefile.cobject(), index,          offx, offy = self.offset
236                             self.dc, pen, brush,          return draw_polygon_init(layer.ShapeStore().Shapefile(), self.dc,
237                             self.map.projection, layer.projection,                                   self.map.projection,
238                             self.scale, -self.scale, offx, offy)                                   layer.projection,
239                                     self.scale, -self.scale,
240                                     offx, offy)
241    
242        def draw_polygon_shape(self, draw_polygon_info, index, pen, brush):
243            draw_polygon_shape(draw_polygon_info, index, pen, brush)
244    
245      def projected_points(self, layer, index):      def projected_points(self, layer, index):
246          proj = self.map.projection          proj = self.map.GetProjection()
247          if proj is not None:          if proj is not None:
248              forward = proj.Forward              forward = proj.Forward
249          else:          else:
250              forward = None              forward = None
251          proj = layer.projection          proj = layer.GetProjection()
252          if proj is not None:          if proj is not None:
253              inverse = proj.Inverse              inverse = proj.Inverse
254          else:          else:
# Line 254  class ScreenRenderer(MapRenderer): Line 344  class ScreenRenderer(MapRenderer):
344    
345              shapetype = layer.ShapeType()              shapetype = layer.ShapeType()
346              if shapetype == SHAPETYPE_POLYGON:              if shapetype == SHAPETYPE_POLYGON:
347                    offx, offy = self.offset
348                    renderparam = self.polygon_render_param(layer)
349                  func = self.draw_polygon_shape                  func = self.draw_polygon_shape
350                  args = (pen, brush)                  args = (pen, brush)
351              elif shapetype == SHAPETYPE_ARC:              elif shapetype == SHAPETYPE_ARC:
352                    renderparam = self.polygon_render_param(layer)
353                  func = self.draw_polygon_shape                  func = self.draw_polygon_shape
354                  args = (pen, None)                  args = (pen, None)
355              elif shapetype == SHAPETYPE_POINT:              elif shapetype == SHAPETYPE_POINT:
356                    renderparam = layer
357                  self.dc.SetBrush(brush)                  self.dc.SetBrush(brush)
358                  self.dc.SetPen(pen)                  self.dc.SetPen(pen)
359                  func = self.draw_point_shape                  func = self.draw_point_shape
# Line 268  class ScreenRenderer(MapRenderer): Line 362  class ScreenRenderer(MapRenderer):
362                  raise TypeError(_("Unhandled shape type %s") % shapetype)                  raise TypeError(_("Unhandled shape type %s") % shapetype)
363    
364              for index in self.selected_shapes:              for index in self.selected_shapes:
365                  func(layer, index, *args)                  func(renderparam, index, *args)
366    
367    
368      def layer_ids(self, layer):      def layer_ids(self, layer):
369          """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 403  class ScreenRenderer(MapRenderer):
403          return layer.ShapesInRegion((left, bottom, right, top))          return layer.ShapesInRegion((left, bottom, right, top))
404    
405    
406  class PrinterRender(MapRenderer):  class ExportRenderer(ScreenRenderer):
407    
408      # When printing we want to see all layers      honor_visibility = 1
     honor_visibility = 0  
   
     RenderMap = MapRenderer.render_map  
409            
410        def RenderMap(self, map, region, mapregion,
411                      selected_layer, selected_shapes ):
412            """Render the map.
413    
414            The rendering device has been specified during initialisation.
415            The device border distance was set in Thuban.UI.view.OutputTranform().
416            
417            RenderMap renders a frame set (one page frame, one around
418            legend/scalebar and one around the map), the map, the legend and the
419            scalebar on the given DC. The map is rendered with the region displayed
420            in the canvas view, centered on the area available for map display.
421            """
422            
423            self.update_region = region
424            self.selected_layer = selected_layer
425            self.selected_shapes = selected_shapes
426    
427            # Get some dimensions
428            llx, lly, urx, ury = region
429            self.mapregion = mapregion
430            mminx, mminy, mmaxx, mmaxy = self.mapregion
431    
432            # Manipulate the offset to position the map
433            offx, offy = self.offset
434            # 1. Shift to corner of map drawing area
435            offx = offx + mminx
436            offy = offy + mminy
437    
438            # 2. Center the map on the map drawing area:
439            # region identifies the region on the canvas view:
440            # center of map drawing area - half the size of region: rendering origin
441            self.shiftx = (mmaxx - mminx)*0.5 - (urx - llx)*0.5
442            self.shifty = (mmaxy - mminy)*0.5 - (ury - lly)*0.5
443    
444            self.offset = (offx+self.shiftx, offy+self.shifty)
445    
446            # Draw the map
447            self.dc.BeginDrawing()
448            self.dc.DestroyClippingRegion()
449            self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty,
450                                      urx, ury)
451            self.render_map(map)
452            self.dc.EndDrawing()
453    
454            # Draw the rest (frames, legend, scalebar)
455            self.dc.BeginDrawing()
456            self.dc.DestroyClippingRegion()
457    
458            # Force the font for Legend drawing
459            font = wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL)
460            self.dc.SetFont(font)
461    
462            self.render_frame(region)
463            self.render_legend(map)
464            self.render_scalebar(map)
465            self.dc.EndDrawing()
466    
467        def render_frame(self, region):
468            """Render the frames for map and legend/scalebar."""
469    
470            dc = self.dc
471            dc.SetPen(wxBLACK_PEN)
472            dc.SetBrush(wxTRANSPARENT_BRUSH)
473    
474            # Dimension stuff
475            width, height = dc.GetSizeTuple()
476            mminx, mminy, mmaxx, mmaxy = self.mapregion
477    
478            # Page Frame
479            dc.DrawRectangle(15,15,width-30, (mmaxy-mminy)+10)
480            
481            # Map Frame
482            llx, lly, urx, ury = region
483            dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury)
484            
485            # Legend Frame
486            dc.DrawRectangle(mmaxx+10,mminy,(width-20) - (mmaxx+10), mmaxy-mminy)
487    
488            dc.DestroyClippingRegion()
489            dc.SetClippingRegion(mmaxx+10,mminy,
490                                 (width-20) - (mmaxx+10), mmaxy-mminy)
491    
492        def render_legend(self, map):
493            """Render the legend on the Map."""
494    
495            previewer = ClassDataPreviewer()
496            dc = self.dc
497            dc.SetPen(wxBLACK_PEN)
498            dc.SetBrush(wxTRANSPARENT_BRUSH)
499    
500            # Dimension stuff
501            width, height = dc.GetSizeTuple()
502            mminx, mminy, mmaxx, mmaxy = self.mapregion
503            textwidth, textheight = dc.GetTextExtent("0")
504            iconwidth  = textheight
505            iconheight = textheight
506            stepy = textheight+3
507            dx = 10
508            posx = mmaxx + 10 + 5   # 10 pix distance mapframe/legend frame,
509                                    # 5 pix inside legend frame
510            posy = mminy + 5        # 5 pix inside legend frame
511            
512            # Render the legend
513            dc.SetTextForeground(wxBLACK)
514            if map.HasLayers():
515                for l in map.Layers():
516                    if l.Visible():
517                        # Render title
518                        dc.DrawText(l.Title(), posx, posy)
519                        posy+=stepy
520                        # Render classification
521                        clazz = l.GetClassification()
522                        shapeType = l.ShapeType()
523                        for g in clazz:
524                            if g.IsVisible():
525                                previewer.Draw(dc,
526                                    wxRect(posx+dx, posy, iconwidth, iconheight),
527                                    g.GetProperties(), shapeType)
528                                dc.DrawText(g.GetDisplayText(),
529                                            posx+2*dx+iconwidth, posy)
530                                posy+=stepy
531            
532        def render_scalebar(self, map):
533            """Render the scalebar."""
534    
535            scalebar = ScaleBar(map)
536    
537            # Dimension stuff
538            width, height = self.dc.GetSizeTuple()
539            mminx, mminy, mmaxx, mmaxy = self.mapregion
540          
541            # Render the scalebar
542            scalebar.DrawScaleBar(self.scale, self.dc,
543                                 (mmaxx+10+5, mmaxy-25),
544                                 ((width-15-5) - (mmaxx+10+5),20)
545                                )
546            # 10 pix between map and legend frame, 5 pix inside legend frame
547            # 25 pix from the legend frame bottom line
548            # Width: 15 pix from DC border, 5 pix inside frame, 10, 5 as above
549            # Height: 20
550    
551    class PrinterRenderer(ExportRenderer):
552    
553        # Printing as well as Export / Screen display only the visible layer.
554        honor_visibility = 1
555    

Legend:
Removed from v.588  
changed lines
  Added in v.1219

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26