# libraries to link to
SET(_link_LIBRARIES
- ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${CAS_KERNEL} ${CAS_VIEWER}
+ ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${CAS_KERNEL} ${CAS_VIEWER} ${CAS_TKGeomAlgo}
CASCatch qtx suit OpenGLUtils ViewerTools ViewerData
)
OCCViewer_ViewPort3d.h
OCCViewer_ViewSketcher.h
OCCViewer_ViewWindow.h
+ OCCViewer_ViewportInputFilter.h
+ OCCViewer_ClipPlaneInteractor.h
)
# header files / no moc processing
OCCViewer_ViewPort3d.cxx
OCCViewer_ViewSketcher.cxx
OCCViewer_ViewWindow.cxx
+ OCCViewer_ViewportInputFilter.cxx
+ OCCViewer_ClipPlaneInteractor.cxx
)
# sources / to compile
--- /dev/null
+// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "OCCViewer_ClipPlaneInteractor.h"
+#include "OCCViewer_ViewPort3d.h"
+#include "OCCViewer_ViewModel.h"
+
+#include <AIS_InteractiveContext.hxx>
+#include <SelectMgr_EntityOwner.hxx>
+#include <V3d_View.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <GeomAPI_IntCS.hxx>
+#include <gce_MakeDir.hxx>
+
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+/*!
+ \brief Constructor.
+ \param theVM [in] the view manager.
+ \param theParent [in] the parent object.
+*/
+OCCViewer_ClipPlaneInteractor::OCCViewer_ClipPlaneInteractor( OCCViewer_ViewManager* theVM,
+ QObject* theParent )
+: OCCViewer_ViewportInputFilter( theVM, theParent ),
+ myPerformingOp( DragOperation_Undef ),
+ myRotationCenter( gp::Origin() ),
+ myIsDraggable( false ),
+ myIsClickable( false )
+{
+}
+
+/*!
+ \brief Get sequence of planes to interact with.
+ \return the sequence of accepted planes.
+*/
+const OCCViewer_ClipPlaneInteractor::SeqOfPlanes& OCCViewer_ClipPlaneInteractor::planes() const
+{
+ return myPlanes;
+}
+
+/*!
+ \brief Sets sequence of planes allowed for interaction.
+ \param thePlanes [in] the sequence of accepted planes.
+*/
+void OCCViewer_ClipPlaneInteractor::setPlanes( const SeqOfPlanes& thePlanes )
+{
+ myPlanes = thePlanes;
+}
+
+/*!
+ \brief Sets center of rotation for the scene.
+ \param theCenter [in] the center of rotation.
+*/
+void OCCViewer_ClipPlaneInteractor::setRotationCenter( const gp_Pnt& theCenter )
+{
+ myRotationCenter = theCenter;
+}
+
+/*!
+ \brief Sets minimum and maximum bounding of the scene.
+ The sliding movements are limited to minimum
+ and maximum bounds.
+ \param theMinMax [in] the minimum and maximum bounds.
+*/
+void OCCViewer_ClipPlaneInteractor::setMinMax( const Bnd_Box& theMinMax )
+{
+ myMinMax = theMinMax;
+}
+
+/*!
+ \brief Enables or disables event processing within the viewer.
+*/
+void OCCViewer_ClipPlaneInteractor::setEnabled( const bool theIsEnabled )
+{
+ if ( !theIsEnabled )
+ {
+ }
+
+ myMouseDragPln = gp_Pln();
+ myPerformingOp = DragOperation_Undef;
+ myPickPos = QPoint();
+ myDragPos = QPoint();
+ myInteractedPlane = NULL;
+ myIsDraggable = false;
+ myIsClickable = false;
+
+ OCCViewer_ViewportInputFilter::setEnabled( theIsEnabled );
+}
+
+/*!
+ \brief Checks whether the interactive operation is in progress.
+ \return TRUE if the interaction is performed on IO object meaning
+ that no other operations in viewer should be processed.
+*/
+bool OCCViewer_ClipPlaneInteractor::isPerforming() const
+{
+ return !myInteractedPlane.IsNull();
+}
+
+/*!
+ \brief Checks whether the interactive plane can be clicked.
+ \return TRUE if the click interaction is supported for the plane.
+*/
+bool OCCViewer_ClipPlaneInteractor::isClickable( const Handle(AIS_Plane)& thePlane )
+{
+ bool isFound = Standard_False;
+ for ( int aPlaneIt = 0; aPlaneIt < myPlanes.size(); ++aPlaneIt )
+ {
+ if ( myPlanes[aPlaneIt] == thePlane )
+ {
+ isFound = true;
+ break;
+ }
+ }
+
+ if ( !isFound )
+ {
+ return false;
+ }
+
+ Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+ if ( anAISContext->IsSelected( thePlane ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \brief Checks whether the interactive plane can be dragged.
+ \return TRUE if the dragging interaction is supported for the plane.
+*/
+bool OCCViewer_ClipPlaneInteractor::isDraggable( const Handle(AIS_Plane)& thePlane )
+{
+ bool isFound = Standard_False;
+ for ( int aPlaneIt = 0; aPlaneIt < myPlanes.size(); ++aPlaneIt )
+ {
+ if ( myPlanes[aPlaneIt] == thePlane )
+ {
+ isFound = true;
+ break;
+ }
+ }
+
+ if ( !isFound )
+ {
+ return false;
+ }
+
+ Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+ if ( !anAISContext->IsSelected( thePlane ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ \brief Checks whether it is possible to start interaction with plane.
+ \param thePickPos [in] the position of mouse picking.
+ \param theDragPos [in] the position of initial mouse dragging.
+ \param theDragOp [in] the drag operation to start.
+ \param thePlane [in] the detected plane.
+ \param theView [in] the view.
+*/
+bool OCCViewer_ClipPlaneInteractor::startDragging( const QPoint& thePickPos,
+ const QPoint& theDragPos,
+ const DragOperation theDragOp,
+ const Handle(AIS_Plane)& thePlane,
+ const Handle(V3d_View)& theView )
+{
+ // get point of view plane intersection with the plane
+ Standard_Real P[3], D[3];
+ theView->ConvertWithProj( thePickPos.x(), thePickPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
+ gp_Lin aPickProj = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+ gp_Pln aPlanePln = thePlane->Component()->Pln();
+
+ Handle(Geom_Line) aPickLine = new Geom_Line( aPickProj );
+ Handle(Geom_Plane) aCrossPlane = new Geom_Plane( aPlanePln );
+
+ GeomAPI_IntCS aFindPick( aPickLine, aCrossPlane );
+ if ( !aFindPick.IsDone() || aFindPick.NbPoints() == 0 )
+ {
+ return false;
+ }
+
+ // check plane geometry
+ Standard_Real aSizeX = 0.0;
+ Standard_Real aSizeY = 0.0;
+ thePlane->Size(aSizeX, aSizeY);
+ if ( aSizeX < Precision::Confusion() || aSizeY < Precision::Confusion() )
+ {
+ return false;
+ }
+
+ gp_Pnt aPickPoint = aFindPick.Point( 1 );
+
+ const gp_Dir& aPlaneN = aPlanePln.Axis().Direction();
+ const gp_Dir& aPlaneX = aPlanePln.XAxis().Direction();
+ const gp_Dir& aPlaneY = aPlanePln.YAxis().Direction();
+ const gp_Pnt& aPlaneCenter = aPlanePln.Location();
+
+ switch ( theDragOp )
+ {
+ // sliding operation is started
+ case DragOperation_Slide :
+ {
+ if ( aPlaneN.IsParallel( aPickProj.Direction(), M_PI / 180.0 ) )
+ {
+ return false;
+ }
+
+ gp_Dir aMousePlnDir = ( aPickProj.Direction() ^ aPlaneN ) ^ aPlaneN;
+
+ myMouseDragPln = gp_Pln( aPickPoint, aMousePlnDir );
+ myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
+
+ return true;
+ }
+
+ // rotation operation is requested
+ case DragOperation_Rotate :
+ {
+ theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
+ gp_Lin aDragProj = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+
+ if ( aPickPoint.Distance( aDragProj.Location() ) < Precision::Confusion() )
+ {
+ return false;
+ }
+
+ // to determine whether we rotate around first or second axis, we
+ // construct a virtual "arm" as vector of from center of rotation
+ // to the picked point. Then we calculate dragging directions for both axes
+ // depending on the difference of picking and dragging mouse coordinates.
+ // The direction which is physically more easy to turn the "arm" is choosen
+ // and the corresponding plane for dragging is selected.
+
+ gp_Vec anArm = gp_Vec( myRotationCenter, aPickPoint );
+ Standard_Real anArmLength = anArm.Magnitude();
+ if ( anArmLength < Precision::Confusion() )
+ {
+ return false;
+ }
+
+ Handle(Geom_Line) aDragLine = new Geom_Line( aDragProj );
+ Standard_Real aMomentArm1 = 0.0;
+ Standard_Real aMomentArm2 = 0.0;
+ Standard_Real anArmLength1 = Abs( anArm * gp_Vec( aPlaneN ^ aPlaneX ) );
+ Standard_Real anArmLength2 = Abs( anArm * gp_Vec( aPlaneN ^ aPlaneY ) );
+
+ // check virtual "arm" dragging moment for first axis of rotation
+ if ( !aPlaneX.IsNormal( aDragProj.Direction(), M_PI / 180.0 ) && ( anArmLength1 / anArmLength > 0.3 ) )
+ {
+ Handle(Geom_Plane) aDragPln = new Geom_Plane( aPickPoint, aPlaneX );
+
+ gp_Pnt aDragPnt = aPickPoint;
+ gp_Vec aDragDir = gp_Vec( 0.0, 0.0, 0.0 );
+ GeomAPI_IntCS aFindCross( aDragLine, aDragPln );
+ if ( aFindCross.IsDone() && aFindCross.NbPoints() != 0 )
+ {
+ aDragPnt = aFindCross.Point( 1 );
+ }
+
+ if ( aDragPnt.Distance( aPickPoint ) > Precision::Confusion() )
+ {
+ aDragDir = gp_Vec( aPickPoint, aDragPnt );
+ }
+
+ aMomentArm1 = anArmLength1 * ( 1.0 - Abs( aDragDir.Normalized() * anArm.Normalized() ) );
+ }
+
+ // check virtual "arm" dragging moment for second axis of rotation
+ if ( !aPlaneY.IsNormal( aDragProj.Direction(), M_PI / 180.0 )&& ( anArmLength2 / anArmLength > 0.3 ) )
+ {
+ Handle(Geom_Plane) aDragPln = new Geom_Plane( aPickPoint, aPlaneY );
+
+ gp_Pnt aDragPnt = aPickPoint;
+ gp_Vec aDragDir = gp_Vec( 0.0, 0.0, 0.0 );
+ GeomAPI_IntCS aFindCross( aDragLine, aDragPln );
+ if ( aFindCross.IsDone() && aFindCross.NbPoints() != 0 )
+ {
+ aDragPnt = aFindCross.Point( 1 );
+ }
+
+ if ( aDragPnt.Distance( aPickPoint ) > Precision::Confusion() )
+ {
+ aDragDir = gp_Vec( aPickPoint, aDragPnt );
+ }
+
+ aMomentArm2 = anArmLength2 * ( 1.0 - Abs( aDragDir.Normalized() * anArm.Normalized() ) );
+ }
+
+ // choose the best plane for dragging
+ if ( aMomentArm1 >= aMomentArm2 )
+ {
+ gp_Vec aMousePlnN = gp_Vec( aPlaneX );
+
+ myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
+
+ Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
+ gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
+ ? aPlaneCenter.Translated( aMousePlnN * aDistance2Center )
+ : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
+
+ myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
+ }
+ else
+ {
+ gp_Vec aMousePlnN = gp_Vec( aPlaneY );
+
+ myMouseDragPln = gp_Pln( aPickPoint, aMousePlnN );
+
+ Standard_Real aDistance2Center = myMouseDragPln.Distance( aPlaneCenter );
+ gp_Pnt aCenterOnMousePln = aMousePlnN * gp_Vec( aPickPoint, aPlaneCenter ) < 0.0
+ ? aPlaneCenter.Translated( aMousePlnN * aDistance2Center )
+ : aPlaneCenter.Translated( aMousePlnN * -aDistance2Center );
+
+ myRotationAxis = gp_Ax1( myRotationCenter, aMousePlnN );
+ }
+
+ myPlaneReferenceCS = gp_Ax3( aPlaneCenter, aPlaneN, aPlaneX );
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*!
+ \brief Performs dragging operation on the passed interactive plane.
+ \param theDragPos [in] the position of mouse dragging.
+ \param theDragOp [in] the drag operation to start.
+ \param thePlane [in] the operated plane.
+ \param theView [in] the view.
+*/
+void OCCViewer_ClipPlaneInteractor::performDragging( const QPoint& theDragPos,
+ const DragOperation theDragOp,
+ const Handle(AIS_Plane)& thePlane,
+ const Handle(V3d_View)& theView )
+{
+ Standard_Real P[3], D[3];
+ theView->ConvertWithProj( theDragPos.x(), theDragPos.y(), P[0], P[1], P[2], D[0], D[1], D[2] );
+ gp_Lin aProjection = gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) );
+
+ // get point on the plane
+ Handle(Geom_Line) aCrossLine = new Geom_Line( aProjection );
+ Handle(Geom_Plane) aCrossPlane = new Geom_Plane( myMouseDragPln );
+
+ GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane );
+ if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 )
+ {
+ return;
+ }
+
+ gp_Pnt aDragPoint = aFindCross.Point( 1 );
+ gp_Pnt aPlaneCenter = myPlaneReferenceCS.Location();
+ gp_Vec aPlaneN = myPlaneReferenceCS.Direction();
+ gp_Vec aPlaneX = myPlaneReferenceCS.XDirection();
+ gp_Pln aPlanePln = gp_Pln( aPlaneCenter, aPlaneN );
+
+ switch ( theDragOp )
+ {
+ // sliding the plane along its normal
+ case DragOperation_Slide:
+ {
+ Standard_Real aTranslation =
+ gp_Vec( aPlaneCenter, aDragPoint ) * gp_Vec( aPlaneN ) > 0.0
+ ? aPlanePln.Distance( aDragPoint )
+ : -aPlanePln.Distance( aDragPoint );
+
+ gp_Pnt aNewCenter = aPlaneCenter.Translated( aPlaneN * aTranslation );
+
+ myPlaneReferenceCS = gp_Ax3( aNewCenter, aPlaneN, aPlaneX );
+
+ adjustBounds( myPlaneReferenceCS, myMinMax );
+
+ thePlane->SetComponent( new Geom_Plane( myPlaneReferenceCS ) );
+ thePlane->SetCenter( myPlaneReferenceCS.Location() );
+ thePlane->SetToUpdate();
+ thePlane->UpdateSelection();
+
+ myViewer->getAISContext()->Update( thePlane );
+ }
+ break;
+
+ case DragOperation_Rotate:
+ {
+ // project the dragging point on rotated plane
+ gp_Dir aRotAxis = myRotationAxis.Direction();
+ gp_Pln aDragAtCenterPln = gp_Pln( myRotationCenter, aRotAxis );
+ gp_Pnt aDragAtCenterPnt = gp_Vec( myRotationCenter, aDragPoint ) * gp_Vec( aRotAxis ) < 0.0
+ ? aDragPoint.Translated( gp_Vec( aRotAxis ) * aDragAtCenterPln.Distance( aDragPoint ) )
+ : aDragPoint.Translated( gp_Vec( aRotAxis ) * -aDragAtCenterPln.Distance( aDragPoint ) );
+
+ gp_Pnt aDragOnPlanePnt = gp_Vec( aPlaneCenter, aDragAtCenterPnt ) * gp_Vec( aPlaneN ) < 0.0
+ ? aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) * aPlanePln.Distance( aDragAtCenterPnt ) )
+ : aDragAtCenterPnt.Translated( gp_Vec( aPlaneN ) * -aPlanePln.Distance( aDragAtCenterPnt ) );
+
+ gp_Vec aDragPointVector( myRotationCenter, aDragAtCenterPnt );
+ gp_Vec aProjPointVector( myRotationCenter, aDragOnPlanePnt );
+
+ // check for rotation tolerance
+ if ( aDragPointVector.Magnitude() < 0.01 || aProjPointVector.Magnitude() < 0.01 )
+ {
+ return;
+ }
+
+ Standard_Real aTurnAngle = aProjPointVector.AngleWithRef( aDragPointVector, myRotationAxis.Direction() );
+
+ gp_Trsf aRotationTrsf;
+ aRotationTrsf.SetRotation( myRotationAxis, aTurnAngle );
+ myPlaneReferenceCS.Transform( aRotationTrsf );
+
+ adjustBounds( myPlaneReferenceCS, myMinMax );
+
+ gp_Ax3 aPlaneCS( myPlaneReferenceCS.Location(), myPlaneReferenceCS.Direction() );
+
+ thePlane->SetComponent( new Geom_Plane( aPlaneCS ) );
+ thePlane->SetCenter( myPlaneReferenceCS.Location() );
+ thePlane->SetToUpdate();
+ thePlane->UpdateSelection();
+
+ myViewer->getAISContext()->Update( thePlane );
+ }
+ break;
+ }
+}
+
+/*!
+ \brief Adjusts min-max bounds of the plane.
+ \param thePlane [in/out] the plane.
+ \param theMinMax [in] the min max bounds
+*/
+void OCCViewer_ClipPlaneInteractor::adjustBounds( gp_Ax3& thePlane, const Bnd_Box& theMinMax )
+{
+ gp_Trsf aRelativeTransform;
+ aRelativeTransform.SetTransformation( gp_Ax3(), thePlane );
+ Bnd_Box aRelativeBounds = theMinMax.Transformed( aRelativeTransform );
+
+ Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
+ aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ if ( aZmax < 0.0 ) // out in positive direction
+ {
+ thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmax );
+ }
+ else if ( aZmin > 0.0 ) // out in negative direction
+ {
+ thePlane.Translate( gp_Vec( thePlane.Direction() ) * aZmin );
+ }
+}
+
+/*!
+ \brief Handle mouse press events. Starts interaction with detected plane.
+ \param theEvent [in] the user event.
+ \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mousePress( QMouseEvent* theEvent,
+ OCCViewer_ViewPort3d* theViewPort )
+{
+ if ( theEvent->button() != Qt::LeftButton )
+ {
+ return false;
+ }
+
+ Handle(V3d_View) aView3D = theViewPort->getView();
+
+ Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext();
+
+ // check detection of plane
+ anAISContext->MoveTo( theEvent->x(), theEvent->y(), aView3D );
+
+ if ( !anAISContext->HasDetected() )
+ {
+ return false;
+ }
+
+ // check that there is only one detected entity
+ anAISContext->InitDetected();
+
+ Handle(AIS_Plane) aPlane;
+ Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner();
+ if ( !aDetectedOwner.IsNull() )
+ {
+ aPlane = Handle(AIS_Plane)::DownCast( aDetectedOwner->Selectable() );
+ }
+
+ if ( aPlane.IsNull() )
+ {
+ aPlane = Handle(AIS_Plane)::DownCast( anAISContext->DetectedInteractive() );
+ }
+
+ myIsClickable = isClickable( aPlane );
+
+ // process mouse click on the object
+ if ( myIsClickable );
+ {
+ myViewer->getAISContext()->SetSelected( aPlane );
+ emit planeClicked( aPlane );
+ }
+
+ myIsDraggable = isDraggable( aPlane );
+
+ if ( !myIsClickable && !myIsDraggable )
+ {
+ return false;
+ }
+
+ myPickPos = theEvent->pos();
+ myInteractedPlane = aPlane;
+
+ return true;
+}
+
+/*!
+ \brief Handle mouse move events. Performs dragging if interaction is in progress.
+ \param theEvent [in] the user event.
+ \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mouseMove( QMouseEvent* theEvent,
+ OCCViewer_ViewPort3d* theViewPort )
+{
+ if ( !isPerforming() )
+ {
+ return false;
+ }
+
+ // no dragging operation can be performed...
+ if ( !myIsDraggable )
+ {
+ return true;
+ }
+
+ Handle(V3d_View) aView3D = theViewPort->getView();
+
+ myDragPos = theEvent->pos();
+
+ // checking whether it is possible to start dragging operation
+ if ( myPerformingOp == DragOperation_Undef )
+ {
+ int aDx = myDragPos.x() - myPickPos.x();
+ int aDy = myDragPos.y() - myPickPos.y();
+ if ( ( aDx * aDx + aDy * aDy ) < 16 )
+ {
+ return true;
+ }
+
+ DragOperation aDragOp =
+ theEvent->modifiers().testFlag(Qt::ControlModifier)
+ ? DragOperation_Rotate
+ : DragOperation_Slide;
+
+ myIsDraggable = startDragging( myPickPos, myDragPos, aDragOp, myInteractedPlane, aView3D );
+
+ if ( !myIsDraggable )
+ {
+ return true;
+ }
+
+ myPerformingOp = aDragOp;
+ }
+
+ // performing dragging operation
+ performDragging( myDragPos, myPerformingOp, myInteractedPlane, aView3D );
+
+ emit planeDragged( myInteractedPlane );
+
+ return true;
+}
+
+/*!
+ \brief Handle mouse release events. Stops interaction.
+ \param theEvent [in] the user event.
+ \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mouseRelease( QMouseEvent* theEvent,
+ OCCViewer_ViewPort3d* theViewPort )
+{
+ if ( !isPerforming() )
+ {
+ return false;
+ }
+
+ myMouseDragPln = gp_Pln();
+ myPerformingOp = DragOperation_Undef;
+ myPickPos = QPoint();
+ myDragPos = QPoint();
+ myInteractedPlane = NULL;
+ myIsDraggable = false;
+ myIsClickable = false;
+ return true;
+}
+
+/*!
+ \brief Handle mouse double clicking events events. Stops the event propagation if
+ interaction with plane is in progress.
+ \param theEvent [in] the user event.
+ \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::mouseDoubleClick( QMouseEvent* theEvent,
+ OCCViewer_ViewPort3d* theViewPort )
+{
+ return isPerforming();
+}
+
+/*!
+ \brief Handle key pressing events. Stops the event propagation if
+ interaction with plane is in progress.
+ \param theEvent [in] the user event.
+ \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::keyPress( QKeyEvent* theEvent,
+ OCCViewer_ViewPort3d* theViewPort )
+{
+ // react to pressing & releasing ctrl key modifier
+ if ( !isPerforming() )
+ {
+ return false;
+ }
+
+ DragOperation aDragOp =
+ theEvent->modifiers().testFlag(Qt::ControlModifier)
+ ? DragOperation_Rotate
+ : DragOperation_Slide;
+
+ if ( aDragOp != myPerformingOp )
+ {
+ myPerformingOp = DragOperation_Undef;
+ myIsDraggable = isDraggable( myInteractedPlane );
+ myPickPos = theViewPort->mapFromGlobal( QCursor::pos() );
+ }
+
+ return true;
+}
+
+/*!
+ \brief Handle key releasing events. Stops the event propagation if
+ interaction with plane is in progress.
+ \param theEvent [in] the user event.
+ \param theViewPort [in] the viewport.
+*/
+bool OCCViewer_ClipPlaneInteractor::keyRelease( QKeyEvent* theEvent,
+ OCCViewer_ViewPort3d* theViewPort )
+{
+ // react to pressing & releasing ctrl key modifier
+ if ( !isPerforming() )
+ {
+ return false;
+ }
+
+ DragOperation aDragOp =
+ theEvent->modifiers().testFlag(Qt::ControlModifier)
+ ? DragOperation_Rotate
+ : DragOperation_Slide;
+
+ if ( aDragOp != myPerformingOp )
+ {
+ myPerformingOp = DragOperation_Undef;
+ myIsDraggable = isDraggable( myInteractedPlane );
+ myPickPos = theViewPort->mapFromGlobal( QCursor::pos() );
+ }
+
+ return true;
+}
--- /dev/null
+// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef OCCVIEWER_CLIPPLANEINTERACTOR_H
+#define OCCVIEWER_CLIPPLANEINTERACTOR_H
+
+#include "OCCViewer_ViewportInputFilter.h"
+
+#include <AIS_Plane.hxx>
+#include <Bnd_Box.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Ax3.hxx>
+
+#include <QPoint>
+
+#include <vector>
+
+class Handle(V3d_View);
+
+/*!
+ \class OCCViewer_ClipPlaneInteractor.
+ \brief The class provides mouse dragging operations with AIS_Plane:
+ 1) Sliding plane by dragging it with point
+ 2) Rotating plane around one or both of the rotation axes by
+ dragging its point with "ctrl" key pressed.
+*/
+class OCCViewer_ClipPlaneInteractor : public OCCViewer_ViewportInputFilter
+{
+ Q_OBJECT
+
+public:
+ typedef std::vector<Handle(AIS_Plane)> SeqOfPlanes;
+
+ // Performing interactive operation.
+ // - Slide: The picked point on plane is dragged along the normal of the plane.
+ // - Rotate: The picked point on plane is dragged around one of the specified rotation
+ // axes ("x", "y" axes of the plane coordinate system, or two orthogonal arbitrary
+ // specified ones). When starting the rotation a corresponding axis is
+ // choosen depending on the direction of dragging. The axis is selected in
+ // the following way: a virtual "arm" is constructed from center of
+ // rotation to picking point. The dragging directions are constructed for
+ // both of the rotation axes, then the direction which is "easiest to
+ // turn" is selected (e.g. the "arm" projection is largest for that axis,
+ // the direction of dragging is closer to orthogonal one for the axis).
+ enum DragOperation
+ {
+ DragOperation_Undef,
+ DragOperation_Slide,
+ DragOperation_Rotate
+ };
+
+public:
+ OCCViewer_ClipPlaneInteractor( OCCViewer_ViewManager*, QObject* theParent );
+
+ const SeqOfPlanes& planes() const;
+ void setPlanes( const SeqOfPlanes& );
+ void setRotationCenter( const gp_Pnt& );
+ void setMinMax( const Bnd_Box& );
+ virtual void setEnabled( const bool );
+
+signals:
+ void planeClicked( const Handle_AIS_Plane& thePlane );
+ void planeDragged( const Handle_AIS_Plane& thePlane );
+
+protected:
+ bool isClickable( const Handle(AIS_Plane)& thePlane );
+ bool isDraggable( const Handle(AIS_Plane)& thePlane );
+ bool isPerforming() const;
+ bool startDragging( const QPoint& thePickPos,
+ const QPoint& theDragPos,
+ const DragOperation theOperation,
+ const Handle(AIS_Plane)& thePlane,
+ const Handle(V3d_View)& theView );
+ void performDragging( const QPoint& theDragPos,
+ const DragOperation theOperation,
+ const Handle(AIS_Plane)& thePlane,
+ const Handle(V3d_View)& theView );
+ void adjustBounds( gp_Ax3&, const Bnd_Box& );
+
+protected:
+ virtual bool mouseMove( QMouseEvent*, OCCViewer_ViewPort3d* );
+ virtual bool mousePress( QMouseEvent*, OCCViewer_ViewPort3d* );
+ virtual bool mouseRelease( QMouseEvent*, OCCViewer_ViewPort3d* );
+ virtual bool mouseDoubleClick( QMouseEvent*, OCCViewer_ViewPort3d* );
+ virtual bool keyPress( QKeyEvent*, OCCViewer_ViewPort3d* );
+ virtual bool keyRelease( QKeyEvent*, OCCViewer_ViewPort3d* );
+
+protected:
+
+ gp_Ax3 myPlaneReferenceCS;
+ gp_Ax1 myRotationAxis;
+ gp_Pln myMouseDragPln;
+ QPoint myDragPos;
+ QPoint myPickPos;
+ DragOperation myPerformingOp;
+ gp_Pnt myRotationCenter;
+ Bnd_Box myMinMax;
+ Handle(AIS_Plane) myInteractedPlane;
+ SeqOfPlanes myPlanes;
+ bool myIsDraggable;
+ bool myIsClickable;
+};
+
+#endif
#include "OCCViewer_ViewWindow.h"
#include "OCCViewer_ViewPort3d.h"
#include "OCCViewer_ViewModel.h"
+#include "OCCViewer_ViewManager.h"
+#include "OCCViewer_ClipPlaneInteractor.h"
#include <V3d_View.hxx>
#include <Visual3d_View.hxx>
/*!
Compute relative clipping plane in absolute coordinates
*/
-void RelativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) ic, double theDefaultSize )
+void relativePlaneToAbsolute (OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) ic, double theDefaultSize )
{
double aNormal[3];
double aDir[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };
aNormal[i] /= den;
}
}
- Cross( aNormal, aDir[1], aDir[0] );
}
double anOrigin[3];
thePlane.Dz = aNormal[2];
}
+/*!
+ \brief Converts absolute plane definition to relative system.
+ \param thePlane [in/out] the plane to convert.
+ \param theIC [in] the interactive context.
+ \param theDefaultSize [in] the default trihedron size.
+ */
+void absolutePlaneToRelative( OCCViewer_ClipPlane& thePlane, Handle(AIS_InteractiveContext) theIC, double theDefaultSize )
+{
+ gp_Pnt aPlaneP( thePlane.X, thePlane.Y, thePlane.Z );
+ gp_Dir aPlaneN( thePlane.Dx, thePlane.Dy, thePlane.Dz );
+
+ double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+
+ getMinMaxFromContext( theIC, theDefaultSize, aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ Bnd_Box aMinMax;
+ aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ gp_Trsf aRelativeTransform;
+ aRelativeTransform.SetTransformation( gp_Ax3(), gp_Ax3( aPlaneP, aPlaneN ) );
+ Bnd_Box aRelativeBounds = aMinMax.Transformed( aRelativeTransform );
+
+ aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ double aLength = aZmax - aZmin;
+ double aDistance = aZmax;
+
+ double aRelativeDistance = aLength > 0.01 ? aDistance / aLength : 0.0;
+ aRelativeDistance = qMin( aRelativeDistance, aLength );
+ aRelativeDistance = qMax( aRelativeDistance, 0.0 );
+ thePlane.RelativeMode.Distance = aRelativeDistance;
+
+ const gp_Dir& aDX = gp::DX();
+ const gp_Dir& aDY = gp::DY();
+ const gp_Dir& aDZ = gp::DZ();
+ double anAng1 = 0.0;
+ double anAng2 = 0.0;
+ switch ( thePlane.RelativeMode.Orientation )
+ {
+ case 0:
+ {
+ if ( aDY.IsEqual( aPlaneN, Precision::Angular() ) )
+ {
+ anAng1 = 0.0;
+ anAng2 = 0.0;
+ break;
+ }
+
+ gp_Dir aDir1 = aPlaneN ^ aDX;
+ gp_Dir aDir2 = aDY ^ aPlaneN;
+ gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDY ^ aPlaneN );
+
+ if ( aDir1 * aRightHand.YDirection() < 0.0 )
+ {
+ aDir1.Reverse();
+ }
+ if ( aDir2 * aRightHand.XDirection() < 0.0 )
+ {
+ aDir2.Reverse();
+ }
+
+ anAng1 = aDY.AngleWithRef( aDir1, aDX );
+ anAng2 = aDX.AngleWithRef( aDir2, -aDY );
+ break;
+ }
+ case 1:
+ {
+ if ( aDZ.IsEqual( aPlaneN, Precision::Angular() ) )
+ {
+ anAng1 = 0.0;
+ anAng2 = 0.0;
+ break;
+ }
+
+ gp_Dir aDir1 = aPlaneN ^ aDY;
+ gp_Dir aDir2 = aDZ ^ aPlaneN;
+ gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDZ ^ aPlaneN );
+
+ if ( aDir1 * aRightHand.YDirection() < 0.0 )
+ {
+ aDir1.Reverse();
+ }
+ if ( aDir2 * aRightHand.XDirection() < 0.0 )
+ {
+ aDir2.Reverse();
+ }
+
+ anAng1 = aDZ.AngleWithRef( aDir1, aDY );
+ anAng2 = aDY.AngleWithRef( aDir2, -aDZ );
+ break;
+ }
+ case 2:
+ {
+ if ( aDX.IsEqual( aPlaneN, Precision::Angular() ) )
+ {
+ anAng1 = 0.0;
+ anAng2 = 0.0;
+ break;
+ }
+
+ gp_Dir aDir1 = aPlaneN ^ aDZ;
+ gp_Dir aDir2 = aDX ^ aPlaneN;
+ gp_Ax3 aRightHand( gp::Origin(), aPlaneN, aDX ^ aPlaneN );
+
+ if ( aDir1 * aRightHand.YDirection() < 0.0 )
+ {
+ aDir1.Reverse();
+ }
+ if ( aDir2 * aRightHand.XDirection() < 0.0 )
+ {
+ aDir2.Reverse();
+ }
+
+ anAng1 = aDX.AngleWithRef( aDir1, aDZ );
+ anAng2 = aDZ.AngleWithRef( aDir2, -aDX );
+ break;
+ }
+ }
+
+ thePlane.RelativeMode.Rotation1 = anAng1 * ( 180.0 / M_PI );
+ thePlane.RelativeMode.Rotation2 = anAng2 * ( 180.0 / M_PI );
+}
+
/*!
Compute clipping plane size base point and normal
*/
SliderDistance = new QSlider( Qt::Horizontal, GroupParameters );
SliderDistance->setObjectName( "SliderDistance" );
+ SliderDistance->setFocusPolicy( Qt::NoFocus );
SliderDistance->setMinimumSize( 300, 0 );
SliderDistance->setMinimum( 0 );
SliderDistance->setMaximum( 100 );
SliderRotation1 = new QSlider( Qt::Horizontal, GroupParameters );
SliderRotation1->setObjectName( "SliderRotation1" );
+ SliderRotation1->setFocusPolicy( Qt::NoFocus );
SliderRotation1->setMinimumSize( 300, 0 );
SliderRotation1->setMinimum( -180 );
SliderRotation1->setMaximum( 180 );
SliderRotation2 = new QSlider( Qt::Horizontal, GroupParameters );
SliderRotation2->setObjectName( "SliderRotation2" );
+ SliderRotation2->setFocusPolicy( Qt::NoFocus );
SliderRotation2->setMinimumSize( 300, 0 );
SliderRotation2->setMinimum( -180 );
SliderRotation2->setMaximum( 180 );
myBusy = false;
myIsSelectPlane = false;
myIsPlaneCreation = false;
+ myIsUpdatingControls = false;
myModel = model;
myModel->getViewer3d()->InitActiveViews();
+ OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) myModel->getViewManager();
+ myInteractor = new OCCViewer_ClipPlaneInteractor( aViewMgr, this );
+ connect( myInteractor, SIGNAL( planeClicked( const Handle_AIS_Plane& ), ), SLOT( onPlaneClicked( const Handle_AIS_Plane& ) ) );
+ connect( myInteractor, SIGNAL( planeDragged( const Handle_AIS_Plane& ), ), SLOT( onPlaneDragged( const Handle_AIS_Plane& ) ) );
+
myLocalPlanes = myModel->getClipPlanes();
synchronize();
}
int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
for ( int i=0; i < clipPlanesCount(); i++ ) {
- OCCViewer_ClipPlane& aClipPlane = getClipPlane(i);
+ OCCViewer_ClipPlane& aClipPlane = getClipPlane(i);
if ( aClipPlane.IsOn ) {
Handle(AIS_Plane) myPreviewPlane;
double aSize;
gp_Pnt aBasePnt;
gp_Dir aNormal;
clipPlaneParams(aClipPlane, ic, aSize, aBasePnt, aNormal, myModel->trihedronSize());
- myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
+ myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
+ myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
myPreviewPlane->SetSize( aSize, aSize );
- ic->Display( myPreviewPlane, 1, -1, false );
ic->SetWidth( myPreviewPlane, 10, false );
ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
ic->SetTransparency( myPreviewPlane, 0.5, false );
Quantity_Color c = (aCurPlaneIndex == i) ? Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ) : Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB );
ic->SetColor( myPreviewPlane, c , false );
+ ic->Display( myPreviewPlane, 1, 0, false );
myPreviewPlaneVector.push_back( myPreviewPlane );
}
}
myModel->update();
+
+ double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+ getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5,
+ (aYmax + aYmin) * 0.5,
+ (aZmax + aZmin) * 0.5 );
+ Bnd_Box aMinMax;
+ aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ myInteractor->setPlanes( myPreviewPlaneVector );
+ myInteractor->setRotationCenter( aRotationCenter );
+ myInteractor->setMinMax( aMinMax );
+ myInteractor->setEnabled( true );
}
void OCCViewer_ClippingDlg::updatePreview() {
}
myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
if(myPreviewPlane.IsNull()) {
- //Plane was not created
- myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
+ //Plane was not created
+ myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ), aBasePnt );
+ myPreviewPlane->SetTypeOfSensitivity( Select3D_TOS_INTERIOR );
myPreviewPlane->SetSize( aSize, aSize );
- ic->Display( myPreviewPlane, 1, -1, false );
+ ic->Display( myPreviewPlane, 1, 0, false );
ic->SetWidth( myPreviewPlane, 10, false );
ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
ic->SetTransparency( myPreviewPlane, 0.5, false );
myPreviewPlaneVector[aCurPlaneIndex] = myPreviewPlane;
} else {
- myPreviewPlane->SetComponent(new Geom_Plane( aBasePnt, aNormal ));
+ myPreviewPlane->SetComponent( new Geom_Plane( aBasePnt, aNormal ) );
+ myPreviewPlane->SetCenter( aBasePnt );
myPreviewPlane->SetSize( aSize, aSize );
}
ic->SetColor( myPreviewPlane, Quantity_Color( 255. / 255., 70. / 255., 0. / 255., Quantity_TOC_RGB ), false );
+ ic->Update( myPreviewPlane, Standard_False );
} else {
if(myPreviewPlaneVector.size() > aCurPlaneIndex ) {
myPreviewPlane = myPreviewPlaneVector[aCurPlaneIndex];
for(int i = 0; i < myPreviewPlaneVector.size(); i++) {
if( i == aCurPlaneIndex ) continue;
if(!myPreviewPlaneVector[i].IsNull())
- ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
+ ic->SetColor( myPreviewPlaneVector[i], Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
}
myModel->update();
+
+ double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+ getMinMaxFromContext( ic, myModel->trihedronSize(), aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ gp_Pnt aRotationCenter( (aXmax + aXmin) * 0.5,
+ (aYmax + aYmin) * 0.5,
+ (aZmax + aZmin) * 0.5 );
+ Bnd_Box aMinMax;
+ aMinMax.Update( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+
+ myInteractor->setPlanes( myPreviewPlaneVector );
+ myInteractor->setRotationCenter( aRotationCenter );
+ myInteractor->setMinMax( aMinMax );
}
/*!
}
myPreviewPlaneVector.clear();
myModel->update();
+ myInteractor->setEnabled( false );
}
/*!
}
}
+/*!
+ Updates state of user controls.
+*/
+void OCCViewer_ClippingDlg::updateControls()
+{
+ if ( clipPlanesCount() == 0 )
+ {
+ initParam();
+ return;
+ }
+
+ int aPlaneIdx = ComboBoxPlanes->currentIndex();
+
+ OCCViewer_ClipPlane& aPlane = getClipPlane( aPlaneIdx );
+
+ if ( aPlane.PlaneMode == Absolute )
+ {
+ ModeStackedLayout->setCurrentIndex( 0 );
+ myCurrentClipPlaneMode = Absolute;
+ int anOrientation = aPlane.Orientation;
+ // Set plane parameters in the dialog
+ SpinBox_X->setValue( aPlane.X );
+ SpinBox_Y->setValue( aPlane.Y );
+ SpinBox_Z->setValue( aPlane.Z );
+ SpinBox_Dx->setValue( aPlane.Dx );
+ SpinBox_Dy->setValue( aPlane.Dy );
+ SpinBox_Dz->setValue( aPlane.Dz );
+ CBAbsoluteOrientation->setCurrentIndex( anOrientation );
+ onOrientationAbsoluteChanged( anOrientation );
+ }
+ else if( aPlane.PlaneMode == Relative )
+ {
+ ModeStackedLayout->setCurrentIndex( 1 );
+ myCurrentClipPlaneMode = Relative;
+ int anOrientation = aPlane.RelativeMode.Orientation;
+
+ // Set plane parameters in the dialog
+ QString aFmtDistance = QString::number( aPlane.RelativeMode.Distance, '.', 2 );
+ QString aFmtRotation1 = QString::number( floor( aPlane.RelativeMode.Rotation1 ) );
+ QString aFmtRotation2 = QString::number( floor( aPlane.RelativeMode.Rotation2 ) );
+ aFmtRotation1 = QString( "%1\xB0" ).arg( aFmtRotation1 );
+ aFmtRotation2 = QString( "%1\xB0" ).arg( aFmtRotation2 );
+
+ SliderDistance->setValue( aPlane.RelativeMode.Distance * 100 );
+ TLValueDistance->setText( aFmtDistance );
+ SliderRotation1->setValue( floor( aPlane.RelativeMode.Rotation1 ) );
+ TLValueRotation1->setText( aFmtRotation1 );
+ SliderRotation2->setValue( floor( aPlane.RelativeMode.Rotation2 ) );
+ TLValueRotation2->setText( aFmtRotation2 );
+ CBRelativeOrientation->setCurrentIndex( anOrientation );
+ onOrientationRelativeChanged( anOrientation );
+ }
+
+ isActivePlane->setChecked( aPlane.IsOn );
+}
+
/*!
SLOT on new button click: create a new clipping plane
*/
void OCCViewer_ClippingDlg::ClickOnNew()
{
-
OCCViewer_ClipPlane aPlane;
aPlane.PlaneMode = (ClipPlaneMode )myCurrentClipPlaneMode;
myLocalPlanes.push_back(aPlane);
*/
void OCCViewer_ClippingDlg::onValueChanged()
{
+ if ( myIsUpdatingControls )
+ {
+ return;
+ }
+
SetCurrentPlaneParam();
+
if ( myIsSelectPlane )
+ {
return;
+ }
+
updateClipping();
}
void OCCViewer_ClippingDlg::onSelectPlane ( int theIndex )
{
if ( clipPlanesCount() == 0 )
+ {
return;
+ }
- OCCViewer_ClipPlane& aClipPlane = getClipPlane (theIndex);
+ OCCViewer_ClipPlane& aClipPlane = getClipPlane( theIndex );
myIsSelectPlane = true;
- if ( aClipPlane.PlaneMode == Absolute ) {
- ModeStackedLayout->setCurrentIndex( 0 );
- myCurrentClipPlaneMode = Absolute;
- int anOrientation = aClipPlane.Orientation;
- // Set plane parameters in the dialog
- SpinBox_X->setValue( aClipPlane.X );
- SpinBox_Y->setValue( aClipPlane.Y );
- SpinBox_Z->setValue( aClipPlane.Z );
- SpinBox_Dx->setValue( aClipPlane.Dx );
- SpinBox_Dy->setValue( aClipPlane.Dy );
- SpinBox_Dz->setValue( aClipPlane.Dz );
- CBAbsoluteOrientation->setCurrentIndex( anOrientation );
- onOrientationAbsoluteChanged( anOrientation );
- }
- else if( aClipPlane.PlaneMode == Relative ) {
- ModeStackedLayout->setCurrentIndex( 1 );
- myCurrentClipPlaneMode = Relative;
- int anOrientation = aClipPlane.RelativeMode.Orientation;
- // Set plane parameters in the dialog
- SliderDistance->setValue( aClipPlane.RelativeMode.Distance*100 );
- TLValueDistance->setText( QString::number(aClipPlane.RelativeMode.Distance ) );
- SliderRotation1->setValue( aClipPlane.RelativeMode.Rotation1 );
- TLValueRotation1->setText( QString( "%1\xB0" ).arg( aClipPlane.RelativeMode.Rotation1 ) );
- SliderRotation2->setValue( aClipPlane.RelativeMode.Rotation2 );
- TLValueRotation2->setText( QString( "%1\xB0" ).arg( aClipPlane.RelativeMode.Rotation2 ) );
- CBRelativeOrientation->setCurrentIndex( anOrientation );
- onOrientationRelativeChanged( anOrientation );
- }
-
- isActivePlane->setChecked( aClipPlane.IsOn );
+ updateControls();
ComboBoxPlanes->setCurrentIndex( theIndex );
myIsSelectPlane = false;
}
int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
- OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
+ OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
- if ( aPlane.PlaneMode == Absolute ) {
+ if ( aPlane.PlaneMode == Absolute )
+ {
aPlane.Orientation = CBAbsoluteOrientation->currentIndex();
- aPlane.X = SpinBox_X->value();
- aPlane.Y = SpinBox_Y->value();
- aPlane.Z = SpinBox_Z->value();
+ aPlane.X = SpinBox_X->value();
+ aPlane.Y = SpinBox_Y->value();
+ aPlane.Z = SpinBox_Z->value();
aPlane.Dx = SpinBox_Dx->value();
aPlane.Dy = SpinBox_Dy->value();
aPlane.Dz = SpinBox_Dz->value();
+ absolutePlaneToRelative( aPlane, myModel->getAISContext(),myModel->trihedronSize() );
}
- else if( aPlane.PlaneMode == Relative ) {
+ else if( aPlane.PlaneMode == Relative )
+ {
aPlane.RelativeMode.Orientation = CBRelativeOrientation->currentIndex();
aPlane.RelativeMode.Distance = TLValueDistance->text().toDouble();
aPlane.RelativeMode.Rotation1 = TLValueRotation1->text().remove("\xB0").toInt();
aPlane.RelativeMode.Rotation2 = TLValueRotation2->text().remove("\xB0").toInt();
- RelativePlaneToAbsolute (aPlane, myModel->getAISContext(),myModel->trihedronSize() );
+ relativePlaneToAbsolute( aPlane, myModel->getAISContext(),myModel->trihedronSize() );
}
aPlane.IsOn = isActivePlane->isChecked();
}
if ( clipPlanesCount() != 0 ) {
int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
- OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
+ OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
aPlane.IsInvert = !aPlane.IsInvert;
}
updateClipping();
}
int aCurPlaneIndex = ComboBoxPlanes->currentIndex();
- OCCViewer_ClipPlane& aPlane = getClipPlane (aCurPlaneIndex);
+ OCCViewer_ClipPlane& aPlane = getClipPlane( aCurPlaneIndex );
if ( aPlane.IsInvert == true ) {
aDx = -aDx; aDy = -aDy; aDz = -aDz;
}
SpinBox_Dz->setValue( aDz );
myBusy = false;
}
- SetCurrentPlaneParam();
- updateClipping();
+
+ if ( !myIsUpdatingControls )
+ {
+ SetCurrentPlaneParam();
+ updateClipping();
+ }
}
/*!
TextLabelRotation2->setText( tr( "ROTATION_AROUND_X_Z2Y" ) );
}
- if( (QComboBox*)sender() == CBRelativeOrientation )
- SetCurrentPlaneParam();
- updateClipping();
+ if ( !myIsUpdatingControls )
+ {
+ if( (QComboBox*)sender() == CBRelativeOrientation )
+ {
+ SetCurrentPlaneParam();
+ }
+
+ updateClipping();
+ }
}
/*!
myIsSelectPlane = false;
}
+/*!
+ SLOT: Called when clip plane is clicked in viewer.
+*/
+void OCCViewer_ClippingDlg::onPlaneClicked( const Handle(AIS_Plane)& thePlane )
+{
+ for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
+ {
+ Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
+ if ( aPlane != thePlane )
+ {
+ continue;
+ }
+
+ ComboBoxPlanes->setCurrentIndex( aPlaneIt );
+
+ break;
+ }
+}
+
+/*!
+ SLOT: Called when clip plane is changed by dragging in viewer.
+*/
+void OCCViewer_ClippingDlg::onPlaneDragged( const Handle(AIS_Plane)& thePlane )
+{
+ for ( int aPlaneIt = 0; aPlaneIt < myPreviewPlaneVector.size(); aPlaneIt++ )
+ {
+ Handle(AIS_Plane)& aPlane = myPreviewPlaneVector.at( aPlaneIt );
+ if ( aPlane != thePlane )
+ {
+ continue;
+ }
+
+ OCCViewer_ClipPlane& aClipPlane = getClipPlane( aPlaneIt );
+
+ gp_Pln aPln = thePlane->Component()->Pln();
+ const gp_Pnt& aPlaneP = aPln.Location();
+ const gp_Dir& aPlaneN = aPln.Axis().Direction();
+
+ aClipPlane.X = aPlaneP.X();
+ aClipPlane.Y = aPlaneP.Y();
+ aClipPlane.Z = aPlaneP.Z();
+ aClipPlane.Dx = aPlaneN.X();
+ aClipPlane.Dy = aPlaneN.Y();
+ aClipPlane.Dz = aPlaneN.Z();
+ absolutePlaneToRelative( aClipPlane, myModel->getAISContext(), myModel->trihedronSize() );
+
+ myIsUpdatingControls = true;
+ updateControls();
+ myIsUpdatingControls = false;
+
+ if ( AutoApplyCheckBox->isChecked() )
+ {
+ onApply();
+ }
+
+ break;
+ }
+}
+
/*!
SLOT: Called when value of slider distance change
*/
onValueChanged();
}
-OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane (int theIndex) {
- return myLocalPlanes[theIndex];
+OCCViewer_ClipPlane& OCCViewer_ClippingDlg::getClipPlane( int theIdx )
+{
+ return myLocalPlanes[theIdx];
}
-int OCCViewer_ClippingDlg::clipPlanesCount() {
+int OCCViewer_ClippingDlg::clipPlanesCount()
+{
return myLocalPlanes.size();
}
class OCCViewer_Viewer;
class OCCViewer_ViewWindow;
+class OCCViewer_ClipPlaneInteractor;
/*!
\class OCCViewer_ClippingDlg
void updatePreview();
bool isValid();
void updateClipping();
+ void updateControls();
- OCCViewer_ClipPlane& getClipPlane (int theIndex);
+ OCCViewer_ClipPlane& getClipPlane( int );
int clipPlanesCount();
QComboBox* ComboBoxPlanes;
std::vector<Handle(AIS_Plane)> myPreviewPlaneVector;
bool myIsSelectPlane;
+ bool myIsUpdatingControls;
bool myBusy;
bool myIsPlaneCreation;
ClipPlanesList myLocalPlanes;
-
+
+ OCCViewer_ClipPlaneInteractor* myInteractor;
+
public slots:
void onApply();
void onReset();
void onInvert();
void onOrientationAbsoluteChanged( int );
- void onOrientationRelativeChanged (int);
+ void onOrientationRelativeChanged( int );
void onPreview( bool on );
void onAutoApply(bool);
void SliderDistanceHasMoved(int);
void SliderRotation1HasMoved(int);
void SliderRotation2HasMoved(int);
+
+ void onPlaneClicked( const Handle_AIS_Plane& thePlane );
+ void onPlaneDragged( const Handle_AIS_Plane& thePlane );
};
#endif // OCCVIEWER_CLIPPINGDLG_H
--- /dev/null
+// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "OCCViewer_ViewportInputFilter.h"
+#include "OCCViewer_ViewManager.h"
+#include "OCCViewer_ViewModel.h"
+#include "OCCViewer_ViewWindow.h"
+#include "OCCViewer_ViewPort3d.h"
+
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+/*!
+ \brief Constructor.
+ \param theVM [in] the view manager to embed the filter into.
+ \param theParent [in] the parent object.
+*/
+OCCViewer_ViewportInputFilter::OCCViewer_ViewportInputFilter( OCCViewer_ViewManager* theVM,
+ QObject* theParent )
+: QObject( theParent ),
+ myVM( theVM )
+{
+}
+
+/*!
+ \brief Destructor.
+*/
+OCCViewer_ViewportInputFilter::~OCCViewer_ViewportInputFilter()
+{
+ setEnabled( false );
+}
+
+/*!
+ \brief Enables or disables event processing within the viewer.
+*/
+void OCCViewer_ViewportInputFilter::setEnabled(const bool theIsEnabled)
+{
+ if ( theIsEnabled == myIsEnabled )
+ {
+ return;
+ }
+
+ if ( theIsEnabled )
+ {
+ // install event filtering on viewer windows
+ myViewer = (OCCViewer_Viewer*) myVM->getViewModel();
+ if ( !myVM || !myViewer )
+ {
+ return;
+ }
+
+ connect( myVM, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), SLOT( onViewCreated( SUIT_ViewWindow* ) ) );
+ connect( myVM, SIGNAL( deleteView ( SUIT_ViewWindow* ) ), SLOT( onViewRemoved( SUIT_ViewWindow* ) ) );
+
+ QVector<SUIT_ViewWindow*> aViews = myVM->getViews();
+ QVector<SUIT_ViewWindow*>::iterator aViewIt = aViews.begin();
+ for ( ; aViewIt != aViews.end(); ++aViewIt )
+ {
+ connectView( *aViewIt );
+ }
+ }
+ else
+ {
+ // remove event filtering from viewer windows
+ QVector<SUIT_ViewWindow*> aViews = myVM->getViews();
+ QVector<SUIT_ViewWindow*>::iterator aViewIt = aViews.begin();
+ for ( ; aViewIt != aViews.end(); ++aViewIt )
+ {
+ disconnectView( *aViewIt );
+ }
+ }
+
+ myIsEnabled = theIsEnabled;
+}
+
+/*!
+ \brief Base-level implementation of event filtering.
+ Routes user input events to associated implementation methods.
+ \param theObject [in] the filtered object.
+ \param theEvent [in] the incoming event.
+*/
+bool OCCViewer_ViewportInputFilter::eventFilter( QObject* theObject, QEvent* theEvent )
+{
+ OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*) theObject;
+
+ if ( !aViewPort )
+ {
+ return false;
+ }
+
+ switch ( theEvent->type() )
+ {
+ case QEvent::MouseMove : return mouseMove( (QMouseEvent*)theEvent, aViewPort );
+ case QEvent::MouseButtonPress : return mousePress( (QMouseEvent*)theEvent, aViewPort );
+ case QEvent::MouseButtonRelease : return mouseRelease( (QMouseEvent*)theEvent, aViewPort );
+ case QEvent::MouseButtonDblClick : return mouseDoubleClick( (QMouseEvent*)theEvent, aViewPort );
+ case QEvent::KeyPress : return keyPress( (QKeyEvent*)theEvent, aViewPort );
+ case QEvent::KeyRelease : return keyRelease( (QKeyEvent*)theEvent, aViewPort );
+ default :
+ return false;
+ }
+}
+
+/*!
+ \brief Connects view to event processing.
+ \param theView [in] the view to connect.
+*/
+void OCCViewer_ViewportInputFilter::connectView( SUIT_ViewWindow* theView )
+{
+ ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this );
+}
+
+/*!
+ \brief Disconnects view to event processing.
+ \param theView [in] the view to disconnect.
+*/
+void OCCViewer_ViewportInputFilter::disconnectView( SUIT_ViewWindow* theView )
+{
+ ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this );
+}
+
+/*!
+ \brief Connects newly created within viewer to event processing.
+ \param theView [in] the view to connect.
+*/
+void OCCViewer_ViewportInputFilter::onViewCreated( SUIT_ViewWindow* theView )
+{
+ connectView( theView );
+}
+
+/*!
+ \brief Disconnects view being removed from viewer.
+ \param theView [in] the view to disconnect.
+*/
+void OCCViewer_ViewportInputFilter::onViewRemoved( SUIT_ViewWindow* theView )
+{
+ disconnectView( theView );
+}
--- /dev/null
+// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef OCCVIEWER_VIEWPORTINPUTFILTER_H
+#define OCCVIEWER_VIEWPORTINPUTFILTER_H
+
+#include <QObject>
+
+class OCCViewer_ViewManager;
+class OCCViewer_ViewPort3d;
+class OCCViewer_Viewer;
+class SUIT_ViewWindow;
+class QMouseEvent;
+class QKeyEvent;
+
+/*!
+ \class OCCViewer_ViewportInputFilter.
+ \brief The user input filter of OCC viewports. The class can be used
+ to introduce custom interactive operations in OCC viewer,
+ e.g. manipulating IO. The filter receives events in priority
+ to the viewport itself and can bypass some events if it provides
+ custom handling.
+
+ This class is abstract and required implementation of custom reaction
+ on hooked viewport events. The role of the code behind this class
+ is to properly embed the event filter into OCC viewer's structure.
+*/
+class OCCViewer_ViewportInputFilter : public QObject
+{
+ Q_OBJECT
+
+public:
+ OCCViewer_ViewportInputFilter( OCCViewer_ViewManager*, QObject* );
+ ~OCCViewer_ViewportInputFilter();
+
+public:
+ virtual void setEnabled( const bool );
+
+protected:
+ virtual bool mouseMove( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+ virtual bool mousePress( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+ virtual bool mouseRelease( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+ virtual bool mouseDoubleClick( QMouseEvent*, OCCViewer_ViewPort3d* ) = 0;
+ virtual bool keyPress( QKeyEvent*, OCCViewer_ViewPort3d* ) = 0;
+ virtual bool keyRelease( QKeyEvent*, OCCViewer_ViewPort3d* ) = 0;
+
+protected:
+ void connectView( SUIT_ViewWindow* );
+ void disconnectView( SUIT_ViewWindow* );
+
+protected:
+ bool eventFilter( QObject*, QEvent* );
+
+protected slots:
+ void onViewCreated( SUIT_ViewWindow* );
+ void onViewRemoved( SUIT_ViewWindow* );
+
+protected:
+ OCCViewer_ViewManager* myVM;
+ OCCViewer_Viewer* myViewer;
+ bool myIsEnabled;
+};
+
+#endif