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

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

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

revision 1591 by bh, Fri Aug 15 14:00:53 2003 UTC revision 1914 by bh, Mon Nov 3 14:17:51 2003 UTC
# Line 14  be tested reasonably easily and it could Line 14  be tested reasonably easily and it could
14  renderers.  renderers.
15  """  """
16    
17    from __future__ import generators
18    
19  __version__ = "$Revision$"  __version__ = "$Revision$"
20  # $Source$  # $Source$
21  # $Id$  # $Id$
# Line 49  class BaseRenderer: Line 51  class BaseRenderer:
51      TRANSPARENT_PEN = None      TRANSPARENT_PEN = None
52      TRANSPARENT_BRUSH = None      TRANSPARENT_BRUSH = None
53    
54      def __init__(self, dc, scale, offset, resolution = 72.0,      def __init__(self, dc, map, scale, offset, region = None,
55                   honor_visibility = None):                   resolution = 72.0, honor_visibility = None):
56          """Inititalize the renderer.          """Inititalize the renderer.
57    
58          dc -- the device context to render on.          dc -- the device context to render on.
# Line 58  class BaseRenderer: Line 60  class BaseRenderer:
60          scale, offset -- the scale factor and translation to convert          scale, offset -- the scale factor and translation to convert
61                  between projected coordinates and the DC coordinates                  between projected coordinates and the DC coordinates
62    
63            region -- The region to draw as a (x, y, width, height) tuple in
64                      the map's coordinate system. Default is None meaning
65                      to draw everything.
66    
67          resolution -- the assumed resolution of the DC. Used to convert          resolution -- the assumed resolution of the DC. Used to convert
68                  absolute lengths like font sizes to DC coordinates. The                  absolute lengths like font sizes to DC coordinates. The
69                  defauult is 72.0                  default is 72.0. If given, this parameter must be
70                    provided as a keyword argument.
71    
72          honor_visibility -- boolean. If true, honor the visibility flag          honor_visibility -- boolean. If true, honor the visibility flag
73                  of the layers, otherwise draw all layers. If None (the                  of the layers, otherwise draw all layers. If None (the
74                  default), use the renderer's default.                  default), use the renderer's default. If given, this
75                    parameter must be provided as a keyword argument.
76          """          """
77          # resolution in pixel/inch          # resolution in pixel/inch
   
78          self.dc = dc          self.dc = dc
79            self.map = map
80          self.scale = scale          self.scale = scale
81          self.offset = offset          self.offset = offset
82            self.region = region
83          if honor_visibility is not None:          if honor_visibility is not None:
84              self.honor_visibility = honor_visibility              self.honor_visibility = honor_visibility
85          # store the resolution in pixel/point because it's more useful          # store the resolution in pixel/point because it's more useful
# Line 85  class BaseRenderer: Line 94  class BaseRenderer:
94          """          """
95          raise NotImplementedError          raise NotImplementedError
96    
97      def render_map(self, map):      def render_map(self):
98          """Render the map onto the DC the renderer was instantiated with          """Render the map onto the DC.
99    
100            Both map and DC are the ones the renderer was instantiated with.
101    
102            This method is just a front-end for render_map_incrementally
103            which does all rendering in one go. It also calls the dc's
104            BeginDrawing and EndDrawing methods before and after calling
105            render_map_incrementally.
106            """
107    
108            self.dc.BeginDrawing()
109            try:
110                for cont in self.render_map_incrementally():
111                    pass
112            finally:
113                self.dc.EndDrawing()
114    
115        def render_map_incrementally(self):
116            """Render the map incrementally.
117    
118            Return an iterator whose next method should be called until it
119            returns False. After returning False it will raise StopIteration
120            so that you could also use it in a for loop (implementation
121            detail: this method is implemented as a generator).
122    
123          Iterate through all layers and draw them. Layers containing          Iterate through all layers and draw them. Layers containing
124          vector data are drawn with the draw_shape_layer method, raster          vector data are drawn with the draw_shape_layer method, raster
# Line 97  class BaseRenderer: Line 129  class BaseRenderer:
129          that methods especially in derived classes have access to the          that methods especially in derived classes have access to the
130          map if necessary.          map if necessary.
131          """          """
         # Some method have to have access to the map so we store it in  
         # self.map.  
         self.map = map  
   
132          # Whether the raster layer has already been drawn. See below for          # Whether the raster layer has already been drawn. See below for
133          # the optimization this is used for          # the optimization this is used for
134          seenRaster = True          seenRaster = True
135    
136          self.dc.BeginDrawing()          #
137            # This is only a good optimization if there is only one
138          try:          # raster layer and the image covers the entire window (as
139              #          # it currently does). We note if there is a raster layer
140              # This is only a good optimization if there is only one          # and only begin drawing layers once we have drawn it.
141              # raster layer and the image covers the entire window (as          # That way we avoid drawing layers that won't be seen.
142              # it currently does). We note if there is a raster layer          #
143              # and only begin drawing layers once we have drawn it.          if Thuban.Model.resource.has_gdal_support():
144              # That way we avoid drawing layers that won't be seen.              for layer in self.map.Layers():
145              #                  if isinstance(layer, RasterLayer) and layer.Visible():
146              if Thuban.Model.resource.has_gdal_support():                      seenRaster = False
147                  for layer in map.Layers():                      break
148                      if isinstance(layer, RasterLayer) and layer.Visible():  
149                          seenRaster = False          for layer in self.map.Layers():
150                          break              # if honor_visibility is true, only draw visible layers,
151                # otherwise draw all layers
152              for layer in map.Layers():              if not self.honor_visibility or layer.Visible():
153                  # if honor_visibility is true, only draw visible layers,                  if isinstance(layer, Layer) and seenRaster:
154                  # otherwise draw all layers                      for i in self.draw_shape_layer_incrementally(layer):
155                  if not self.honor_visibility or layer.Visible():                          yield True
156                      if isinstance(layer, Layer) and seenRaster:                  elif isinstance(layer, RasterLayer) \
157                          self.draw_shape_layer(layer)                      and Thuban.Model.resource.has_gdal_support():
158                      elif isinstance(layer, RasterLayer) \                      self.draw_raster_layer(layer)
159                          and Thuban.Model.resource.has_gdal_support():                      seenRaster = True
160                          self.draw_raster_layer(layer)                      yield True
                         seenRaster = True  
161    
162              self.draw_label_layer(map.LabelLayer())          self.draw_label_layer(self.map.LabelLayer())
163          finally:          yield False
             self.dc.EndDrawing()  
164    
165      def draw_shape_layer(self, layer):      def draw_shape_layer_incrementally(self, layer):
166          """Draw the shape layer layer onto the map.          """Draw the shape layer layer onto the map incrementally.
167    
168          Automatically called by render_map. Iterate through all shapes          This method is a generator which yields True after every 500
169          as indicated by self.layer_ids() and draw them, using low-level          shapes.
         renderers returned by self.low_level_renderer().  
170          """          """
171          scale = self.scale          scale = self.scale
172          offx, offy = self.offset          offx, offy = self.offset
# Line 159  class BaseRenderer: Line 184  class BaseRenderer:
184          defaultGroup = lc.GetDefaultGroup()          defaultGroup = lc.GetDefaultGroup()
185          table = layer.ShapeStore().Table()          table = layer.ShapeStore().Table()
186    
187            if lc.GetNumGroups() == 0:
188                # There's only the default group, so we can pretend that
189                # there is no field to classifiy on which makes things
190                # faster since we don't need the attribute information at
191                # all.
192                field = None
193    
194          # Determine which render function to use.          # Determine which render function to use.
195          useraw, draw_func, draw_func_param = self.low_level_renderer(layer)          useraw, draw_func, draw_func_param = self.low_level_renderer(layer)
196    
197            #
198          # Iterate through all shapes that have to be drawn.          # Iterate through all shapes that have to be drawn.
199          for i in self.layer_ids(layer):          #
             shape = layer.Shape(i)  
200    
201            # Count the shapes drawn so that we can yield every few hundred
202            # shapes
203            count = 0
204    
205            # Cache the tools (pens and brushes) for the classification
206            # groups. This is a mapping from the group's ids to the a tuple
207            # (pen, brush)
208            tool_cache = {}
209    
210            for shape in self.layer_shapes(layer):
211                count += 1
212              if field is None:              if field is None:
213                  group = defaultGroup                  group = defaultGroup
214              else:              else:
215                  record = table.ReadRowAsDict(i)                  value = table.ReadRowAsDict(shape.ShapeID())[field]
216                  assert record is not None                  group = lc.FindGroup(value)
                 group = lc.FindGroup(record[field])  
217    
218              if not group.IsVisible():              if not group.IsVisible():
219                  continue                  continue
220    
221              # don't recreate new objects if they are the same as before              try:
222              if group is not old_group:                  pen, brush = tool_cache[id(group)]
223                  old_group = group              except KeyError:
224                    pen, brush = tool_cache[id(group)] \
225                  prop = group.GetProperties()                               = self.tools_for_property(group.GetProperties())
   
                 if prop != old_prop:  
                     pen, brush = self.tools_for_property(prop)  
226    
227              if useraw:              if useraw:
228                  data = shape.RawData()                  data = shape.RawData()
229              else:              else:
230                  data = shape.Points()                  data = shape.Points()
231              draw_func(draw_func_param, data, pen, brush)              draw_func(draw_func_param, data, pen, brush)
232                if count % 500 == 0:
233                    yield True
234    
235      def layer_ids(self, layer):      def layer_shapes(self, layer):
236          """Return the shape ids of the given layer that have to be drawn.          """Return an iterable over the shapes to be drawn from the given layer.
237    
238          The default implementation simply returns all ids in the layer.          The default implementation simply returns all ids in the layer.
239          Override in derived classes to be more precise.          Override in derived classes to be more precise.
240          """          """
241          return range(layer.NumShapes())          return layer.ShapeStore().AllShapes()
242    
243      def low_level_renderer(self, layer):      def low_level_renderer(self, layer):
244          """Return the low-level renderer for the layer for draw_shape_layer          """Return the low-level renderer for the layer for draw_shape_layer

Legend:
Removed from v.1591  
changed lines
  Added in v.1914

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26