/[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 910 by frank, Fri May 16 16:23:43 2003 UTC revision 1271 by jonathan, Fri Jun 20 16:43:04 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, wxYield,\
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, wxBeginBusyCursor, wxEndBusyCursor, wxCursor, \
# Line 34  from wxPython import wx Line 34  from wxPython import wx
34    
35  from wxproj import point_in_polygon_shape, shape_centroid  from wxproj import point_in_polygon_shape, shape_centroid
36    
   
37  from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \  from Thuban.Model.messages import MAP_PROJECTION_CHANGED, \
38         LAYER_PROJECTION_CHANGED, \
39       MAP_LAYERS_CHANGED, LAYER_CHANGED, LAYER_VISIBILITY_CHANGED       MAP_LAYERS_CHANGED, LAYER_CHANGED, LAYER_VISIBILITY_CHANGED
40  from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \  from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
41       SHAPETYPE_POINT       SHAPETYPE_POINT
# Line 272  class MapPrintout(wx.wxPrintout): Line 272  class MapPrintout(wx.wxPrintout):
272                                  (height/canvas_scale)*scale),                                  (height/canvas_scale)*scale),
273                                  mapregion,                                  mapregion,
274                             self.selected_layer, self.selected_shapes)                             self.selected_layer, self.selected_shapes)
275          return wx.true          return True
   
276    
277  class MapCanvas(wxWindow, Publisher):  class MapCanvas(wxWindow, Publisher):
278    
# Line 303  class MapCanvas(wxWindow, Publisher): Line 302  class MapCanvas(wxWindow, Publisher):
302          # the map displayed in this canvas. Set with SetMap()          # the map displayed in this canvas. Set with SetMap()
303          self.map = None          self.map = None
304    
305            # current map projection. should only differ from map.projection
306            # when the map's projection is changing and we need access to the
307            # old projection.
308            self.current_map_proj = None
309    
310          # scale and offset describe the transformation from projected          # scale and offset describe the transformation from projected
311          # coordinates to window coordinates.          # coordinates to window coordinates.
312          self.scale = 1.0          self.scale = 1.0
# Line 378  class MapCanvas(wxWindow, Publisher): Line 382  class MapCanvas(wxWindow, Publisher):
382          dc = wxPaintDC(self)          dc = wxPaintDC(self)
383          clear = self.map is None or not self.map.HasLayers()          clear = self.map is None or not self.map.HasLayers()
384    
385          #wxBeginBusyCursor()          wxBeginBusyCursor()
386            wxYield()
387    
388          if not clear:          try:
389              try:              if not clear:
390                  self.do_redraw()                  self.do_redraw()
391              except:                  try:
392                  print "Error during drawing:", sys.exc_info()[0]                      pass
393                  clear = True                  except:
394                        print "Error during drawing:", sys.exc_info()[0]
395          if clear:                      clear = True
396              # If we've got no map or if the map is empty, simply clear  
397              # the screen.              if clear:
398                    # If we've got no map or if the map is empty, simply clear
399              # XXX it's probably possible to get rid of this. The                  # the screen.
400              # background color of the window is already white and the  
401              # only thing we may have to do is to call self.Refresh()                  # XXX it's probably possible to get rid of this. The
402              # with a true argument in the right places.                  # background color of the window is already white and the
403              dc.BeginDrawing()                  # only thing we may have to do is to call self.Refresh()
404              dc.Clear()                  # with a true argument in the right places.
405              dc.EndDrawing()                  dc.BeginDrawing()
406                    dc.Clear()
407          #wxEndBusyCursor()                  dc.EndDrawing()
408            finally:
409                wxEndBusyCursor()
410    
411      def do_redraw(self):      def do_redraw(self):
412          # 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 447  class MapCanvas(wxWindow, Publisher): Line 454  class MapCanvas(wxWindow, Publisher):
454          clientdc.EndDrawing()          clientdc.EndDrawing()
455    
456      def Export(self):      def Export(self):
457            if self.scale == 0:
458                return
459    
460          if hasattr(self, "export_path"):          if hasattr(self, "export_path"):
461              export_path = self.export_path              export_path = self.export_path
462          else:          else:
# Line 459  class MapCanvas(wxWindow, Publisher): Line 469  class MapCanvas(wxWindow, Publisher):
469              dc = wxMetaFileDC(dlg.GetPath())              dc = wxMetaFileDC(dlg.GetPath())
470            
471              scale, offset, mapregion = OutputTransform(self.scale,              scale, offset, mapregion = OutputTransform(self.scale,
472                                                         self.canvas.offset,                                                         self.offset,
473                                                         self.GetSizeTuple(),                                                         self.GetSizeTuple(),
474                                                         dc.GetSizeTuple())                                                         dc.GetSizeTuple())
475    
# Line 489  class MapCanvas(wxWindow, Publisher): Line 499  class MapCanvas(wxWindow, Publisher):
499                    
500          printout = MapPrintout(self, self.map, (0, 0, width, height),          printout = MapPrintout(self, self.map, (0, 0, width, height),
501                                 selected_layer, selected_shapes)                                 selected_layer, selected_shapes)
502          printer.Print(self, printout, wx.true)          printer.Print(self, printout, True)
503          printout.Destroy()          printout.Destroy()
504    
505      def SetMap(self, map):      def SetMap(self, map):
# Line 499  class MapCanvas(wxWindow, Publisher): Line 509  class MapCanvas(wxWindow, Publisher):
509              for channel in redraw_channels:              for channel in redraw_channels:
510                  self.map.Unsubscribe(channel, self.full_redraw)                  self.map.Unsubscribe(channel, self.full_redraw)
511              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,              self.map.Unsubscribe(MAP_PROJECTION_CHANGED,
512                                   self.projection_changed)                                   self.map_projection_changed)
513                self.map.Unsubscribe(LAYER_PROJECTION_CHANGED,
514                                     self.layer_projection_changed)
515          self.map = map          self.map = map
516            self.current_map_proj = self.map.GetProjection()
517          self.selection.ClearSelection()          self.selection.ClearSelection()
518          if self.map is not None:          if self.map is not None:
519              for channel in redraw_channels:              for channel in redraw_channels:
520                  self.map.Subscribe(channel, self.full_redraw)                  self.map.Subscribe(channel, self.full_redraw)
521              self.map.Subscribe(MAP_PROJECTION_CHANGED, self.projection_changed)              self.map.Subscribe(MAP_PROJECTION_CHANGED, self.map_projection_changed)
522                self.map.Subscribe(LAYER_PROJECTION_CHANGED, self.layer_projection_changed)
523          self.FitMapToWindow()          self.FitMapToWindow()
524          # 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
525          # 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 523  class MapCanvas(wxWindow, Publisher): Line 537  class MapCanvas(wxWindow, Publisher):
537          self.bitmap = None          self.bitmap = None
538          self.redraw()          self.redraw()
539    
540      def projection_changed(self, *args):      def map_projection_changed(self, *args):
541          self.FitMapToWindow()  
542            proj = self.current_map_proj
543            self.current_map_proj = self.map.GetProjection()
544    
545            bbox = None
546    
547            if proj is not None and self.current_map_proj is not None:
548                width, height = self.GetSizeTuple()
549                llx, lly = self.win_to_proj(0, height)
550                urx, ury = self.win_to_proj(width, 0)
551                bbox = proj.Inverse(llx, lly) + proj.Inverse(urx, ury)
552                bbox = self.current_map_proj.ForwardBBox(bbox)
553    
554            if bbox is not None:
555                self.FitRectToWindow(bbox)
556            else:
557                self.FitMapToWindow()
558    
559            self.full_redraw()
560    
561        def layer_projection_changed(self, *args):
562          self.full_redraw()          self.full_redraw()
563    
564      def set_view_transform(self, scale, offset):      def set_view_transform(self, scale, offset):
565            # width/height of the projected bbox
566            llx, lly, urx, ury = bbox = self.map.ProjectedBoundingBox()
567            pwidth = float(urx - llx)
568            pheight = float(ury - lly)
569    
570            # width/height of the window
571            wwidth, wheight = self.GetSizeTuple()
572    
573            # The window's center in projected coordinates assuming the new
574            # scale/offset
575            pcenterx = (wwidth/2 - offset[0]) / scale
576            pcentery = (offset[1] - wheight/2) / scale
577    
578            # The window coordinates used when drawing the shapes must fit
579            # into 16bit signed integers.
580            max_len = max(pwidth, pheight)
581            if max_len:
582                max_scale = 32000.0 / max_len
583            else:
584                # FIXME: What to do in this case? The bbox is effectively
585                # empty so any scale should work.
586                max_scale = scale
587    
588            # The minimal scale is somewhat arbitrarily set to half that of
589            # the bbox fit into the window
590            scales = []
591            if pwidth:
592                scales.append(wwidth / pwidth)
593            if pheight:
594                scales.append(wheight / pheight)
595            if scales:
596                min_scale = 0.5 * min(scales)
597            else:
598                min_scale = scale
599    
600            if scale > max_scale:
601                scale = max_scale
602            elif scale < min_scale:
603                scale = min_scale
604    
605          self.scale = scale          self.scale = scale
606          self.offset = offset  
607            # determine new offset to preserve the center
608            self.offset = (wwidth/2 - scale * pcenterx,
609                           wheight/2 + scale * pcentery)
610          self.full_redraw()          self.full_redraw()
611          self.issue(SCALE_CHANGED, scale)          self.issue(SCALE_CHANGED, scale)
612    
# Line 537  class MapCanvas(wxWindow, Publisher): Line 614  class MapCanvas(wxWindow, Publisher):
614          """\          """\
615          Return the point in  window coords given by projected coordinates x y          Return the point in  window coords given by projected coordinates x y
616          """          """
617            if self.scale == 0:
618                return (0, 0)
619    
620          offx, offy = self.offset          offx, offy = self.offset
621          return (self.scale * x + offx, -self.scale * y + offy)          return (self.scale * x + offx, -self.scale * y + offy)
622    
# Line 544  class MapCanvas(wxWindow, Publisher): Line 624  class MapCanvas(wxWindow, Publisher):
624          """\          """\
625          Return the point in projected coordinates given by window coords x y          Return the point in projected coordinates given by window coords x y
626          """          """
627            if self.scale == 0:
628                return (0, 0)
629    
630          offx, offy = self.offset          offx, offy = self.offset
631          return ((x - offx) / self.scale, (offy - y) / self.scale)          return ((x - offx) / self.scale, (offy - y) / self.scale)
632    
# Line 571  class MapCanvas(wxWindow, Publisher): Line 654  class MapCanvas(wxWindow, Publisher):
654          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
655          center it in the window.          center it in the window.
656          """          """
657          bbox = self.map.ProjectedBoundingBox()          if self.map is not None:
658          if bbox is not None:              bbox = self.map.ProjectedBoundingBox()
659              self.FitRectToWindow(bbox)              if bbox is not None:
660                    self.FitRectToWindow(bbox)
661    
662      def FitLayerToWindow(self, layer):      def FitLayerToWindow(self, layer):
663          """Fit the given layer to the window.          """Fit the given layer to the window.
# Line 602  class MapCanvas(wxWindow, Publisher): Line 686  class MapCanvas(wxWindow, Publisher):
686                  bbox = proj.ForwardBBox(bbox)                  bbox = proj.ForwardBBox(bbox)
687    
688              if bbox is not None:              if bbox is not None:
689                  self.FitRectToWindow(bbox)                  if len(shapes) == 1 and layer.ShapeType() == SHAPETYPE_POINT:
690                        self.ZoomFactor(1, self.proj_to_win(bbox[0], bbox[1]))
691                    else:
692                        self.FitRectToWindow(bbox)
693    
694      def ZoomFactor(self, factor, center = None):      def ZoomFactor(self, factor, center = None):
695          """Multiply the zoom by factor and center on center.          """Multiply the zoom by factor and center on center.
# Line 611  class MapCanvas(wxWindow, Publisher): Line 698  class MapCanvas(wxWindow, Publisher):
698          that should be centered. If it is omitted, it defaults to the          that should be centered. If it is omitted, it defaults to the
699          center of the window          center of the window
700          """          """
701          width, height = self.GetSizeTuple()          if self.scale > 0:
702          scale = self.scale * factor              width, height = self.GetSizeTuple()
703          offx, offy = self.offset              scale = self.scale * factor
704          if center is not None:              offx, offy = self.offset
705              cx, cy = center              if center is not None:
706          else:                  cx, cy = center
707              cx = width / 2              else:
708              cy = height / 2                  cx = width / 2
709          offset = (factor * (offx - cx) + width / 2,                  cy = height / 2
710                    factor * (offy - cy) + height / 2)              offset = (factor * (offx - cx) + width / 2,
711          self.set_view_transform(scale, offset)                      factor * (offy - cy) + height / 2)
712                self.set_view_transform(scale, offset)
713    
714      def ZoomOutToRect(self, rect):      def ZoomOutToRect(self, rect):
715          """Zoom out to fit the currently visible region into rect.          """Zoom out to fit the currently visible region into rect.
# Line 807  class MapCanvas(wxWindow, Publisher): Line 895  class MapCanvas(wxWindow, Publisher):
895              forward = None              forward = None
896    
897          scale = self.scale          scale = self.scale
898    
899            if scale == 0:
900                return None, None
901    
902          offx, offy = self.offset          offx, offy = self.offset
903    
904          if select_labels:          if select_labels:
# Line 885  class MapCanvas(wxWindow, Publisher): Line 977  class MapCanvas(wxWindow, Publisher):
977    
978              if shapetype == SHAPETYPE_POLYGON:              if shapetype == SHAPETYPE_POLYGON:
979                  for i in shape_ids:                  for i in shape_ids:
980                      result = point_in_polygon_shape(layer.shapefile.cobject(),                      shapefile = layer.ShapeStore().Shapefile().cobject()
981                                                      i,                      result = point_in_polygon_shape(shapefile, i,
982                                                      filled, stroked,                                                      filled, stroked,
983                                                      map_proj, layer_proj,                                                      map_proj, layer_proj,
984                                                      scale, -scale, offx, offy,                                                      scale, -scale, offx, offy,
# Line 896  class MapCanvas(wxWindow, Publisher): Line 988  class MapCanvas(wxWindow, Publisher):
988                          break                          break
989              elif shapetype == SHAPETYPE_ARC:              elif shapetype == SHAPETYPE_ARC:
990                  for i in shape_ids:                  for i in shape_ids:
991                      result = point_in_polygon_shape(layer.shapefile.cobject(),                      shapefile = layer.ShapeStore().Shapefile().cobject()
992                        result = point_in_polygon_shape(shapefile,
993                                                      i, 0, 1,                                                      i, 0, 1,
994                                                      map_proj, layer_proj,                                                      map_proj, layer_proj,
995                                                      scale, -scale, offx, offy,                                                      scale, -scale, offx, offy,
# Line 958  class MapCanvas(wxWindow, Publisher): Line 1051  class MapCanvas(wxWindow, Publisher):
1051              # a label was selected              # a label was selected
1052              label_layer.RemoveLabel(shape_index)              label_layer.RemoveLabel(shape_index)
1053          elif layer is not None:          elif layer is not None:
1054              text = labeldialog.run_label_dialog(self, layer.table, shape_index)              text = labeldialog.run_label_dialog(self,
1055                                                    layer.ShapeStore().Table(),
1056                                                    shape_index)
1057              if text:              if text:
1058                  proj = self.map.projection                  proj = self.map.projection
1059                  if proj is not None:                  if proj is not None:
# Line 973  class MapCanvas(wxWindow, Publisher): Line 1068  class MapCanvas(wxWindow, Publisher):
1068    
1069                  shapetype = layer.ShapeType()                  shapetype = layer.ShapeType()
1070                  if shapetype == SHAPETYPE_POLYGON:                  if shapetype == SHAPETYPE_POLYGON:
1071                      x, y = shape_centroid(layer.shapefile.cobject(),                      shapefile = layer.ShapeStore().Shapefile().cobject()
1072                                            shape_index,                      x, y = shape_centroid(shapefile, shape_index,
1073                                            map_proj, layer_proj, 1, 1, 0, 0)                                            map_proj, layer_proj, 1, 1, 0, 0)
1074                      if map_proj is not None:                      if map_proj is not None:
1075                          x, y = map_proj.Inverse(x, y)                          x, y = map_proj.Inverse(x, y)

Legend:
Removed from v.910  
changed lines
  Added in v.1271

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26