1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "OCCViewer_ClippingDlg.h"
25 #include <QtxDoubleSpinBox.h>
26 #include <QtxAction.h>
28 #include "SUIT_Session.h"
29 #include "SUIT_ViewWindow.h"
30 #include "SUIT_ViewManager.h"
31 #include "OCCViewer_ViewWindow.h"
32 #include "OCCViewer_ViewPort3d.h"
33 #include "OCCViewer_ViewModel.h"
35 #include <V3d_View.hxx>
36 #include <Geom_Plane.hxx>
37 #include <Prs3d_Presentation.hxx>
38 #include <AIS_ListIteratorOfListOfInteractive.hxx>
39 #include <AIS_ListOfInteractive.hxx>
40 #include <AIS_InteractiveObject.hxx>
41 #include <AIS_InteractiveContext.hxx>
42 #include <IntAna_IntConicQuad.hxx>
47 #include <QApplication>
49 #include <QHBoxLayout>
50 #include <QVBoxLayout>
51 #include <QGridLayout>
53 #include <QPushButton>
59 \param view - view window
60 \param parent - parent widget
61 \param name - dialog name
62 \param modal - is this dialog modal
65 OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, const char* name, bool modal, Qt::WindowFlags fl )
66 : QDialog( view, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
69 setObjectName( "OCCViewer_ClippingDlg" );
72 setWindowTitle( tr( "Clipping" ) );
74 QVBoxLayout* topLayout = new QVBoxLayout( this );
75 topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
77 /***************************************************************/
78 GroupPoint = new QGroupBox( this );
79 GroupPoint->setObjectName( "GroupPoint" );
80 GroupPoint->setTitle( tr("Base point") );
81 QGridLayout* GroupPointLayout = new QGridLayout( GroupPoint );
82 GroupPointLayout->setAlignment( Qt::AlignTop );
83 GroupPointLayout->setSpacing( 6 );
84 GroupPointLayout->setMargin( 11 );
87 const double min = -1e+7;
88 const double max = 1e+7;
89 const double step = 5;
90 const int precision = -7;
92 TextLabelX = new QLabel( GroupPoint );
93 TextLabelX->setObjectName( "TextLabelX" );
94 TextLabelX->setText( tr("X:") );
95 GroupPointLayout->addWidget( TextLabelX, 0, 0 );
97 SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupPoint );
98 SpinBox_X->setObjectName("SpinBox_X" );
99 SpinBox_X->setPrecision( precision );
100 GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
102 TextLabelY = new QLabel( GroupPoint );
103 TextLabelY->setObjectName( "TextLabelY" );
104 TextLabelY->setText( tr("Y:") );
105 GroupPointLayout->addWidget( TextLabelY, 0, 2 );
107 SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupPoint );
108 SpinBox_Y->setObjectName("SpinBox_Y" );
109 SpinBox_Y->setPrecision( precision );
110 GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
112 TextLabelZ = new QLabel( GroupPoint );
113 TextLabelZ->setObjectName( "TextLabelZ" );
114 TextLabelZ->setText( tr("Z:") );
115 GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
117 SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupPoint );
118 SpinBox_Z->setObjectName("SpinBox_Z" );
119 SpinBox_Z->setPrecision( precision );
120 GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
122 resetButton = new QPushButton( GroupPoint );
123 resetButton->setObjectName( "resetButton" );
124 resetButton->setText( tr( "Reset" ) );
125 GroupPointLayout->addWidget( resetButton, 0, 6 );
127 /***************************************************************/
128 GroupDirection = new QGroupBox( this );
129 GroupDirection->setObjectName( "GroupDirection" );
130 GroupDirection->setTitle( tr("Direction") );
131 QGridLayout* GroupDirectionLayout = new QGridLayout( GroupDirection );
132 GroupDirectionLayout->setAlignment( Qt::AlignTop );
133 GroupDirectionLayout->setSpacing( 6 );
134 GroupDirectionLayout->setMargin( 11 );
137 TextLabelDx = new QLabel( GroupDirection );
138 TextLabelDx->setObjectName( "TextLabelDx" );
139 TextLabelDx->setText( tr("Dx:") );
140 GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
142 SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupDirection );
143 SpinBox_Dx->setObjectName("SpinBox_Dx" );
144 SpinBox_Dx->setPrecision( precision );
145 GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
147 TextLabelDy = new QLabel( GroupDirection );
148 TextLabelDy->setObjectName( "TextLabelDy" );
149 TextLabelDy->setText( tr("Dy:") );
150 GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
152 SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupDirection );
153 SpinBox_Dy->setObjectName("SpinBox_Dy" );
154 SpinBox_Dy->setPrecision( precision );
155 GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
157 TextLabelDz = new QLabel( GroupDirection );
158 TextLabelDz->setObjectName( "TextLabelDz" );
159 TextLabelDz->setText( tr("Dz:") );
160 GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
162 SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupDirection );
163 SpinBox_Dz->setObjectName("SpinBox_Dz" );
164 SpinBox_Dz->setPrecision( precision );
165 GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
167 invertButton = new QPushButton( GroupDirection );
168 invertButton->setObjectName( "invertButton" );
169 invertButton->setText( tr( "Invert" ) );
170 GroupDirectionLayout->addWidget( invertButton, 0, 6 );
172 DirectionCB = new QComboBox( GroupDirection );
173 DirectionCB->setObjectName( "DirectionCB" );
174 DirectionCB->insertItem(DirectionCB->count(),tr("CUSTOM"));
175 DirectionCB->insertItem(DirectionCB->count(),tr("||X-Y"));
176 DirectionCB->insertItem(DirectionCB->count(),tr("||Y-Z"));
177 DirectionCB->insertItem(DirectionCB->count(),tr("||Z-X"));
178 GroupDirectionLayout->addWidget( DirectionCB, 1, 0, 1, 6 );
180 /***************************************************************/
182 PreviewChB = new QCheckBox( tr("Preview") ,this );
183 PreviewChB->setObjectName( "PreviewChB" );
184 PreviewChB->setChecked( true );
186 /***************************************************************/
187 QGroupBox* GroupButtons = new QGroupBox( this );
188 GroupButtons->setObjectName( "GroupButtons" );
189 QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons );
190 GroupButtonsLayout->setAlignment( Qt::AlignTop );
191 GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 );
193 buttonApply = new QPushButton( GroupButtons );
194 buttonApply->setObjectName( "buttonApply" );
195 buttonApply->setText( tr( "BUT_APPLY" ) );
196 buttonApply->setAutoDefault( TRUE );
197 buttonApply->setDefault( TRUE );
198 GroupButtonsLayout->addWidget( buttonApply );
200 GroupButtonsLayout->addStretch();
202 buttonClose = new QPushButton( GroupButtons );
203 buttonClose->setObjectName( "buttonClose" );
204 buttonClose->setText( tr( "BUT_CLOSE" ) );
205 buttonClose->setAutoDefault( TRUE );
206 GroupButtonsLayout->addWidget( buttonClose );
208 /***************************************************************/
210 topLayout->addWidget( GroupPoint );
211 topLayout->addWidget( GroupDirection );
213 topLayout->addWidget( PreviewChB );
215 topLayout->addWidget( GroupButtons );
217 /* initializations */
219 SpinBox_X->setValue( 0.0 );
220 SpinBox_Y->setValue( 0.0 );
221 SpinBox_Z->setValue( 0.0 );
223 SpinBox_Dx->setValue( 1.0 );
224 SpinBox_Dy->setValue( 1.0 );
225 SpinBox_Dz->setValue( 1.0 );
227 /* signals and slots connections */
228 connect( resetButton, SIGNAL (clicked() ), this, SLOT( onReset() ) );
229 connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
231 connect( SpinBox_X, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
232 connect( SpinBox_Y, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
233 connect( SpinBox_Z, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
234 connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
235 connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
236 connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
238 connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
240 connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
242 connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
243 connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
247 connect(view, SIGNAL(Show( QShowEvent * )), this, SLOT(onViewShow()));
248 connect(view, SIGNAL(Hide( QHideEvent * )), this, SLOT(onViewHide()));
253 Destroys the object and frees any allocated resources
255 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
257 // no need to delete child widgets, Qt does it all for us
262 Custom handling of close event: erases preview
264 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
268 // Set the clipping plane back
269 /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
270 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
271 aView3d->SetPlaneOn( myClippingPlane );*/
273 myAction->setChecked( false );
275 QDialog::closeEvent( e );
280 Custom handling of show event: displays preview
282 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
284 //ReserveClippingPlane();
286 QDialog::showEvent( e );
287 onPreview( PreviewChB->isChecked() );
292 Custom handling of hide event: erases preview
294 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
297 QDialog::hideEvent( e );
302 SLOT on close button click: erases preview and rejects dialog
304 void OCCViewer_ClippingDlg::ClickOnClose()
308 // Set the clipping plane back
309 /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
310 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
311 aView3d->SetPlaneOn( myClippingPlane );
313 myAction->setChecked( false );
320 SLOT on apply button click: sets cutting plane
322 void OCCViewer_ClippingDlg::ClickOnApply()
324 qApp->processEvents();
325 QApplication::setOverrideCursor( Qt::WaitCursor );
326 qApp->processEvents();
328 myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
329 SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
331 QApplication::restoreOverrideCursor();
335 //ReserveClippingPlane();
339 SLOT on reset button click: sets default values
341 void OCCViewer_ClippingDlg::onReset()
344 SpinBox_X->setValue(0);
345 SpinBox_Y->setValue(0);
346 SpinBox_Z->setValue(0);
349 if ( PreviewChB->isChecked() )
357 SLOT on invert button click: inverts normal of cutting plane
359 void OCCViewer_ClippingDlg::onInvert()
361 double Dx = SpinBox_Dx->value();
362 double Dy = SpinBox_Dy->value();
363 double Dz = SpinBox_Dz->value();
366 SpinBox_Dx->setValue( -Dx );
367 SpinBox_Dy->setValue( -Dy );
368 SpinBox_Dz->setValue( -Dz );
371 if ( PreviewChB->isChecked() )
379 SLOT: called on mode changed
381 void OCCViewer_ClippingDlg::onModeChanged( int mode )
383 bool isUserMode = (mode==0);
385 TextLabelX->setEnabled( isUserMode );
386 TextLabelY->setEnabled( isUserMode );
387 TextLabelZ->setEnabled( isUserMode );
389 SpinBox_X->setEnabled( isUserMode );
390 SpinBox_Y->setEnabled( isUserMode );
391 SpinBox_Z->setEnabled( isUserMode );
393 TextLabelDx->setEnabled( isUserMode );
394 TextLabelDy->setEnabled( isUserMode );
395 TextLabelDz->setEnabled( isUserMode );
397 SpinBox_Dx->setEnabled( isUserMode );
398 SpinBox_Dy->setEnabled( isUserMode );
399 SpinBox_Dz->setEnabled( isUserMode );
404 double aDx = 0, aDy = 0, aDz = 0;
409 TextLabelZ->setEnabled( true );
410 SpinBox_Z->setEnabled( true );
411 SpinBox_Z->setFocus();
413 else if ( mode == 2 )
416 TextLabelX->setEnabled( true );
417 SpinBox_X->setEnabled( true );
418 SpinBox_X->setFocus();
420 else if ( mode == 3 )
423 TextLabelY->setEnabled( true );
424 SpinBox_Y->setEnabled( true );
425 SpinBox_Y->setFocus();
429 SpinBox_Dx->setValue( aDx );
430 SpinBox_Dy->setValue( aDy );
431 SpinBox_Dz->setValue( aDz );
434 if ( PreviewChB->isChecked() )
443 Displays preview of clipping plane
445 void OCCViewer_ClippingDlg::displayPreview()
447 if ( myBusy || !isValid() )
450 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
454 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
456 double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
457 aXMin = aYMin = aZMin = DBL_MAX;
458 aXMax = aYMax = aZMax = -DBL_MAX;
460 bool isFound = false;
461 AIS_ListOfInteractive aList;
462 ic->DisplayedObjects( aList );
463 for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
465 Handle(AIS_InteractiveObject) anObj = it.Value();
466 if ( !anObj.IsNull() && anObj->HasPresentation() &&
467 !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
469 Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
470 if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
473 double xmin, ymin, zmin, xmax, ymax, zmax;
474 aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
475 aXMin = qMin( aXMin, xmin ); aXMax = qMax( aXMax, xmax );
476 aYMin = qMin( aYMin, ymin ); aYMax = qMax( aYMax, ymax );
477 aZMin = qMin( aZMin, zmin ); aZMax = qMax( aZMax, zmax );
484 gp_Pnt aBasePnt( SpinBox_X->value(), SpinBox_Y->value(), SpinBox_Z->value() );
485 gp_Dir aNormal( SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
486 gp_Pnt aCenter = aBasePnt;
490 // compute clipping plane size
491 aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
492 double aDiag = aCenter.Distance(gp_Pnt(aXMax, aYMax, aZMax ))*2;
495 // compute clipping plane center ( redefine the base point )
496 IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
498 intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
499 if ( intersector.IsDone() && intersector.NbPoints() == 1 )
500 aBasePnt = intersector.Point( 1 );
503 myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
504 myPreviewPlane->SetSize( aSize, aSize );
506 // Deactivate clipping planes
507 //myView->getViewPort()->getView()->SetPlaneOff();
508 //myView->setPlaneOff();
510 ic->Display( myPreviewPlane, 1, -1, false );
511 ic->SetWidth( myPreviewPlane, 10, false );
512 ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
513 ic->SetTransparency( myPreviewPlane, 0.5, false );
514 ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
516 anOCCViewer->update();
521 Erases preview of clipping plane
523 void OCCViewer_ClippingDlg::erasePreview ()
525 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
529 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
531 if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
533 #if OCC_VERSION_LARGE <= 0x06060000
534 ic->Erase( myPreviewPlane, false, false );
536 ic->Erase( myPreviewPlane, false );
538 ic->Remove( myPreviewPlane, false );
539 myPreviewPlane.Nullify();
542 anOCCViewer->update();
547 SLOT: called on value changes (co-ordinates of point or normal)
549 void OCCViewer_ClippingDlg::onValueChanged()
551 if ( PreviewChB->isChecked() )
560 SLOT: called on preview check box toggled
562 void OCCViewer_ClippingDlg::onPreview( bool on )
571 \return true if plane parameters are valid
573 bool OCCViewer_ClippingDlg::isValid()
575 return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
579 Remember the current clipping plane
581 void OCCViewer_ClippingDlg::ReserveClippingPlane()
583 /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
584 if ( !aView3d.IsNull() )
586 aView3d->InitActivePlanes();
587 if ( aView3d->MoreActivePlanes() )
588 myClippingPlane = aView3d->ActivePlane();
592 void OCCViewer_ClippingDlg::onViewShow()
594 if(myAction->isChecked())
600 void OCCViewer_ClippingDlg::onViewHide()