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

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

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

revision 967 by jonathan, Wed May 21 17:24:54 2003 UTC revision 1285 by jonathan, Mon Jun 23 10:30:53 2003 UTC
# Line 19  import os.path Line 19  import os.path
19    
20  from math import hypot  from math import hypot
21    
22  from wxPython.wx import wxWindow,\  from wxPython.wx import wxWindow, \
23       wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\       wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\
24       EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW, \       EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW, \
25       wxBITMAP_TYPE_XPM, wxBeginBusyCursor, wxEndBusyCursor, wxCursor, \       wxBITMAP_TYPE_XPM, wxCursor, wxImageFromBitmap, wxPlatform, \
26       wxImageFromBitmap, wxPlatform       wxBeginBusyCursor, wxEndBusyCursor
27    
28    
29  # Export related stuff  # Export related stuff
30  if wxPlatform == '__WXMSW__':  if wxPlatform == '__WXMSW__':
# Line 35  from wxPython import wx Line 36  from wxPython import wx
36  from wxproj import point_in_polygon_shape, shape_centroid  from wxproj import point_in_polygon_shape, shape_centroid
37    
38  from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \  from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \
39         LAYER_PROJECTION_CHANGED, \
40       MAP_LAYERS_CHANGED, LAYER_CHANGED, LAYER_VISIBILITY_CHANGED       MAP_LAYERS_CHANGED, LAYER_CHANGED, LAYER_VISIBILITY_CHANGED
41  from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \  from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
42       SHAPETYPE_POINT       SHAPETYPE_POINT
# Line 271  class MapPrintout(wx.wxPrintout): Line 273  class MapPrintout(wx.wxPrintout):
273                                  (height/canvas_scale)*scale),                                  (height/canvas_scale)*scale),
274                                  mapregion,                                  mapregion,
275                             self.selected_layer, self.selected_shapes)                             self.selected_layer, self.selected_shapes)
276          return wx.true          return True
   
277    
278  class MapCanvas(wxWindow, Publisher):  class MapCanvas(wxWindow, Publisher):
279    
# Line 302  class MapCanvas(wxWindow, Publisher): Line 303  class MapCanvas(wxWindow, Publisher):
303          # the map displayed in this canvas. Set with SetMap()          # the map displayed in this canvas. Set with SetMap()
304          self.map = None          self.map = None
305    
306            # current map projection. should only differ from map.projection
307            # when the map's projection is changing and we need access to the
308            # old projection.
309            self.current_map_proj = None
310    
311          # scale and offset describe the transformation from projected          # scale and offset describe the transformation from projected
312          # coordinates to window coordinates.          # coordinates to window coordinates.
313          self.scale = 1.0          self.scale = 1.0
# Line 375  class MapCanvas(wxWindow, Publisher): Line 381  class MapCanvas(wxWindow, Publisher):
381    
382      def OnPaint(self, event):      def OnPaint(self, event):
383          dc = wxPaintDC(self)          dc = wxPaintDC(self)
384    
385          clear = self.map is None or not self.map.HasLayers()          clear = self.map is None or not self.map.HasLayers()
386    
387          wxBeginBusyCursor()          wxBeginBusyCursor()
388            try:
389                if not clear:
390                    self.do_redraw()
391                else:
392                    # If we've got no map or if the map is empty, simply clear
393                    # the screen.
394    
395          if not clear:                  # XXX it's probably possible to get rid of this. The
396              self.do_redraw()                  # background color of the window is already white and the
397              try:                  # only thing we may have to do is to call self.Refresh()
398                  pass                  # with a true argument in the right places.
399              except:                  dc.BeginDrawing()
400                  print "Error during drawing:", sys.exc_info()[0]                  dc.Clear()
401                  clear = True                  dc.EndDrawing()
402            finally:
403          if clear:              wxEndBusyCursor()
             # If we've got no map or if the map is empty, simply clear  
             # the screen.  
   
             # XXX it's probably possible to get rid of this. The  
             # background color of the window is already white and the  
             # only thing we may have to do is to call self.Refresh()  
             # with a true argument in the right places.  
             dc.BeginDrawing()  
             dc.Clear()  
             dc.EndDrawing()  
   
         wxEndBusyCursor()  
404    
405      def do_redraw(self):      def do_redraw(self):
406          # This should only be called if we have a non-empty map.          # This should only be called if we have a non-empty map.
# Line 492  class MapCanvas(wxWindow, Publisher): Line 493  class MapCanvas(wxWindow, Publisher):
493                    
494          printout = MapPrintout(self, self.map, (0, 0, width, height),          printout = MapPrintout(self, self.map, (0, 0, width, height),
495                                 selected_layer, selected_shapes)                                 selected_layer, selected_shapes)
496          printer.Print(self, printout, wx.true)          printer.Print(self, printout, True)
497          printout.Destroy()          printout.Destroy()
498    
499      def SetMap(self, map):      def SetMap(self, map):
# Line 502  class MapCanvas(wxWindow, Publisher): Line 503  class MapCanvas(wxWindow, Publisher):
503              for channel in redraw_channels:              for channel in redraw_channels:
504                  self.map.Unsubscribe(channel, self.full_redraw)                  self.map.Unsubscribe(channel, self.full_redraw)
505              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,
506                                   self.projection_changed)                                   self.map_projection_changed)
507                self.map.Unsubscribe(LAYER_PROJECTION_CHANGED,
508                                     self.layer_projection_changed)
509          self.map = map          self.map = map
510            self.current_map_proj = self.map.GetProjection()
511          self.selection.ClearSelection()          self.selection.ClearSelection()
512          if self.map is not None:          if self.map is not None:
513              for channel in redraw_channels:              for channel in redraw_channels:
514                  self.map.Subscribe(channel, self.full_redraw)                  self.map.Subscribe(channel, self.full_redraw)
515              self.map.Subscribe(MAP_PROJECTION_CHANGED, self.projection_changed)              self.map.Subscribe(MAP_PROJECTION_CHANGED, self.map_projection_changed)
516                self.map.Subscribe(LAYER_PROJECTION_CHANGED, self.layer_projection_changed)
517          self.FitMapToWindow()          self.FitMapToWindow()
518          # force a redraw. If map is not empty, it's already been called          # force a redraw. If map is not empty, it's already been called
519          # by FitMapToWindow but if map is empty it hasn't been called          # by FitMapToWindow but if map is empty it hasn't been called
# Line 526  class MapCanvas(wxWindow, Publisher): Line 531  class MapCanvas(wxWindow, Publisher):
531          self.bitmap = None          self.bitmap = None
532          self.redraw()          self.redraw()
533    
534      def projection_changed(self, *args):      def map_projection_changed(self, *args):
535          self.FitMapToWindow()  
536            proj = self.current_map_proj
537            self.current_map_proj = self.map.GetProjection()
538    
539            bbox = None
540    
541            if proj is not None and self.current_map_proj is not None:
542                width, height = self.GetSizeTuple()
543                llx, lly = self.win_to_proj(0, height)
544                urx, ury = self.win_to_proj(width, 0)
545                bbox = proj.Inverse(llx, lly) + proj.Inverse(urx, ury)
546                bbox = self.current_map_proj.ForwardBBox(bbox)
547    
548            if bbox is not None:
549                self.FitRectToWindow(bbox)
550            else:
551                self.FitMapToWindow()
552    
553            self.full_redraw()
554    
555        def layer_projection_changed(self, *args):
556          self.full_redraw()          self.full_redraw()
557    
558      def set_view_transform(self, scale, offset):      def set_view_transform(self, scale, offset):
559            # width/height of the projected bbox
560            llx, lly, urx, ury = bbox = self.map.ProjectedBoundingBox()
561            pwidth = float(urx - llx)
562            pheight = float(ury - lly)
563    
564            # width/height of the window
565            wwidth, wheight = self.GetSizeTuple()
566    
567            # The window's center in projected coordinates assuming the new
568            # scale/offset
569            pcenterx = (wwidth/2 - offset[0]) / scale
570            pcentery = (offset[1] - wheight/2) / scale
571    
572            # The window coordinates used when drawing the shapes must fit
573            # into 16bit signed integers.
574            max_len = max(pwidth, pheight)
575            if max_len:
576                max_scale = 32000.0 / max_len
577            else:
578                # FIXME: What to do in this case? The bbox is effectively
579                # empty so any scale should work.
580                max_scale = scale
581    
582            # The minimal scale is somewhat arbitrarily set to half that of
583            # the bbox fit into the window
584            scales = []
585            if pwidth:
586                scales.append(wwidth / pwidth)
587            if pheight:
588                scales.append(wheight / pheight)
589            if scales:
590                min_scale = 0.5 * min(scales)
591            else:
592                min_scale = scale
593    
594            if scale > max_scale:
595                scale = max_scale
596            elif scale < min_scale:
597                scale = min_scale
598    
599          self.scale = scale          self.scale = scale
600    
601          self.offset = offset          # determine new offset to preserve the center
602            self.offset = (wwidth/2 - scale * pcenterx,
603                           wheight/2 + scale * pcentery)
604          self.full_redraw()          self.full_redraw()
605          self.issue(SCALE_CHANGED, scale)          self.issue(SCALE_CHANGED, scale)
606    
# Line 581  class MapCanvas(wxWindow, Publisher): Line 648  class MapCanvas(wxWindow, Publisher):
648          Set the scale so that the map fits exactly into the window and          Set the scale so that the map fits exactly into the window and
649          center it in the window.          center it in the window.
650          """          """
651          bbox = self.map.ProjectedBoundingBox()          if self.map is not None:
652          if bbox is not None:              bbox = self.map.ProjectedBoundingBox()
653              self.FitRectToWindow(bbox)              if bbox is not None:
654                    self.FitRectToWindow(bbox)
655    
656      def FitLayerToWindow(self, layer):      def FitLayerToWindow(self, layer):
657          """Fit the given layer to the window.          """Fit the given layer to the window.
# Line 612  class MapCanvas(wxWindow, Publisher): Line 680  class MapCanvas(wxWindow, Publisher):
680                  bbox = proj.ForwardBBox(bbox)                  bbox = proj.ForwardBBox(bbox)
681    
682              if bbox is not None:              if bbox is not None:
683                  self.FitRectToWindow(bbox)                  if len(shapes) == 1 and layer.ShapeType() == SHAPETYPE_POINT:
684                        self.ZoomFactor(1, self.proj_to_win(bbox[0], bbox[1]))
685                    else:
686                        self.FitRectToWindow(bbox)
687    
688      def ZoomFactor(self, factor, center = None):      def ZoomFactor(self, factor, center = None):
689          """Multiply the zoom by factor and center on center.          """Multiply the zoom by factor and center on center.
# Line 867  class MapCanvas(wxWindow, Publisher): Line 938  class MapCanvas(wxWindow, Publisher):
938              layer = layers[layer_index]              layer = layers[layer_index]
939    
940              # search only in visible layers              # search only in visible layers
941              if not layer.Visible():              if not layer.Visible() or not layer.HasShapes():
942                  continue                  continue
943    
944              filled = layer.GetClassification().GetDefaultFill() \              filled = layer.GetClassification().GetDefaultFill() \
# Line 900  class MapCanvas(wxWindow, Publisher): Line 971  class MapCanvas(wxWindow, Publisher):
971    
972              if shapetype == SHAPETYPE_POLYGON:              if shapetype == SHAPETYPE_POLYGON:
973                  for i in shape_ids:                  for i in shape_ids:
974                      result = point_in_polygon_shape(layer.shapefile.cobject(),                      shapefile = layer.ShapeStore().Shapefile().cobject()
975                                                      i,                      result = point_in_polygon_shape(shapefile, i,
976                                                      filled, stroked,                                                      filled, stroked,
977                                                      map_proj, layer_proj,                                                      map_proj, layer_proj,
978                                                      scale, -scale, offx, offy,                                                      scale, -scale, offx, offy,
# Line 911  class MapCanvas(wxWindow, Publisher): Line 982  class MapCanvas(wxWindow, Publisher):
982                          break                          break
983              elif shapetype == SHAPETYPE_ARC:              elif shapetype == SHAPETYPE_ARC:
984                  for i in shape_ids:                  for i in shape_ids:
985                      result = point_in_polygon_shape(layer.shapefile.cobject(),                      shapefile = layer.ShapeStore().Shapefile().cobject()
986                        result = point_in_polygon_shape(shapefile,
987                                                      i, 0, 1,                                                      i, 0, 1,
988                                                      map_proj, layer_proj,                                                      map_proj, layer_proj,
989                                                      scale, -scale, offx, offy,                                                      scale, -scale, offx, offy,
# Line 973  class MapCanvas(wxWindow, Publisher): Line 1045  class MapCanvas(wxWindow, Publisher):
1045              # a label was selected              # a label was selected
1046              label_layer.RemoveLabel(shape_index)              label_layer.RemoveLabel(shape_index)
1047          elif layer is not None:          elif layer is not None:
1048              text = labeldialog.run_label_dialog(self, layer.table, shape_index)              text = labeldialog.run_label_dialog(self,
1049                                                    layer.ShapeStore().Table(),
1050                                                    shape_index)
1051              if text:              if text:
1052                  proj = self.map.projection                  proj = self.map.projection
1053                  if proj is not None:                  if proj is not None:
# Line 988  class MapCanvas(wxWindow, Publisher): Line 1062  class MapCanvas(wxWindow, Publisher):
1062    
1063                  shapetype = layer.ShapeType()                  shapetype = layer.ShapeType()
1064                  if shapetype == SHAPETYPE_POLYGON:                  if shapetype == SHAPETYPE_POLYGON:
1065                      x, y = shape_centroid(layer.shapefile.cobject(),                      shapefile = layer.ShapeStore().Shapefile().cobject()
1066                                            shape_index,                      x, y = shape_centroid(shapefile, shape_index,
1067                                            map_proj, layer_proj, 1, 1, 0, 0)                                            map_proj, layer_proj, 1, 1, 0, 0)
1068                      if map_proj is not None:                      if map_proj is not None:
1069                          x, y = map_proj.Inverse(x, y)                          x, y = map_proj.Inverse(x, y)

Legend:
Removed from v.967  
changed lines
  Added in v.1285

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26