+/*!
+ Get distance for cutting plane in relative mode
+*/
+double SMESHGUI_ClippingDlg::getDistance() const
+{
+ return SpinSliderDistance->value();
+}
+
+/*!
+ Set distance of cutting plane in relative mode
+*/
+void SMESHGUI_ClippingDlg::setDistance( const double theDistance )
+{
+ SpinSliderDistance->setValue( theDistance );
+}
+
+/*!
+ Get rotation1 for cutting plane in relative mode
+*/
+double SMESHGUI_ClippingDlg::getRotation1() const
+{
+ return SpinSliderRotation1->value();
+}
+
+/*!
+ Get rotation2 for cutting plane in relative mode
+*/
+double SMESHGUI_ClippingDlg::getRotation2() const
+{
+ return SpinSliderRotation2->value();
+}
+
+/*!
+ Set angles of clipping plane in relative mode
+*/
+void SMESHGUI_ClippingDlg::setRotation (const double theRot1, const double theRot2)
+{
+ SpinSliderRotation1->setValue( int(floor(theRot1)) );
+ SpinSliderRotation2->setValue( int(floor(theRot2)) );
+}
+
+/*!
+ Set coordinates of origin point in dialog box
+*/
+void SMESHGUI_ClippingDlg::setOrigin( double theVal[3] )
+{
+ int anOrientation = CBAbsoluteOrientation->currentIndex();
+ if( anOrientation == 0 || anOrientation == 2 )
+ SpinBox_X->setValue( theVal[0] );
+ if( anOrientation == 0 || anOrientation == 3 )
+ SpinBox_Y->setValue( theVal[1] );
+ if( anOrientation == 0 || anOrientation == 1 )
+ SpinBox_Z->setValue( theVal[2] );
+}
+
+/*!
+ Set coordinates of normal vector in dialog box
+*/
+void SMESHGUI_ClippingDlg::setDirection( double theVal[3] )
+{
+ int anOrientation = CBAbsoluteOrientation->currentIndex();
+ if( anOrientation == 0 ) {
+ SpinBox_Dx->setValue( theVal[0] );
+ SpinBox_Dy->setValue( theVal[1] );
+ SpinBox_Dz->setValue( theVal[2] );
+ }
+}
+
+/*!
+ Create a new widget for preview clipping plane
+*/
+vtkImplicitPlaneWidget* SMESHGUI_ClippingDlg::createPreviewWidget()
+{
+ vtkImplicitPlaneWidget* aPlaneWgt = vtkImplicitPlaneWidget::New();
+
+ aPlaneWgt->SetInteractor( myViewWindow->getInteractor() );
+ aPlaneWgt->SetPlaceFactor( SIZEFACTOR );
+ aPlaneWgt->ScaleEnabledOff();
+ aPlaneWgt->SetOrigin( 0, 0, 0 );
+ aPlaneWgt->SetNormal( -1, -1, -1 );
+ aPlaneWgt->Off();
+
+ double anRGB[3];
+ SMESH::GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) );
+
+ aPlaneWgt->GetPlaneProperty()->SetColor( anRGB[0],anRGB[1],anRGB[2] );
+ aPlaneWgt->GetPlaneProperty()->SetOpacity( 0.2 );;
+
+ aPlaneWgt->GetSelectedPlaneProperty()->SetColor( anRGB[0],anRGB[1],anRGB[2] );
+ aPlaneWgt->GetSelectedPlaneProperty()->SetOpacity( 0.2 );
+ aPlaneWgt->GetSelectedPlaneProperty()->SetLineWidth( 2.0 );
+
+ aPlaneWgt->AddObserver(vtkCommand::InteractionEvent, myCallback, 0.);
+
+ return aPlaneWgt;
+}
+
+namespace
+{
+ /*!
+ Translate two angles of plane to normal
+ */
+ void rotationToNormal ( double theRotation[2],
+ int theOrientation,
+ double theNormal[3],
+ double theDir[2][3] )
+ {
+ static double aCoeff = M_PI/180.0;
+
+ double anU[2] = { cos( aCoeff * theRotation[0] ), cos( aCoeff * theRotation[1] ) };
+ double aV[2] = { sqrt( 1.0 - anU[0]*anU[0] ), sqrt( 1.0 - anU[1] * anU[1] ) };
+ aV[0] = theRotation[0] > 0? aV[0]: -aV[0];
+ aV[1] = theRotation[1] > 0? aV[1]: -aV[1];
+
+ switch ( theOrientation ) {
+ case 0:
+ case 1:
+ theDir[0][1] = anU[0];
+ theDir[0][2] = aV[0];
+ theDir[1][0] = anU[1];
+ theDir[1][2] = aV[1];
+ break;
+ case 2:
+ theDir[0][2] = anU[0];
+ theDir[0][0] = aV[0];
+ theDir[1][1] = anU[1];
+ theDir[1][0] = aV[1];
+ break;
+ case 3:
+ theDir[0][0] = anU[0];
+ theDir[0][1] = aV[0];
+ theDir[1][2] = anU[1];
+ theDir[1][1] = aV[1];
+ break;
+ }
+
+ vtkMath::Cross( theDir[1], theDir[0], theNormal );
+ vtkMath::Normalize( theNormal );
+ vtkMath::Cross( theNormal, theDir[1], theDir[0] );
+ }
+
+ /*!
+ * \brief Return a name of a father mesh if any
+ */
+ QString getFatherName( _PTR(SObject)& theSObj )
+ {
+ _PTR(SComponent) objComponent = theSObj->GetFatherComponent();
+ const int theMeshDepth = 1 + objComponent->Depth();
+ if ( theSObj->Depth() <= theMeshDepth )
+ return QString(); // theSObj is a mesh
+
+ _PTR(SObject) sobj = theSObj->GetFather();
+ while ( sobj && sobj->Depth() > theMeshDepth )
+ sobj = sobj->GetFather();
+
+ return sobj ? sobj->GetName().c_str() : "";
+ }
+}
+
+/*!
+ Used in SMESHGUI::restoreVisualParameters() to avoid
+ Declaration of OrientedPlane outside of SMESHGUI_ClippingDlg.cxx
+*/
+bool SMESHGUI_ClippingDlg::AddPlane ( SMESH::TActorList theActorList,
+ SMESH::OrientedPlane* thePlane )
+{
+ double aNormal[3];
+ double aDir[2][3] = {{0, 0, 0}, {0, 0, 0}};
+ static double aCoeff = vtkMath::Pi()/180.0;
+
+ int anOrientation = 0;
+ if ( thePlane->PlaneMode == SMESH::Absolute )
+ anOrientation = thePlane->myAbsoluteOrientation;
+ else if ( thePlane->PlaneMode == SMESH::Relative )
+ anOrientation = thePlane->myRelativeOrientation + 1;
+
+ if ( anOrientation == 0 ) {
+ // compute a direction for plane in absolute mode
+ double znam = sqrt( thePlane->Dx*thePlane->Dx + thePlane->Dy*thePlane->Dy + thePlane->Dz*thePlane->Dz );
+ double aRotation = acos( thePlane->Dy/znam )/aCoeff;
+ if ( thePlane->Dy >= 0.0 && thePlane->Dz >= 0.0 ) thePlane->myAngle[0] = 90.0 + aRotation;
+ else if ( thePlane->Dy >= 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[0] = 90.0 - aRotation;
+ else if ( thePlane->Dy < 0.0 && thePlane->Dz >= 0.0 ) thePlane->myAngle[0] = aRotation - 90.0;
+ else if ( thePlane->Dy < 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[0] = 270.0 - aRotation;
+
+ aRotation = acos( thePlane->Dx/znam )/aCoeff;
+ if ( thePlane->Dx >= 0.0 && thePlane->Dz >= 0.0 ) thePlane->myAngle[1] = 90.0 + aRotation;
+ else if ( thePlane->Dx >= 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[1] = 90.0 - aRotation;
+ else if ( thePlane->Dx < 0.0 && thePlane->Dz >= 0.0 ) thePlane->myAngle[1] = aRotation - 90.0;
+ else if ( thePlane->Dx < 0.0 && thePlane->Dz < 0.0 ) thePlane->myAngle[1] = 270.0 - aRotation;
+ }
+
+ // compute a normal
+ rotationToNormal( thePlane->myAngle, anOrientation, aNormal, aDir );
+
+ double aBounds[6];
+ double anOrigin[3];
+
+ if ( thePlane->PlaneMode == SMESH::Absolute ) {
+ aNormal[0] = thePlane->Dx;
+ aNormal[1] = thePlane->Dy;
+ aNormal[2] = thePlane->Dz;
+ }
+
+ bool anIsOk = false;
+ if( theActorList.empty() ) {
+ // to support planes with empty actor list we should create
+ // a nullified plane that will be initialized later
+ anOrigin[0] = anOrigin[1] = anOrigin[2] = 0;
+ aBounds[0] = aBounds[2] = aBounds[4] = 0;
+ aBounds[1] = aBounds[3] = aBounds[5] = 0;
+ anIsOk = true;
+ }
+ else
+ anIsOk = SMESH::ComputeClippingPlaneParameters( theActorList,
+ aNormal,
+ thePlane->myDistance,
+ aBounds,
+ anOrigin );
+ if( !anIsOk )
+ return false;
+
+ if ( thePlane->PlaneMode == SMESH::Absolute ) {
+ anOrigin[0] = thePlane->X;
+ anOrigin[1] = thePlane->Y;
+ anOrigin[2] = thePlane->Z;
+ }
+ thePlane->SetNormal( aNormal );
+ thePlane->SetOrigin( anOrigin );
+
+
+ double aPnt[3] = { ( aBounds[0] + aBounds[1] ) / 2.,
+ ( aBounds[2] + aBounds[3] ) / 2.,
+ ( aBounds[4] + aBounds[5] ) / 2. };
+
+ double aDel = pow( pow( aBounds[1] - aBounds[0], 2 ) +
+ pow( aBounds[3] - aBounds[2], 2 ) +
+ pow( aBounds[5] - aBounds[4], 2 ), 0.5 );
+
+ double aDelta[2][3] = { { aDir[0][0]*aDel, aDir[0][1]*aDel, aDir[0][2]*aDel },
+ { aDir[1][0]*aDel, aDir[1][1]*aDel, aDir[1][2]*aDel } };
+ double aParam, aPnt0[3], aPnt1[3], aPnt2[3];
+
+ double aPnt01[3] = { aPnt[0] - aDelta[0][0] - aDelta[1][0],
+ aPnt[1] - aDelta[0][1] - aDelta[1][1],
+ aPnt[2] - aDelta[0][2] - aDelta[1][2] };
+ double aPnt02[3] = { aPnt01[0] + aNormal[0],
+ aPnt01[1] + aNormal[1],
+ aPnt01[2] + aNormal[2] };
+ vtkPlane::IntersectWithLine( aPnt01, aPnt02, aNormal, anOrigin, aParam, aPnt0 );
+
+ double aPnt11[3] = { aPnt[0] - aDelta[0][0] + aDelta[1][0],
+ aPnt[1] - aDelta[0][1] + aDelta[1][1],
+ aPnt[2] - aDelta[0][2] + aDelta[1][2] };
+ double aPnt12[3] = { aPnt11[0] + aNormal[0],
+ aPnt11[1] + aNormal[1],
+ aPnt11[2] + aNormal[2] };
+ vtkPlane::IntersectWithLine( aPnt11, aPnt12, aNormal, anOrigin, aParam, aPnt1);
+
+ double aPnt21[3] = { aPnt[0] + aDelta[0][0] - aDelta[1][0],
+ aPnt[1] + aDelta[0][1] - aDelta[1][1],
+ aPnt[2] + aDelta[0][2] - aDelta[1][2] };
+ double aPnt22[3] = { aPnt21[0] + aNormal[0],
+ aPnt21[1] + aNormal[1],
+ aPnt21[2] + aNormal[2] };
+ vtkPlane::IntersectWithLine( aPnt21, aPnt22, aNormal, anOrigin, aParam, aPnt2);
+
+ vtkPlaneSource* aPlaneSource = thePlane->myPlaneSource;
+ aPlaneSource->SetNormal( aNormal[0], aNormal[1], aNormal[2] );
+ aPlaneSource->SetOrigin( aPnt0[0], aPnt0[1], aPnt0[2] );
+ aPlaneSource->SetPoint1( aPnt1[0], aPnt1[1], aPnt1[2] );
+ aPlaneSource->SetPoint2( aPnt2[0], aPnt2[1], aPnt2[2] );
+ aPlaneSource->Update();
+
+ SMESH::TActorList::iterator anIter = theActorList.begin();
+ for ( ; anIter != theActorList.end(); anIter++ )
+ if( vtkActor* aVTKActor = *anIter )
+ if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
+ if( thePlane->IsOpenGLClipping )
+ anActor->AddOpenGLClippingPlane( thePlane->InvertPlane() );
+ else
+ anActor->AddClippingPlane( thePlane );
+ }
+
+ return true;
+}
+
+/*!
+ Custom handling of events
+*/
+void SMESHGUI_ClippingDlg::keyPressEvent( QKeyEvent* e )