Skip to content

Commit

Permalink
added orbital rotation mode and take scroll delta into account when z…
Browse files Browse the repository at this point in the history
…ooming
  • Loading branch information
mbway committed May 28, 2021
1 parent 0613140 commit 5b65f4d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 42 deletions.
97 changes: 57 additions & 40 deletions cq_editor/widgets/occt_widget.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,55 @@
import math
from sys import platform


from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QEvent

import OCP

from OCP.AIS import AIS_InteractiveContext, AIS_DisplayMode
from OCP.Aspect import Aspect_DisplayConnection, Aspect_TypeOfTriedronPosition
from OCP.OpenGl import OpenGl_GraphicDriver
from OCP.V3d import V3d_Viewer
from OCP.AIS import AIS_InteractiveContext, AIS_DisplayMode
from OCP.Quantity import Quantity_Color
from OCP.V3d import V3d_Viewer
from OCP.gp import gp_Trsf, gp_Ax1, gp_Dir
from PyQt5.QtCore import pyqtSignal, Qt, QPoint
from PyQt5.QtWidgets import QWidget


ZOOM_STEP = 0.9


class OCCTWidget(QWidget):

sigObjectSelected = pyqtSignal(list)

def __init__(self,parent=None):
def __init__(self, parent=None, *,
orbital_rotation: bool = True,
rotate_step: float = 0.008,
zoom_step: float = 0.1):

super(OCCTWidget,self).__init__(parent)
super(OCCTWidget, self).__init__(parent)

self.setAttribute(Qt.WA_NativeWindow)
self.setAttribute(Qt.WA_PaintOnScreen)
self.setAttribute(Qt.WA_NoSystemBackground)

self._initialized = False
self._needs_update = False
self._old_pos = QPoint(0, 0)
self._rotate_step = rotate_step
self._zoom_step = zoom_step
self._orbital_rotation = orbital_rotation

#OCCT secific things
# OCCT secific things
self.display_connection = Aspect_DisplayConnection()
self.graphics_driver = OpenGl_GraphicDriver(self.display_connection)

self.viewer = V3d_Viewer(self.graphics_driver)
self.view = self.viewer.CreateView()
self.context = AIS_InteractiveContext(self.viewer)

#Trihedorn, lights, etc
# Trihedorn, lights, etc
self.prepare_display()


def set_orbital_rotation(self, new_value: bool):
if self._orbital_rotation != new_value:
self._orbital_rotation = new_value

Check warning on line 49 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L49

Added line #L49 was not covered by tests
if self._orbital_rotation:
self.view.SetUp(0, 0, 1)

Check warning on line 51 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L51

Added line #L51 was not covered by tests

def prepare_display(self):

view = self.view
Expand All @@ -65,49 +73,58 @@ def prepare_display(self):
ctx.DefaultDrawer().SetFaceBoundaryDraw(True)

def wheelEvent(self, event):

delta = event.angleDelta().y()
factor = ZOOM_STEP if delta<0 else 1/ZOOM_STEP


# dividing by 120 gets number of notches on a typical scroll wheel.
# See QWheelEvent documentation
delta_notches = event.angleDelta().y() / 120
direction = math.copysign(1, delta_notches)
factor = (1 + self._zoom_step * direction) ** abs(delta_notches)

Check warning on line 81 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L79-L81

Added lines #L79 - L81 were not covered by tests

self.view.SetZoom(factor)

def mousePressEvent(self,event):
def mousePressEvent(self, event):

pos = event.pos()

if event.button() == Qt.LeftButton:
self.view.StartRotation(pos.x(), pos.y())
if not self._orbital_rotation:
self.view.StartRotation(pos.x(), pos.y())

Check warning on line 91 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L91

Added line #L91 was not covered by tests
elif event.button() == Qt.RightButton:
self.view.StartZoomAtPoint(pos.x(), pos.y())

self.old_pos = pos
def mouseMoveEvent(self,event):
self._old_pos = pos

def mouseMoveEvent(self, event):

pos = event.pos()
x,y = pos.x(),pos.y()
x, y = pos.x(), pos.y()

Check warning on line 100 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L100

Added line #L100 was not covered by tests

if event.buttons() == Qt.LeftButton:
self.view.Rotation(x,y)

if self._orbital_rotation:
delta_x, delta_y = x - self._old_pos.x(), y - self._old_pos.y()
cam = self.view.Camera()
z_rotation = gp_Trsf()
z_rotation.SetRotation(gp_Ax1(cam.Center(), gp_Dir(0, 0, 1)), -delta_x * self._rotate_step)
cam.Transform(z_rotation)
self.view.Rotate(0, -delta_y * self._rotate_step, 0)

Check warning on line 109 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L104-L109

Added lines #L104 - L109 were not covered by tests
else:
self.view.Rotation(x, y)

Check warning on line 111 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L111

Added line #L111 was not covered by tests

elif event.buttons() == Qt.MiddleButton:
self.view.Pan(x - self.old_pos.x(),
self.old_pos.y() - y, theToStart=True)
delta_x, delta_y = x - self._old_pos.x(), y - self._old_pos.y()
self.view.Pan(delta_x, -delta_y, theToStart=True)

Check warning on line 115 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L114-L115

Added lines #L114 - L115 were not covered by tests

elif event.buttons() == Qt.RightButton:
self.view.ZoomAtPoint(self.old_pos.x(), y,
x, self.old_pos.y())
self.view.ZoomAtPoint(self._old_pos.x(), y,

Check warning on line 118 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L118

Added line #L118 was not covered by tests
x, self._old_pos.y())

self.old_pos = pos
self._old_pos = pos

Check warning on line 121 in cq_editor/widgets/occt_widget.py

View check run for this annotation

Codecov / codecov/patch

cq_editor/widgets/occt_widget.py#L121

Added line #L121 was not covered by tests

def mouseReleaseEvent(self,event):
def mouseReleaseEvent(self, event):

if event.button() == Qt.LeftButton:
pos = event.pos()
x,y = pos.x(),pos.y()

self.context.MoveTo(x,y,self.view,True)

self.context.MoveTo(pos.x(), pos.y(), self.view, True)
self._handle_selection()

def _handle_selection(self):
Expand Down
6 changes: 4 additions & 2 deletions cq_editor/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ class OCCViewer(QWidget,ComponentMixin):
{'name': 'Background color (aux)', 'type': 'color', 'value': (30,30,30)},
{'name': 'Default object color', 'type': 'color', 'value': "FF0"},
{'name': 'Deviation', 'type': 'float', 'value': 1e-5, 'dec': True, 'step': 1},
{'name': 'Angular deviation', 'type': 'float', 'value': 0.1, 'dec': True, 'step': 1}])

{'name': 'Angular deviation', 'type': 'float', 'value': 0.1, 'dec': True, 'step': 1},
{'name': 'Orbital rotation', 'type': 'bool', 'value': True}])


IMAGE_EXTENSIONS = 'png'

Expand Down Expand Up @@ -71,6 +72,7 @@ def updatePreferences(self,*args):
if not self.preferences['Use gradient']:
color2 = color1
self.canvas.view.SetBgGradientColors(color1,color2,theToUpdate=True)
self.canvas.set_orbital_rotation(self.preferences['Orbital rotation'])

self.canvas.update()

Expand Down

0 comments on commit 5b65f4d

Please sign in to comment.