VisPyCanvas.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import numpy as np
  2. from PyQt5.QtGui import QPalette
  3. import vispy.scene as scene
  4. from vispy.scene.cameras.base_camera import BaseCamera
  5. from vispy.color import Color
  6. import time
  7. white = Color("#ffffff" )
  8. black = Color("#000000")
  9. class VisPyCanvas(scene.SceneCanvas):
  10. def __init__(self, config=None):
  11. scene.SceneCanvas.__init__(self, keys=None, config=config)
  12. self.unfreeze()
  13. back_color = str(QPalette().color(QPalette.Window).name())
  14. self.central_widget.bgcolor = back_color
  15. self.central_widget.border_color = back_color
  16. self.grid_widget = self.central_widget.add_grid(margin=10)
  17. self.grid_widget.spacing = 0
  18. top_padding = self.grid_widget.add_widget(row=0, col=0, col_span=2)
  19. top_padding.height_max = 0
  20. self.yaxis = scene.AxisWidget(orientation='left', axis_color='black', text_color='black', font_size=8)
  21. self.yaxis.width_max = 55
  22. self.grid_widget.add_widget(self.yaxis, row=1, col=0)
  23. self.xaxis = scene.AxisWidget(orientation='bottom', axis_color='black', text_color='black', font_size=8)
  24. self.xaxis.height_max = 25
  25. self.grid_widget.add_widget(self.xaxis, row=2, col=1)
  26. right_padding = self.grid_widget.add_widget(row=0, col=2, row_span=2)
  27. # right_padding.width_max = 24
  28. right_padding.width_max = 0
  29. view = self.grid_widget.add_view(row=1, col=1, border_color='black', bgcolor='white')
  30. view.camera = Camera(aspect=1, rect=(-100,-100,500,500))
  31. # Following function was removed from 'prepare_draw()' of 'Grid' class by patch,
  32. # it is necessary to call manually
  33. self.grid_widget._update_child_widget_dim()
  34. self.xaxis.link_view(view)
  35. self.yaxis.link_view(view)
  36. grid1 = scene.GridLines(parent=view.scene, color='dimgray')
  37. grid1.set_gl_state(depth_test=False)
  38. self.view = view
  39. self.grid = grid1
  40. self.freeze()
  41. # self.measure_fps()
  42. def translate_coords(self, pos):
  43. tr = self.grid.get_transform('canvas', 'visual')
  44. return tr.map(pos)
  45. def translate_coords_2(self, pos):
  46. tr = self.grid.get_transform('visual', 'document')
  47. return tr.map(pos)
  48. class Camera(scene.PanZoomCamera):
  49. def __init__(self, **kwargs):
  50. super(Camera, self).__init__(**kwargs)
  51. self.minimum_scene_size = 0.01
  52. self.maximum_scene_size = 10000
  53. self.last_event = None
  54. self.last_time = 0
  55. # Default mouse button for panning is RMB
  56. self.pan_button_setting = "2"
  57. def zoom(self, factor, center=None):
  58. center = center if (center is not None) else self.center
  59. super(Camera, self).zoom(factor, center)
  60. def viewbox_mouse_event(self, event):
  61. """
  62. The SubScene received a mouse event; update transform
  63. accordingly.
  64. Parameters
  65. ----------
  66. event : instance of Event
  67. The event.
  68. """
  69. if event.handled or not self.interactive:
  70. return
  71. # Limit mouse move events
  72. last_event = event.last_event
  73. t = time.time()
  74. if t - self.last_time > 0.015:
  75. self.last_time = t
  76. if self.last_event:
  77. last_event = self.last_event
  78. self.last_event = None
  79. else:
  80. if not self.last_event:
  81. self.last_event = last_event
  82. event.handled = True
  83. return
  84. # Scrolling
  85. BaseCamera.viewbox_mouse_event(self, event)
  86. if event.type == 'mouse_wheel':
  87. center = self._scene_transform.imap(event.pos)
  88. scale = (1 + self.zoom_factor) ** (-event.delta[1] * 30)
  89. self.limited_zoom(scale, center)
  90. event.handled = True
  91. elif event.type == 'mouse_move':
  92. if event.press_event is None:
  93. return
  94. modifiers = event.mouse_event.modifiers
  95. # self.pan_button_setting is actually self.FlatCAM.APP.defaults['global_pan_button']
  96. if event.button == int(self.pan_button_setting) and not modifiers:
  97. # Translate
  98. p1 = np.array(last_event.pos)[:2]
  99. p2 = np.array(event.pos)[:2]
  100. p1s = self._transform.imap(p1)
  101. p2s = self._transform.imap(p2)
  102. self.pan(p1s-p2s)
  103. event.handled = True
  104. elif event.button in [2, 3] and 'Shift' in modifiers:
  105. # Zoom
  106. p1c = np.array(last_event.pos)[:2]
  107. p2c = np.array(event.pos)[:2]
  108. scale = ((1 + self.zoom_factor) **
  109. ((p1c-p2c) * np.array([1, -1])))
  110. center = self._transform.imap(event.press_event.pos[:2])
  111. self.limited_zoom(scale, center)
  112. event.handled = True
  113. else:
  114. event.handled = False
  115. elif event.type == 'mouse_press':
  116. # accept the event if it is button 1 or 2.
  117. # This is required in order to receive future events
  118. event.handled = event.button in [1, 2, 3]
  119. else:
  120. event.handled = False
  121. def limited_zoom(self, scale, center):
  122. try:
  123. zoom_in = scale[1] < 1
  124. except IndexError:
  125. zoom_in = scale < 1
  126. if (not zoom_in and self.rect.width < self.maximum_scene_size) \
  127. or (zoom_in and self.rect.width > self.minimum_scene_size):
  128. self.zoom(scale, center)