Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clipping plane support for X/Y/Z dimensions. #391

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cq_editor/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .widgets.viewer import OCCViewer
from .widgets.console import ConsoleWidget
from .widgets.object_tree import ObjectTree
from .widgets.clipping_planes import ClippingPlanes
from .widgets.traceback_viewer import TracebackPane
from .widgets.debugger import Debugger, LocalsView
from .widgets.cq_object_inspector import CQObjectInspector
Expand Down Expand Up @@ -128,6 +129,13 @@ def prepare_panes(self):
self,
defaultArea='bottom'))

self.registerComponent('clipping_planes',
ClippingPlanes(self),
lambda c: dock(c,
'Clipping Planes',
self,
defaultArea='right'))

for d in self.docks.values():
d.show()

Expand Down Expand Up @@ -259,6 +267,9 @@ def prepare_actions(self):
self.components['debugger'].sigTraceback\
.connect(self.components['traceback_viewer'].addTraceback)

self.components['clipping_planes'].sigClippingPlaneChanged\
.connect(self.components['viewer'].update_clipping_plane)

# trigger re-render when file is modified externally or saved
self.components['editor'].triggerRerender \
.connect(self.components['debugger'].render)
Expand Down
74 changes: 74 additions & 0 deletions cq_editor/widgets/clipping_planes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from PyQt5.QtWidgets import QApplication, QCheckBox, QHBoxLayout, QLabel, QSpinBox, QWidget
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal

from qtconsole.rich_jupyter_widget import RichJupyterWidget

from ..mixins import ComponentMixin
from ..utils import layout

class ClippingPlane(QWidget):

sigClippingPlaneChanged = pyqtSignal(bool,int,bool)

def __init__(self, parent, dimension):
super(ClippingPlane, self).__init__(parent)

self.check = QCheckBox(f"{dimension} Axis", self)
self.spinbox = QSpinBox(self)
self.spinbox.setValue(50)
self.spinbox.setRange(1, 256)
self.invert = QCheckBox("Invert", self)

self.group = layout(self,(self.spinbox,self.invert),layout_type=QHBoxLayout, spacing=5)

layout(self,(self.check,self.group),layout_type=QHBoxLayout, top_widget=self)

self.group.setDisabled(True)
self.check.stateChanged.connect(self.handleChecked)
self.invert.stateChanged.connect(self.handleInvertChecked)
self.spinbox.valueChanged.connect(self.handlePositionChanged)

def handleChecked(self, arg):
self.group.setDisabled(not self.check.checkState())
self.emitState()

def handleInvertChecked(self, arg):
self.emitState()

def handlePositionChanged(self, arg):
self.emitState()

def emitState(self):
self.sigClippingPlaneChanged.emit(self.check.checkState(), self.spinbox.value(), self.invert.checkState())

class ClippingPlanes(QWidget,ComponentMixin):

name = 'Clipping Planes'

sigClippingPlaneChanged = pyqtSignal(str,bool,int,bool)

def __init__(self, parent):
super(ClippingPlanes, self).__init__(parent)

self.x = ClippingPlane(self, "X")
self.x.sigClippingPlaneChanged.connect(self.onXPlaneChanged)
self.y = ClippingPlane(self, "Y")
self.y.sigClippingPlaneChanged.connect(self.onYPlaneChanged)
self.z = ClippingPlane(self, "Z")
self.z.sigClippingPlaneChanged.connect(self.onZPlaneChanged)

layout(self,(self.x,self.y,self.z),top_widget=self)

@pyqtSlot(bool,int,bool)
def onXPlaneChanged(self,enabled,val,inverted):
self.sigClippingPlaneChanged.emit("X",enabled,val,inverted)

@pyqtSlot(bool,int,bool)
def onYPlaneChanged(self,enabled,val,inverted):
self.sigClippingPlaneChanged.emit("Y",enabled,val,inverted)

@pyqtSlot(bool,int,bool)
def onZPlaneChanged(self,enabled,val,inverted):
self.sigClippingPlaneChanged.emit("Z",enabled,val,inverted)


42 changes: 37 additions & 5 deletions cq_editor/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtGui import QIcon

from OCP.Graphic3d import Graphic3d_Camera, Graphic3d_StereoMode, Graphic3d_NOM_JADE,\
Graphic3d_MaterialAspect
from OCP.Graphic3d import Graphic3d_Camera, Graphic3d_ClipPlane, Graphic3d_StereoMode, Graphic3d_NOM_JADE,\
Graphic3d_MaterialAspect, Graphic3d_Texture2Dplane
from OCP.AIS import AIS_Shaded,AIS_WireFrame, AIS_ColoredShape, AIS_Axis
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, Quantity_TOC_RGB as TOC_RGB,\
from OCP.Aspect import Aspect_GDM_Lines, Aspect_GT_Rectangular, Aspect_HS_GRID
from OCP.TCollection import TCollection_AsciiString
from OCP.Quantity import Quantity_NOC_BLACK as BLACK, Quantity_NOC_WHITE as WHITE, Quantity_TOC_RGB as TOC_RGB,\
Quantity_Color
from OCP.Geom import Geom_Axis1Placement
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1
from OCP.gp import gp_Ax3, gp_Dir, gp_Pnt, gp_Ax1, gp_Pln

from ..utils import layout, get_save_filename
from ..mixins import ComponentMixin
Expand Down Expand Up @@ -56,6 +57,14 @@ def __init__(self,parent=None):
self.canvas = OCCTWidget()
self.canvas.sigObjectSelected.connect(self.handle_selection)


self.x_clipping_plane = self.setup_clipping_plane(gp_Pln(-1, 0.0, 0.0, 100))
self.y_clipping_plane = self.setup_clipping_plane(gp_Pln(0.0, -1, 0.0, 100))
self.z_clipping_plane = self.setup_clipping_plane(gp_Pln(0.0, 0.0, -1, 100))
self.canvas.view.AddClipPlane(self.x_clipping_plane)
self.canvas.view.AddClipPlane(self.y_clipping_plane)
self.canvas.view.AddClipPlane(self.z_clipping_plane)

self.create_actions(self)

self.layout_ = layout(self,
Expand All @@ -66,6 +75,16 @@ def __init__(self,parent=None):
self.setup_default_drawer()
self.updatePreferences()

def setup_clipping_plane(self, eq):
cp = Graphic3d_ClipPlane()
cp.SetEquation(eq)
cp.SetCapping(True)
cp.SetUseObjectMaterial(True)
# cp.SetCappingTexture(Graphic3d_Texture2Dplane(TCollection_AsciiString("./clip-texture.png")))
cp.SetOn(False)

return cp

def setup_default_drawer(self):

# set the default color and material
Expand Down Expand Up @@ -369,6 +388,19 @@ def set_selected(self,ais):

self.redraw()

@pyqtSlot(str,bool,int,bool)
def update_clipping_plane(self,plane,enabled,val,inverted):
if plane == "X":
self.x_clipping_plane.SetEquation(gp_Pln(1 if inverted else -1, 0.0, 0.0, val))
self.x_clipping_plane.SetOn(enabled)
elif plane == "Y":
self.y_clipping_plane.SetEquation(gp_Pln(0.0, 1 if inverted else -1, 0.0, val))
self.y_clipping_plane.SetOn(enabled)
elif plane == "Z":
self.z_clipping_plane.SetEquation(gp_Pln(0.0, 0.0, 1 if inverted else -1, val))
self.z_clipping_plane.SetOn(enabled)

self.redraw()

if __name__ == "__main__":

Expand Down