1 // Copyright (C) 2007-2008 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
22 #include "OCCViewer_ClippingDlg.h"
24 #include <QtxDoubleSpinBox.h>
25 #include <QtxAction.h>
27 #include "SUIT_Session.h"
28 #include "SUIT_ViewWindow.h"
29 #include "SUIT_ViewManager.h"
30 #include "OCCViewer_ViewWindow.h"
31 #include "OCCViewer_ViewPort3d.h"
32 #include "OCCViewer_ViewModel.h"
34 #include <V3d_View.hxx>
35 #include <Geom_Plane.hxx>
36 #include <Prs3d_Presentation.hxx>
37 #include <AIS_ListIteratorOfListOfInteractive.hxx>
38 #include <AIS_ListOfInteractive.hxx>
39 #include <AIS_InteractiveObject.hxx>
40 #include <AIS_InteractiveContext.hxx>
41 #include <IntAna_IntConicQuad.hxx>
46 #include <QApplication>
48 #include <QHBoxLayout>
49 #include <QVBoxLayout>
50 #include <QGridLayout>
52 #include <QPushButton>
58 \param view - view window
59 \param parent - parent widget
60 \param name - dialog name
61 \param modal - is this dialog modal
64 OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl )
65 : QDialog( parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
68 setObjectName( "OCCViewer_ClippingDlg" );
71 setWindowTitle( tr( "Clipping" ) );
73 QVBoxLayout* topLayout = new QVBoxLayout( this );
74 topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
76 /***************************************************************/
77 GroupPoint = new QGroupBox( this );
78 GroupPoint->setObjectName( "GroupPoint" );
79 GroupPoint->setTitle( tr("Base point") );
80 QGridLayout* GroupPointLayout = new QGridLayout( GroupPoint );
81 GroupPointLayout->setAlignment( Qt::AlignTop );
82 GroupPointLayout->setSpacing( 6 );
83 GroupPointLayout->setMargin( 11 );
86 const double min = -1e+7;
87 const double max = 1e+7;
88 const double step = 5;
89 const int precision = 3;
91 TextLabelX = new QLabel( GroupPoint );
92 TextLabelX->setObjectName( "TextLabelX" );
93 TextLabelX->setText( tr("X:") );
94 GroupPointLayout->addWidget( TextLabelX, 0, 0 );
96 SpinBox_X = new QtxDoubleSpinBox( min, max, step, GroupPoint );
97 SpinBox_X->setObjectName("SpinBox_X" );
98 SpinBox_X->setDecimals( precision );
99 GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
101 TextLabelY = new QLabel( GroupPoint );
102 TextLabelY->setObjectName( "TextLabelY" );
103 TextLabelY->setText( tr("Y:") );
104 GroupPointLayout->addWidget( TextLabelY, 0, 2 );
106 SpinBox_Y = new QtxDoubleSpinBox( min, max, step, GroupPoint );
107 SpinBox_Y->setObjectName("SpinBox_Y" );
108 SpinBox_Y->setDecimals( precision );
109 GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
111 TextLabelZ = new QLabel( GroupPoint );
112 TextLabelZ->setObjectName( "TextLabelZ" );
113 TextLabelZ->setText( tr("Z:") );
114 GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
116 SpinBox_Z = new QtxDoubleSpinBox( min, max, step, GroupPoint );
117 SpinBox_Z->setObjectName("SpinBox_Z" );
118 SpinBox_Z->setDecimals( precision );
119 GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
121 resetButton = new QPushButton( GroupPoint );
122 resetButton->setObjectName( "resetButton" );
123 resetButton->setText( tr( "Reset" ) );
124 GroupPointLayout->addWidget( resetButton, 0, 6 );
126 /***************************************************************/
127 GroupDirection = new QGroupBox( this );
128 GroupDirection->setObjectName( "GroupDirection" );
129 GroupDirection->setTitle( tr("Direction") );
130 QGridLayout* GroupDirectionLayout = new QGridLayout( GroupDirection );
131 GroupDirectionLayout->setAlignment( Qt::AlignTop );
132 GroupDirectionLayout->setSpacing( 6 );
133 GroupDirectionLayout->setMargin( 11 );
136 TextLabelDx = new QLabel( GroupDirection );
137 TextLabelDx->setObjectName( "TextLabelDx" );
138 TextLabelDx->setText( tr("Dx:") );
139 GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
141 SpinBox_Dx = new QtxDoubleSpinBox( min, max, step, GroupDirection );
142 SpinBox_Dx->setObjectName("SpinBox_Dx" );
143 SpinBox_Dx->setDecimals( precision );
144 GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
146 TextLabelDy = new QLabel( GroupDirection );
147 TextLabelDy->setObjectName( "TextLabelDy" );
148 TextLabelDy->setText( tr("Dy:") );
149 GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
151 SpinBox_Dy = new QtxDoubleSpinBox( min, max, step, GroupDirection );
152 SpinBox_Dy->setObjectName("SpinBox_Dy" );
153 SpinBox_Dy->setDecimals( precision );
154 GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
156 TextLabelDz = new QLabel( GroupDirection );
157 TextLabelDz->setObjectName( "TextLabelDz" );
158 TextLabelDz->setText( tr("Dz:") );
159 GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
161 SpinBox_Dz = new QtxDoubleSpinBox( min, max, step, GroupDirection );
162 SpinBox_Dz->setObjectName("SpinBox_Dz" );
163 SpinBox_Dz->setDecimals( precision );
164 GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
166 invertButton = new QPushButton( GroupDirection );
167 invertButton->setObjectName( "invertButton" );
168 invertButton->setText( tr( "Invert" ) );
169 GroupDirectionLayout->addWidget( invertButton, 0, 6 );
171 DirectionCB = new QComboBox( GroupDirection );
172 DirectionCB->setObjectName( "DirectionCB" );
173 DirectionCB->insertItem(DirectionCB->count(),tr("CUSTOM"));
174 DirectionCB->insertItem(DirectionCB->count(),tr("||X-Y"));
175 DirectionCB->insertItem(DirectionCB->count(),tr("||Y-Z"));
176 DirectionCB->insertItem(DirectionCB->count(),tr("||Z-X"));
177 GroupDirectionLayout->addWidget( DirectionCB, 1, 0, 1, 6 );
179 /***************************************************************/
181 PreviewChB = new QCheckBox( tr("Preview") ,this );
182 PreviewChB->setObjectName( "PreviewChB" );
183 PreviewChB->setChecked( true );
185 /***************************************************************/
186 QGroupBox* GroupButtons = new QGroupBox( this );
187 GroupButtons->setObjectName( "GroupButtons" );
188 QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons );
189 GroupButtonsLayout->setAlignment( Qt::AlignTop );
190 GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 );
192 buttonApply = new QPushButton( GroupButtons );
193 buttonApply->setObjectName( "buttonApply" );
194 buttonApply->setText( tr( "BUT_APPLY" ) );
195 buttonApply->setAutoDefault( TRUE );
196 buttonApply->setDefault( TRUE );
197 GroupButtonsLayout->addWidget( buttonApply );
199 GroupButtonsLayout->addStretch();
201 buttonClose = new QPushButton( GroupButtons );
202 buttonClose->setObjectName( "buttonClose" );
203 buttonClose->setText( tr( "BUT_CLOSE" ) );
204 buttonClose->setAutoDefault( TRUE );
205 GroupButtonsLayout->addWidget( buttonClose );
207 /***************************************************************/
209 topLayout->addWidget( GroupPoint );
210 topLayout->addWidget( GroupDirection );
212 topLayout->addWidget( PreviewChB );
214 topLayout->addWidget( GroupButtons );
216 /* initializations */
218 SpinBox_X->setValue( 0.0 );
219 SpinBox_Y->setValue( 0.0 );
220 SpinBox_Z->setValue( 0.0 );
222 SpinBox_Dx->setValue( 1.0 );
223 SpinBox_Dy->setValue( 1.0 );
224 SpinBox_Dz->setValue( 1.0 );
226 /* signals and slots connections */
227 connect( resetButton, SIGNAL (clicked() ), this, SLOT( onReset() ) );
228 connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
230 connect( SpinBox_X, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
231 connect( SpinBox_Y, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
232 connect( SpinBox_Z, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
233 connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
234 connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
235 connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
237 connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
239 connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
241 connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
242 connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
246 connect(view, SIGNAL(Show( QShowEvent * )), this, SLOT(onViewShow()));
247 connect(view, SIGNAL(Hide( QHideEvent * )), this, SLOT(onViewHide()));
252 Destroys the object and frees any allocated resources
254 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
256 // no need to delete child widgets, Qt does it all for us
261 Custom handling of close event: erases preview
263 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
267 // Set the clipping plane back
268 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
269 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
270 aView3d->SetPlaneOn( myClippingPlane );
272 myAction->setChecked( false );
274 QDialog::closeEvent( e );
279 Custom handling of show event: displays preview
281 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
283 ReserveClippingPlane();
285 QDialog::showEvent( e );
286 onPreview( PreviewChB->isChecked() );
291 Custom handling of hide event: erases preview
293 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
296 QDialog::hideEvent( e );
301 SLOT on close button click: erases preview and rejects dialog
303 void OCCViewer_ClippingDlg::ClickOnClose()
307 // Set the clipping plane back
308 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
309 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
310 aView3d->SetPlaneOn( myClippingPlane );
312 myAction->setChecked( false );
319 SLOT on apply button click: sets cutting plane
321 void OCCViewer_ClippingDlg::ClickOnApply()
323 qApp->processEvents();
324 QApplication::setOverrideCursor( Qt::WaitCursor );
325 qApp->processEvents();
327 myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
328 SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
330 QApplication::restoreOverrideCursor();
334 ReserveClippingPlane();
338 SLOT on reset button click: sets default values
340 void OCCViewer_ClippingDlg::onReset()
343 SpinBox_X->setValue(0);
344 SpinBox_Y->setValue(0);
345 SpinBox_Z->setValue(0);
348 if ( PreviewChB->isChecked() )
356 SLOT on invert button click: inverts normal of cutting plane
358 void OCCViewer_ClippingDlg::onInvert()
360 double Dx = SpinBox_Dx->value();
361 double Dy = SpinBox_Dy->value();
362 double Dz = SpinBox_Dz->value();
365 SpinBox_Dx->setValue( -Dx );
366 SpinBox_Dy->setValue( -Dy );
367 SpinBox_Dz->setValue( -Dz );
370 if ( PreviewChB->isChecked() )
378 SLOT: called on mode changed
380 void OCCViewer_ClippingDlg::onModeChanged( int mode )
382 bool isUserMode = (mode==0);
384 TextLabelX->setEnabled( isUserMode );
385 TextLabelY->setEnabled( isUserMode );
386 TextLabelZ->setEnabled( isUserMode );
388 SpinBox_X->setEnabled( isUserMode );
389 SpinBox_Y->setEnabled( isUserMode );
390 SpinBox_Z->setEnabled( isUserMode );
392 TextLabelDx->setEnabled( isUserMode );
393 TextLabelDy->setEnabled( isUserMode );
394 TextLabelDz->setEnabled( isUserMode );
396 SpinBox_Dx->setEnabled( isUserMode );
397 SpinBox_Dy->setEnabled( isUserMode );
398 SpinBox_Dz->setEnabled( isUserMode );
403 double aDx = 0, aDy = 0, aDz = 0;
408 TextLabelZ->setEnabled( true );
409 SpinBox_Z->setEnabled( true );
410 SpinBox_Z->setFocus();
412 else if ( mode == 2 )
415 TextLabelX->setEnabled( true );
416 SpinBox_X->setEnabled( true );
417 SpinBox_X->setFocus();
419 else if ( mode == 3 )
422 TextLabelY->setEnabled( true );
423 SpinBox_Y->setEnabled( true );
424 SpinBox_Y->setFocus();
428 SpinBox_Dx->setValue( aDx );
429 SpinBox_Dy->setValue( aDy );
430 SpinBox_Dz->setValue( aDz );
433 if ( PreviewChB->isChecked() )
442 Displays preview of clipping plane
444 void OCCViewer_ClippingDlg::displayPreview()
446 if ( myBusy || !isValid() )
449 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
453 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
455 double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
456 aXMin = aYMin = aZMin = DBL_MAX;
457 aXMax = aYMax = aZMax = -DBL_MAX;
459 bool isFound = false;
460 AIS_ListOfInteractive aList;
461 ic->DisplayedObjects( aList );
462 for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
464 Handle(AIS_InteractiveObject) anObj = it.Value();
465 if ( !anObj.IsNull() && anObj->HasPresentation() &&
466 !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
468 Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
469 if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
472 double xmin, ymin, zmin, xmax, ymax, zmax;
473 aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
474 aXMin = qMin( aXMin, xmin ); aXMax = qMax( aXMax, xmax );
475 aYMin = qMin( aYMin, ymin ); aYMax = qMax( aYMax, ymax );
476 aZMin = qMin( aZMin, zmin ); aZMax = qMax( aZMax, zmax );
483 gp_Pnt aBasePnt( SpinBox_X->value(), SpinBox_Y->value(), SpinBox_Z->value() );
484 gp_Dir aNormal( SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
485 gp_Pnt aCenter = aBasePnt;
489 // compute clipping plane size
490 aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
491 double aDiag = aCenter.Distance(gp_Pnt(aXMax, aYMax, aZMax ))*2;
494 // compute clipping plane center ( redefine the base point )
495 IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
497 intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
498 if ( intersector.IsDone() && intersector.NbPoints() == 1 )
499 aBasePnt = intersector.Point( 1 );
502 myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
503 myPreviewPlane->SetSize( aSize, aSize );
505 // Deactivate clipping planes
506 myView->getViewPort()->getView()->SetPlaneOff();
508 ic->Display( myPreviewPlane, 1, -1, false );
509 ic->SetWidth( myPreviewPlane, 10, false );
510 ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
511 ic->SetTransparency( myPreviewPlane, 0.5, false );
512 ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
514 anOCCViewer->update();
519 Erases preview of clipping plane
521 void OCCViewer_ClippingDlg::erasePreview ()
523 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
527 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
529 if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
531 ic->Erase( myPreviewPlane, false, false );
532 ic->Remove( myPreviewPlane, false );
533 myPreviewPlane.Nullify();
536 anOCCViewer->update();
541 SLOT: called on value changes (co-ordinates of point or normal)
543 void OCCViewer_ClippingDlg::onValueChanged()
545 if ( PreviewChB->isChecked() )
554 SLOT: called on preview check box toggled
556 void OCCViewer_ClippingDlg::onPreview( bool on )
565 \return true if plane parameters are valid
567 bool OCCViewer_ClippingDlg::isValid()
569 return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
573 Remember the current clipping plane
575 void OCCViewer_ClippingDlg::ReserveClippingPlane()
577 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
578 if ( !aView3d.IsNull() )
580 aView3d->InitActivePlanes();
581 if ( aView3d->MoreActivePlanes() )
582 myClippingPlane = aView3d->ActivePlane();
586 void OCCViewer_ClippingDlg::onViewShow()
588 if(myAction->isChecked())
594 void OCCViewer_ClippingDlg::onViewHide()