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/ or email : webmaster.salome@opencascade.com
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+16;
80 const double max = 1e+16;
81 const double step = 5;
82 const int precision = -6; // PAL12789. Minus is for using 'g' double->string conversion specifier,
83 // see QtxDblSpinBox::mapValueToText( double v )
85 TextLabelX = new QLabel( GroupPoint, "TextLabelX" );
86 TextLabelX->setText( tr("X:") );
87 GroupPointLayout->addWidget( TextLabelX, 0, 0 );
89 SpinBox_X = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_X" );
90 SpinBox_X->setPrecision( precision );
91 GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
93 TextLabelY = new QLabel( GroupPoint, "TextLabelY" );
94 TextLabelY->setText( tr("Y:") );
95 GroupPointLayout->addWidget( TextLabelY, 0, 2 );
97 SpinBox_Y = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Y" );
98 SpinBox_Y->setPrecision( precision );
99 GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
101 TextLabelZ = new QLabel( GroupPoint, "TextLabelZ" );
102 TextLabelZ->setText( tr("Z:") );
103 GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
105 SpinBox_Z = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Z" );
106 SpinBox_Z->setPrecision( precision );
107 GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
109 resetButton = new QPushButton( GroupPoint, "resetButton" );
110 resetButton->setText( tr( "Reset" ) );
111 GroupPointLayout->addWidget( resetButton, 0, 6 );
113 /***************************************************************/
114 GroupDirection = new QGroupBox( this, "GroupDirection" );
115 GroupDirection->setTitle( tr("Direction") );
116 GroupDirection->setColumnLayout(0, Qt::Vertical );
117 GroupDirection->layout()->setSpacing( 0 );
118 GroupDirection->layout()->setMargin( 0 );
119 QGridLayout* GroupDirectionLayout = new QGridLayout( GroupDirection->layout() );
120 GroupDirectionLayout->setAlignment( Qt::AlignTop );
121 GroupDirectionLayout->setSpacing( 6 );
122 GroupDirectionLayout->setMargin( 11 );
125 TextLabelDx = new QLabel( GroupDirection, "TextLabelDx" );
126 TextLabelDx->setText( tr("Dx:") );
127 GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
129 SpinBox_Dx = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dx" );
130 SpinBox_Dx->setPrecision( precision );
131 GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
133 TextLabelDy = new QLabel( GroupDirection, "TextLabelDy" );
134 TextLabelDy->setText( tr("Dy:") );
135 GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
137 SpinBox_Dy = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dy" );
138 SpinBox_Dy->setPrecision( precision );
139 GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
141 TextLabelDz = new QLabel( GroupDirection, "TextLabelDz" );
142 TextLabelDz->setText( tr("Dz:") );
143 GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
145 SpinBox_Dz = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dz" );
146 SpinBox_Dz->setPrecision( precision );
147 GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
149 invertButton = new QPushButton( GroupDirection, "invertButton" );
150 invertButton->setText( tr( "Invert" ) );
151 GroupDirectionLayout->addWidget( invertButton, 0, 6 );
153 DirectionCB = new QComboBox( GroupDirection, "DirectionCB" );
154 DirectionCB->insertItem(tr("CUSTOM"));
155 DirectionCB->insertItem(tr("||X-Y"));
156 DirectionCB->insertItem(tr("||Y-Z"));
157 DirectionCB->insertItem(tr("||Z-X"));
158 GroupDirectionLayout->addMultiCellWidget( DirectionCB, 1, 1, 0, 5 );
160 /***************************************************************/
162 PreviewChB = new QCheckBox( tr("Preview") ,this, "PreviewChB" );
163 PreviewChB->setChecked( true );
165 /***************************************************************/
166 QGroupBox* GroupButtons = new QGroupBox( this, "GroupButtons" );
167 GroupButtons->setColumnLayout(0, Qt::Vertical );
168 GroupButtons->layout()->setMargin( 0 ); GroupButtons->layout()->setSpacing( 0 );
169 QHBoxLayout* GroupButtonsLayout = new QHBoxLayout( GroupButtons->layout() );
170 GroupButtonsLayout->setAlignment( Qt::AlignTop );
171 GroupButtonsLayout->setMargin( 11 ); GroupButtonsLayout->setSpacing( 6 );
173 buttonApply = new QPushButton( GroupButtons, "buttonApply" );
174 buttonApply->setText( tr( "BUT_APPLY" ) );
175 buttonApply->setAutoDefault( TRUE );
176 buttonApply->setDefault( TRUE );
177 GroupButtonsLayout->addWidget( buttonApply );
179 GroupButtonsLayout->addStretch();
181 buttonClose = new QPushButton( GroupButtons, "buttonClose" );
182 buttonClose->setText( tr( "BUT_CLOSE" ) );
183 buttonClose->setAutoDefault( TRUE );
184 GroupButtonsLayout->addWidget( buttonClose );
185 /***************************************************************/
187 topLayout->addWidget( GroupPoint );
188 topLayout->addWidget( GroupDirection );
190 topLayout->addWidget( PreviewChB );
192 topLayout->addWidget( GroupButtons );
194 /* initializations */
196 SpinBox_X->setValue( 0.0 );
197 SpinBox_Y->setValue( 0.0 );
198 SpinBox_Z->setValue( 0.0 );
200 SpinBox_Dx->setValue( 1.0 );
201 SpinBox_Dy->setValue( 1.0 );
202 SpinBox_Dz->setValue( 1.0 );
204 /* signals and slots connections */
205 connect( resetButton, SIGNAL (clicked() ), this, SLOT( onReset() ) );
206 connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
208 connect( SpinBox_X, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
209 connect( SpinBox_Y, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
210 connect( SpinBox_Z, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
211 connect( SpinBox_Dx, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
212 connect( SpinBox_Dy, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
213 connect( SpinBox_Dz, SIGNAL ( valueChanged( double ) ), this, SLOT( onValueChanged() ) );
215 connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
217 connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
219 connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
220 connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
224 connect(view, SIGNAL(Show( QShowEvent * )), this, SLOT(onViewShow()));
225 connect(view, SIGNAL(Hide( QHideEvent * )), this, SLOT(onViewHide()));
230 Destroys the object and frees any allocated resources
232 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
234 // no need to delete child widgets, Qt does it all for us
239 Custom handling of close event: erases preview
241 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
245 // Set the clipping plane back
246 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
247 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
248 aView3d->SetPlaneOn( myClippingPlane );
250 if (!myView->isCuttingPlane())
251 myAction->setOn( false );
253 QDialog::closeEvent( e );
258 Custom handling of show event: displays preview
260 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
262 ReserveClippingPlane();
264 QDialog::showEvent( e );
265 onPreview( PreviewChB->isChecked() );
270 Custom handling of hide event: erases preview
272 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
275 QDialog::hideEvent( e );
280 SLOT on close button click: erases preview and rejects dialog
282 void OCCViewer_ClippingDlg::ClickOnClose()
286 // Set the clipping plane back
287 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
288 if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
289 aView3d->SetPlaneOn( myClippingPlane );
291 if (!myView->isCuttingPlane())
292 myAction->setOn( false );
299 SLOT on apply button click: sets cutting plane
301 void OCCViewer_ClippingDlg::ClickOnApply()
303 qApp->processEvents();
304 QApplication::setOverrideCursor( Qt::WaitCursor );
305 qApp->processEvents();
307 myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
308 SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
310 QApplication::restoreOverrideCursor();
314 ReserveClippingPlane();
318 SLOT on reset button click: sets default values
320 void OCCViewer_ClippingDlg::onReset()
323 SpinBox_X->setValue(0);
324 SpinBox_Y->setValue(0);
325 SpinBox_Z->setValue(0);
328 if ( PreviewChB->isChecked() )
336 SLOT on invert button click: inverts normal of cutting plane
338 void OCCViewer_ClippingDlg::onInvert()
340 double Dx = SpinBox_Dx->value();
341 double Dy = SpinBox_Dy->value();
342 double Dz = SpinBox_Dz->value();
345 SpinBox_Dx->setValue( -Dx );
346 SpinBox_Dy->setValue( -Dy );
347 SpinBox_Dz->setValue( -Dz );
350 if ( PreviewChB->isChecked() )
358 SLOT: called on mode changed
360 void OCCViewer_ClippingDlg::onModeChanged( int mode )
362 bool isUserMode = (mode==0);
364 TextLabelX->setEnabled( isUserMode );
365 TextLabelY->setEnabled( isUserMode );
366 TextLabelZ->setEnabled( isUserMode );
368 SpinBox_X->setEnabled( isUserMode );
369 SpinBox_Y->setEnabled( isUserMode );
370 SpinBox_Z->setEnabled( isUserMode );
372 TextLabelDx->setEnabled( isUserMode );
373 TextLabelDy->setEnabled( isUserMode );
374 TextLabelDz->setEnabled( isUserMode );
376 SpinBox_Dx->setEnabled( isUserMode );
377 SpinBox_Dy->setEnabled( isUserMode );
378 SpinBox_Dz->setEnabled( isUserMode );
383 double aDx = 0, aDy = 0, aDz = 0;
388 TextLabelZ->setEnabled( true );
389 SpinBox_Z->setEnabled( true );
390 SpinBox_Z->setFocus();
392 else if ( mode == 2 )
395 TextLabelX->setEnabled( true );
396 SpinBox_X->setEnabled( true );
397 SpinBox_X->setFocus();
399 else if ( mode == 3 )
402 TextLabelY->setEnabled( true );
403 SpinBox_Y->setEnabled( true );
404 SpinBox_Y->setFocus();
408 SpinBox_Dx->setValue( aDx );
409 SpinBox_Dy->setValue( aDy );
410 SpinBox_Dz->setValue( aDz );
413 if ( PreviewChB->isChecked() )
422 Displays preview of clipping plane
424 void OCCViewer_ClippingDlg::displayPreview()
426 if ( myBusy || !isValid() )
429 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
433 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
435 double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
436 aXMin = aYMin = aZMin = DBL_MAX;
437 aXMax = aYMax = aZMax = -DBL_MAX;
439 bool isFound = false;
440 AIS_ListOfInteractive aList;
441 ic->DisplayedObjects( aList );
442 for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
444 Handle(AIS_InteractiveObject) anObj = it.Value();
445 if ( !anObj.IsNull() && anObj->HasPresentation() &&
446 !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
448 Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
449 if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
452 double xmin, ymin, zmin, xmax, ymax, zmax;
453 aPrs->MinMaxValues( xmin, ymin, zmin, xmax, ymax, zmax );
454 aXMin = QMIN( aXMin, xmin ); aXMax = QMAX( aXMax, xmax );
455 aYMin = QMIN( aYMin, ymin ); aYMax = QMAX( aYMax, ymax );
456 aZMin = QMIN( aZMin, zmin ); aZMax = QMAX( aZMax, zmax );
463 gp_Pnt aBasePnt( SpinBox_X->value(), SpinBox_Y->value(), SpinBox_Z->value() );
464 gp_Dir aNormal( SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
465 gp_Pnt aCenter = aBasePnt;
469 // compute clipping plane size
470 aCenter = gp_Pnt( ( aXMin + aXMax ) / 2, ( aYMin + aYMax ) / 2, ( aZMin + aZMax ) / 2 );
471 double aDiag = aCenter.Distance(gp_Pnt(aXMax, aYMax, aZMax ))*2;
474 // compute clipping plane center ( redefine the base point )
475 IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
477 intersector.Perform( gp_Lin( aCenter, aNormal), gp_Pln( aBasePnt, aNormal), Precision::Confusion() );
478 if ( intersector.IsDone() && intersector.NbPoints() == 1 )
479 aBasePnt = intersector.Point( 1 );
482 myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
483 myPreviewPlane->SetSize( aSize, aSize );
485 // Deactivate clipping planes
486 myView->getViewPort()->getView()->SetPlaneOff();
488 ic->Display( myPreviewPlane, 1, -1, false );
489 ic->SetWidth( myPreviewPlane, 10, false );
490 ic->SetMaterial( myPreviewPlane, Graphic3d_NOM_PLASTIC, false );
491 ic->SetTransparency( myPreviewPlane, 0.5, false );
492 ic->SetColor( myPreviewPlane, Quantity_Color( 85 / 255., 85 / 255., 255 / 255., Quantity_TOC_RGB ), false );
494 anOCCViewer->update();
499 Erases preview of clipping plane
501 void OCCViewer_ClippingDlg::erasePreview ()
503 OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
507 Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
509 if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
511 ic->Erase( myPreviewPlane, false, false );
512 ic->Remove( myPreviewPlane, false );
513 myPreviewPlane.Nullify();
516 anOCCViewer->update();
521 SLOT: called on value changes (co-ordinates of point or normal)
523 void OCCViewer_ClippingDlg::onValueChanged()
525 if ( PreviewChB->isChecked() )
534 SLOT: called on preview check box toggled
536 void OCCViewer_ClippingDlg::onPreview( bool on )
545 \return true if plane parameters are valid
547 bool OCCViewer_ClippingDlg::isValid()
549 return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
553 Remember the current clipping plane
555 void OCCViewer_ClippingDlg::ReserveClippingPlane()
557 Handle(V3d_View) aView3d = myView->getViewPort()->getView();
558 if ( !aView3d.IsNull() )
560 aView3d->InitActivePlanes();
561 if ( aView3d->MoreActivePlanes() )
562 myClippingPlane = aView3d->ActivePlane();
566 void OCCViewer_ClippingDlg::onViewShow()
574 void OCCViewer_ClippingDlg::onViewHide()