1 // Copyright (C) 2005 CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/
19 #include "OCCViewer_ClippingDlg.h"
21 #include <QtxDblSpinBox.h>
22 #include <QtxAction.h>
24 #include "SUIT_Session.h"
25 #include "SUIT_ViewWindow.h"
26 #include "OCCViewer_ViewWindow.h"
27 #include "OCCViewer_ViewPort3d.h"
29 #include <V3d_View.hxx>
31 #include <Geom_Plane.hxx>
32 #include <Prs3d_Presentation.hxx>
33 #include <AIS_ListIteratorOfListOfInteractive.hxx>
34 #include <AIS_ListOfInteractive.hxx>
35 #include <AIS_InteractiveObject.hxx>
36 #include <AIS_InteractiveContext.hxx>
37 #include <IntAna_IntConicQuad.hxx>
42 #include <qapplication.h>
43 #include <qgroupbox.h>
46 #include <qpushbutton.h>
47 #include <qcombobox.h>
48 #include <qcheckbox.h>
52 \param view - view window
53 \param parent - parent widget
54 \param name - dialog name
55 \param modal - is this dialog modal
58 OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, QWidget* parent, const char* name, bool modal, WFlags fl )
59 : QDialog( parent, "OCCViewer_ClippingDlg", modal, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu ),
62 setCaption( tr( "Clipping" ) );
64 QVBoxLayout* topLayout = new QVBoxLayout( this );
65 topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
67 /***************************************************************/
68 GroupPoint = new QGroupBox( this, "GroupPoint" );
69 GroupPoint->setTitle( tr("Base point") );
70 GroupPoint->setColumnLayout(0, Qt::Vertical );
71 GroupPoint->layout()->setSpacing( 0 );
72 GroupPoint->layout()->setMargin( 0 );
73 QGridLayout* GroupPointLayout = new QGridLayout( GroupPoint->layout() );
74 GroupPointLayout->setAlignment( Qt::AlignTop );
75 GroupPointLayout->setSpacing( 6 );
76 GroupPointLayout->setMargin( 11 );
79 const double min = -1e+06;
80 const double max = 1e+06;
81 const double step = 5;
83 TextLabelX = new QLabel( GroupPoint, "TextLabelX" );
84 TextLabelX->setText( tr("X:") );
85 GroupPointLayout->addWidget( TextLabelX, 0, 0 );
87 SpinBox_X = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_X" );
88 GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
90 TextLabelY = new QLabel( GroupPoint, "TextLabelY" );
91 TextLabelY->setText( tr("Y:") );
92 GroupPointLayout->addWidget( TextLabelY, 0, 2 );
94 SpinBox_Y = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Y" );
95 GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
97 TextLabelZ = new QLabel( GroupPoint, "TextLabelZ" );
98 TextLabelZ->setText( tr("Z:") );
99 GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
101 SpinBox_Z = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Z" );
102 GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
104 resetButton = new QPushButton( GroupPoint, "resetButton" );
105 resetButton->setText( tr( "Reset" ) );
106 GroupPointLayout->addWidget( resetButton, 0, 6 );
108 /***************************************************************/
109 GroupDirection = new QGroupBox( this, "GroupDirection" );
110 GroupDirection->setTitle( tr("Direction") );
111 GroupDirection->setColumnLayout(0, Qt::Vertical );
112 GroupDirection->layout()->setSpacing( 0 );
113 GroupDirection->layout()->setMargin( 0 );
114 QGridLayout* GroupDirectionLayout = new QGridLayout( GroupDirection->layout() );
115 GroupDirectionLayout->setAlignment( Qt::AlignTop );
116 GroupDirectionLayout->setSpacing( 6 );
117 GroupDirectionLayout->setMargin( 11 );
120 TextLabelDx = new QLabel( GroupDirection, "TextLabelDx" );
121 TextLabelDx->setText( tr("Dx:") );
122 GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
124 SpinBox_Dx = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dx" );
125 GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
127 TextLabelDy = new QLabel( GroupDirection, "TextLabelDy" );
128 TextLabelDy->setText( tr("Dy:") );
129 GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
131 SpinBox_Dy = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dy" );
132 GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
134 TextLabelDz = new QLabel( GroupDirection, "TextLabelDz" );
135 TextLabelDz->setText( tr("Dz:") );
136 GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
138 SpinBox_Dz = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dz" );
139 GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
141 invertButton = new QPushButton( GroupDirection, "invertButton" );
142 invertButton->setText( tr( "Invert" ) );
143 GroupDirectionLayout->addWidget( invertButton, 0, 6 );
145 DirectionCB = new QComboBox( GroupDirection, "DirectionCB" );
146 DirectionCB->insertItem(tr("CUSTOM"));
147 DirectionCB->insertItem(tr("||X-Y"));
148 DirectionCB->insertItem(tr("||Y-Z"));
149 DirectionCB->insertItem(tr("||Z-X"));
150 GroupDirectionLayout->addMultiCellWidget( DirectionCB, 1, 1, 0, 5 );
152 /***************************************************************/
154 PreviewChB = new QCheckBox( tr("Preview") ,this, "PreviewChB" );
155 PreviewChB->setChecked( true );
157 /***************************************************************/
158 QGroupBox* GroupButtons = new QGroupBox( this, "GroupButtons" );
159 GroupButtons->setColumnLayout(0, Qt::Vertical );
160 GroupButtons->layout()->setMargin( 0 ); GroupButtons->layout()->setSpacing( 0 );
161 QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons->layout() );
162 GroupButtonsLayout->setAlignment( Qt::AlignTop );
163 GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 );
165 buttonApply = new QPushButton( GroupButtons, "buttonApply" );
166 buttonApply->setText( tr( "BUT_APPLY" ) );
167 buttonApply->setAutoDefault( TRUE );
168 buttonApply->setDefault( TRUE );
169 GroupButtonsLayout->addWidget( buttonApply );
171 GroupButtonsLayout->addStretch();
173 buttonClose = new QPushButton( GroupButtons, "buttonClose" );
174 buttonClose->setText( tr( "BUT_CLOSE" ) );
175 buttonClose->setAutoDefault( TRUE );
176 GroupButtonsLayout->addWidget( buttonClose );
177 /***************************************************************/
179 topLayout->addWidget( GroupPoint );
180 topLayout->addWidget( GroupDirection );
182 topLayout->addWidget( PreviewChB );
184 topLayout->addWidget( GroupButtons );
186 /* initializations */
188 SpinBox_X->setValue( 0.0 );
189 SpinBox_Y->setValue( 0.0 );
190 SpinBox_Z->setValue( 0.0 );
192 SpinBox_Dx->setValue( 1.0 );
193 SpinBox_Dy->setValue( 1.0 );
194 SpinBox_Dz->setValue( 1.0 );
196 /* signals and slots connections */
197 connect( resetButton, SIGNAL (clicked() ), this, SLOT( onReset() ) );
198 connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
200 connect( SpinBox_X, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
201 connect( SpinBox_Y, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
202 connect( SpinBox_Z, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
203 connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
204 connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
205 connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
207 connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
209 connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
211 connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
212 connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
219 Destroys the object and frees any allocated resources
221 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
223 // no need to delete child widgets, Qt does it all for us
228 Custom handling of close event: erases preview
230 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
234 // Set the clipping plane back
235 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
236 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
237 aView3d->SetPlaneOn( myClippingPlane );
239 if (!myView->isCuttingPlane())
240 myAction->setOn( false );
242 QDialog::closeEvent( e );
247 Custom handling of show event: displays preview
249 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
251 ReserveClippingPlane();
253 QDialog::showEvent( e );
254 onPreview( PreviewChB->isChecked() );
259 Custom handling of hide event: erases preview
261 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
264 QDialog::hideEvent( e );
269 SLOT on close button click: erases preview and rejects dialog
271 void OCCViewer_ClippingDlg::ClickOnClose()
275 // Set the clipping plane back
276 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
277 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
278 aView3d->SetPlaneOn( myClippingPlane );
280 if (!myView->isCuttingPlane())
281 myAction->setOn( false );
288 SLOT on apply button click: sets cutting plane
290 void OCCViewer_ClippingDlg::ClickOnApply()
292 qApp->processEvents();
293 QApplication::setOverrideCursor( Qt::WaitCursor );
294 qApp->processEvents();
296 myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
297 SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
299 QApplication::restoreOverrideCursor();
303 ReserveClippingPlane();
307 SLOT on reset button click: sets default values
309 void OCCViewer_ClippingDlg::onReset()
312 SpinBox_X->setValue(0);
313 SpinBox_Y->setValue(0);
314 SpinBox_Z->setValue(0);
317 if ( PreviewChB->isChecked() )
325 SLOT on invert button click: inverts normal of cutting plane
327 void OCCViewer_ClippingDlg::onInvert()
329 double Dx = SpinBox_Dx->value();
330 double Dy = SpinBox_Dy->value();
331 double Dz = SpinBox_Dz->value();
334 SpinBox_Dx->setValue( -Dx );
335 SpinBox_Dy->setValue( -Dy );
336 SpinBox_Dz->setValue( -Dz );
339 if ( PreviewChB->isChecked() )
347 SLOT: called on mode changed
349 void OCCViewer_ClippingDlg::onModeChanged( int mode )
351 bool isUserMode = (mode==0);
353 TextLabelX->setEnabled( isUserMode );
354 TextLabelY->setEnabled( isUserMode );
355 TextLabelZ->setEnabled( isUserMode );
357 SpinBox_X->setEnabled( isUserMode );
358 SpinBox_Y->setEnabled( isUserMode );
359 SpinBox_Z->setEnabled( isUserMode );
361 TextLabelDx->setEnabled( isUserMode );
362 TextLabelDy->setEnabled( isUserMode );
363 TextLabelDz->setEnabled( isUserMode );
365 SpinBox_Dx->setEnabled( isUserMode );
366 SpinBox_Dy->setEnabled( isUserMode );
367 SpinBox_Dz->setEnabled( isUserMode );
372 double aDx = 0, aDy = 0, aDz = 0;
377 TextLabelZ->setEnabled( true );
378 SpinBox_Z->setEnabled( true );
379 SpinBox_Z->setFocus();
381 else if ( mode == 2 )
384 TextLabelX->setEnabled( true );
385 SpinBox_X->setEnabled( true );
386 SpinBox_X->setFocus();
388 else if ( mode == 3 )
391 TextLabelY->setEnabled( true );
392 SpinBox_Y->setEnabled( true );
393 SpinBox_Y->setFocus();
397 SpinBox_Dx->setValue( aDx );
398 SpinBox_Dy->setValue( aDy );
399 SpinBox_Dz->setValue( aDz );
402 if ( PreviewChB->isChecked() )
411 Displays preview of clipping plane
413 void OCCViewer_ClippingDlg::displayPreview()
415 if ( myBusy || !isValid() )
418 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
422 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
424 double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
425 aXMin = aYMin = aZMin = DBL_MAX;
426 aXMax = aYMax = aZMax = -DBL_MAX;
428 bool isFound = false;
429 AIS_ListOfInteractive aList;
430 ic->DisplayedObjects( aList );
431 for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
433 Handle(AIS_InteractiveObject) anObj = it.Value();
434 if ( !anObj.IsNull() && anObj->HasPresentation() &&
435 !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
437 Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
438 if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
441 double xmin, ymin, zmin, xmax, ymax, zmax;
442 aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
443 aXMin = QMIN( aXMin, xmin ); aXMax = QMAX( aXMax, xmax );
444 aYMin = QMIN( aYMin, ymin ); aYMax = QMAX( aYMax, ymax );
445 aZMin = QMIN( aZMin, zmin ); aZMax = QMAX( aZMax, zmax );
452 gp_Pnt aBasePnt( SpinBox_X->value(), SpinBox_Y->value(), SpinBox_Z->value() );
453 gp_Dir aNormal( SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
454 gp_Pnt aCenter = aBasePnt;
458 // compute clipping plane size
459 aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
460 double aDiag = aCenter.Distance(gp_Pnt(aXMax, aYMax, aZMax ))*2;
463 // compute clipping plane center ( redefine the base point )
464 IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
466 intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
467 if ( intersector.IsDone() && intersector.NbPoints() == 1 )
468 aBasePnt = intersector.Point( 1 );
471 myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
472 myPreviewPlane->SetSize( aSize, aSize );
474 // Deactivate clipping planes
475 myView->getViewPort()->getView()->SetPlaneOff();
477 ic->Display( myPreviewPlane, 1, -1, false );
478 ic->SetWidth( myPreviewPlane, 10, false );
479 ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
480 ic->SetTransparency( myPreviewPlane, 0.5, false );
481 ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
483 anOCCViewer->update();
488 Erases preview of clipping plane
490 void OCCViewer_ClippingDlg::erasePreview ()
492 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
496 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
498 if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
500 ic->Erase( myPreviewPlane, false, false );
501 ic->Remove( myPreviewPlane, false );
502 myPreviewPlane.Nullify();
505 anOCCViewer->update();
510 SLOT: called on value changes (co-ordinates of point or normal)
512 void OCCViewer_ClippingDlg::onValueChanged()
514 if ( PreviewChB->isChecked() )
523 SLOT: called on preview check box toggled
525 void OCCViewer_ClippingDlg::onPreview( bool on )
534 \return true if plane parameters are valid
536 bool OCCViewer_ClippingDlg::isValid()
538 return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
542 Remember the current clipping plane
544 void OCCViewer_ClippingDlg::ReserveClippingPlane()
546 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
547 if ( !aView3d.IsNull() )
549 aView3d->InitActivePlanes();
550 if ( aView3d->MoreActivePlanes() )
551 myClippingPlane = aView3d->ActivePlane();