| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- # ##########################################################
- # FlatCAM: 2D Post-processing for Manufacturing #
- # http://flatcam.org #
- # File Author: Dennis Hayrullin #
- # Date: 2/5/2016 #
- # MIT Licence #
- # ##########################################################
- from PyQt5.QtGui import QPalette
- from PyQt5.QtCore import QSettings
- import numpy as np
- import vispy.scene as scene
- from vispy.scene.cameras.base_camera import BaseCamera
- # from vispy.scene.widgets import Widget as VisPyWidget
- from vispy.color import Color
- import time
- white = Color("#ffffff")
- black = Color("#000000")
- class VisPyCanvas(scene.SceneCanvas):
- def __init__(self, config=None):
- # scene.SceneCanvas.__init__(self, keys=None, config=config)
- super().__init__(config=config, keys=None)
- self.unfreeze()
- settings = QSettings("Open Source", "FlatCAM")
- if settings.contains("axis_font_size"):
- a_fsize = settings.value('axis_font_size', type=int)
- else:
- a_fsize = 8
- if settings.contains("theme"):
- theme = settings.value('theme', type=str)
- else:
- theme = 'white'
- if theme == 'white':
- theme_color = Color('#FFFFFF')
- tick_color = Color('#000000')
- back_color = str(QPalette().color(QPalette.Window).name())
- else:
- theme_color = Color('#000000')
- tick_color = Color('gray')
- back_color = Color('#000000')
- # back_color = Color('#272822') # darker
- # back_color = Color('#3c3f41') # lighter
- self.central_widget.bgcolor = back_color
- self.central_widget.border_color = back_color
- self.grid_widget = self.central_widget.add_grid(margin=10)
- self.grid_widget.spacing = 0
- top_padding = self.grid_widget.add_widget(row=0, col=0, col_span=2)
- top_padding.height_max = 0
- self.yaxis = scene.AxisWidget(
- orientation='left', axis_color=tick_color, text_color=tick_color, font_size=a_fsize, axis_width=1
- )
- self.yaxis.width_max = 55
- self.grid_widget.add_widget(self.yaxis, row=1, col=0)
- self.xaxis = scene.AxisWidget(
- orientation='bottom', axis_color=tick_color, text_color=tick_color, font_size=a_fsize, axis_width=1,
- anchors=['center', 'bottom']
- )
- self.xaxis.height_max = 30
- self.grid_widget.add_widget(self.xaxis, row=2, col=1)
- right_padding = self.grid_widget.add_widget(row=0, col=2, row_span=2)
- # right_padding.width_max = 24
- right_padding.width_max = 0
- view = self.grid_widget.add_view(row=1, col=1, border_color=tick_color, bgcolor=theme_color)
- view.camera = Camera(aspect=1, rect=(-25, -25, 150, 150))
- # Following function was removed from 'prepare_draw()' of 'Grid' class by patch,
- # it is necessary to call manually
- self.grid_widget._update_child_widget_dim()
- self.xaxis.link_view(view)
- self.yaxis.link_view(view)
- # grid1 = scene.GridLines(parent=view.scene, color='dimgray')
- # grid1.set_gl_state(depth_test=False)
- settings = QSettings("Open Source", "FlatCAM")
- if settings.contains("theme"):
- theme = settings.value('theme', type=str)
- else:
- theme = 'white'
- self.view = view
- if theme == 'white':
- self.grid = scene.GridLines(parent=self.view.scene, color='dimgray')
- else:
- self.grid = scene.GridLines(parent=self.view.scene, color='#dededeff')
- self.grid.set_gl_state(depth_test=False)
- self.freeze()
- # self.measure_fps()
- def translate_coords(self, pos):
- """
- Translate pixels to FlatCAM units.
- """
- tr = self.grid.get_transform('canvas', 'visual')
- return tr.map(pos)
- def translate_coords_2(self, pos):
- """
- Translate FlatCAM units to pixels.
- """
- tr = self.grid.get_transform('visual', 'document')
- return tr.map(pos)
- class Camera(scene.PanZoomCamera):
- def __init__(self, **kwargs):
- super(Camera, self).__init__(**kwargs)
- self.minimum_scene_size = 0.01
- self.maximum_scene_size = 10000
- self.last_event = None
- self.last_time = 0
- # Default mouse button for panning is RMB
- self.pan_button_setting = "2"
- def zoom(self, factor, center=None):
- center = center if (center is not None) else self.center
- super(Camera, self).zoom(factor, center)
- def viewbox_mouse_event(self, event):
- """
- The SubScene received a mouse event; update transform
- accordingly.
- Parameters
- ----------
- event : instance of Event
- The event.
- """
- if event.handled or not self.interactive:
- return
- # key modifiers
- modifiers = event.mouse_event.modifiers
- # Limit mouse move events
- last_event = event.last_event
- t = time.time()
- if t - self.last_time > 0.015:
- self.last_time = t
- if self.last_event:
- last_event = self.last_event
- self.last_event = None
- else:
- if not self.last_event:
- self.last_event = last_event
- event.handled = True
- return
- # ################### Scrolling ##########################
- BaseCamera.viewbox_mouse_event(self, event)
- if event.type == 'mouse_wheel':
- if not modifiers:
- center = self._scene_transform.imap(event.pos)
- scale = (1 + self.zoom_factor) ** (-event.delta[1] * 30)
- self.limited_zoom(scale, center)
- event.handled = True
- elif event.type == 'mouse_move':
- if event.press_event is None:
- return
- # ################ Panning ############################
- # self.pan_button_setting is actually self.FlatCAM.APP.defaults['global_pan_button']
- if event.button == int(self.pan_button_setting) and not modifiers:
- # Translate
- p1 = np.array(last_event.pos)[:2]
- p2 = np.array(event.pos)[:2]
- p1s = self._transform.imap(p1)
- p2s = self._transform.imap(p2)
- self.pan(p1s-p2s)
- event.handled = True
- elif event.button in [2, 3] and 'Shift' in modifiers:
- # Zoom
- p1c = np.array(last_event.pos)[:2]
- p2c = np.array(event.pos)[:2]
- scale = ((1 + self.zoom_factor) **
- ((p1c-p2c) * np.array([1, -1])))
- center = self._transform.imap(event.press_event.pos[:2])
- self.limited_zoom(scale, center)
- event.handled = True
- else:
- event.handled = False
- elif event.type == 'mouse_press':
- # accept the event if it is button 1 or 2.
- # This is required in order to receive future events
- event.handled = event.button in [1, 2, 3]
- else:
- event.handled = False
- def limited_zoom(self, scale, center):
- try:
- zoom_in = scale[1] < 1
- except IndexError:
- zoom_in = scale < 1
- if (not zoom_in and self.rect.width < self.maximum_scene_size) \
- or (zoom_in and self.rect.width > self.minimum_scene_size):
- self.zoom(scale, center)
|