]> SALOME platform Git repositories - modules/gui.git/blob - src/OCCViewer/OCCViewer_ClippingDlg.cxx
Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/gui.git] / src / OCCViewer / OCCViewer_ClippingDlg.cxx
1 // Copyright (C) 2005  CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "OCCViewer_ClippingDlg.h"
20
21 #include <QtxDblSpinBox.h>
22 #include <QtxAction.h>
23
24 #include "SUIT_Session.h"
25 #include "SUIT_ViewWindow.h"
26 #include "OCCViewer_ViewWindow.h"
27 #include "OCCViewer_ViewPort3d.h"
28
29 #include <V3d_View.hxx>
30 //#include <V3d.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>
38 #include <gp_Lin.hxx>
39 #include <gp_Pln.hxx>
40
41 // QT Includes
42 #include <qapplication.h>
43 #include <qgroupbox.h>
44 #include <qlayout.h>
45 #include <qlabel.h>
46 #include <qpushbutton.h>
47 #include <qcombobox.h>
48 #include <qcheckbox.h>
49
50 /*!
51   Constructor
52   \param view - view window
53   \param parent - parent widget
54   \param name - dialog name
55   \param modal - is this dialog modal
56   \param fl - flags
57 */
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 ),
60   myView( view )
61 {
62   setCaption( tr( "Clipping" ) );
63   
64   QVBoxLayout* topLayout = new QVBoxLayout( this );
65   topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
66   
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 );
77   
78   // Controls
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 )
84
85   TextLabelX = new QLabel( GroupPoint, "TextLabelX" );
86   TextLabelX->setText( tr("X:") );
87   GroupPointLayout->addWidget( TextLabelX, 0, 0 );
88   
89   SpinBox_X = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_X" );
90   SpinBox_X->setPrecision( precision );
91   GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
92
93   TextLabelY = new QLabel( GroupPoint, "TextLabelY" );
94   TextLabelY->setText( tr("Y:") );
95   GroupPointLayout->addWidget( TextLabelY, 0, 2 );
96
97   SpinBox_Y = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Y" );
98   SpinBox_Y->setPrecision( precision );
99   GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
100
101   TextLabelZ = new QLabel( GroupPoint, "TextLabelZ" );
102   TextLabelZ->setText( tr("Z:") );
103   GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
104
105   SpinBox_Z = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Z" );
106   SpinBox_Z->setPrecision( precision );
107   GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
108
109   resetButton  = new QPushButton( GroupPoint, "resetButton" );
110   resetButton->setText( tr( "Reset"  ) );
111   GroupPointLayout->addWidget( resetButton, 0, 6 );
112
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 );
123   
124   // Controls
125   TextLabelDx = new QLabel( GroupDirection, "TextLabelDx" );
126   TextLabelDx->setText( tr("Dx:") );
127   GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
128   
129   SpinBox_Dx = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dx" );
130   SpinBox_Dx->setPrecision( precision );
131   GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
132
133   TextLabelDy = new QLabel( GroupDirection, "TextLabelDy" );
134   TextLabelDy->setText( tr("Dy:") );
135   GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
136   
137   SpinBox_Dy = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dy" );
138   SpinBox_Dy->setPrecision( precision );
139   GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
140
141   TextLabelDz = new QLabel( GroupDirection, "TextLabelDz" );
142   TextLabelDz->setText( tr("Dz:") );
143   GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
144   
145   SpinBox_Dz = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dz" );
146   SpinBox_Dz->setPrecision( precision );
147   GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
148
149   invertButton  = new QPushButton( GroupDirection, "invertButton" );
150   invertButton->setText( tr( "Invert"  ) );
151   GroupDirectionLayout->addWidget( invertButton, 0, 6 );
152  
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 );
159   
160   /***************************************************************/
161   
162   PreviewChB = new QCheckBox( tr("Preview") ,this, "PreviewChB" );
163   PreviewChB->setChecked( true );
164   
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 );
172   
173   buttonApply = new QPushButton( GroupButtons, "buttonApply" );
174   buttonApply->setText( tr( "BUT_APPLY"  ) );
175   buttonApply->setAutoDefault( TRUE ); 
176   buttonApply->setDefault( TRUE );
177   GroupButtonsLayout->addWidget( buttonApply );
178   
179   GroupButtonsLayout->addStretch();
180   
181   buttonClose = new QPushButton( GroupButtons, "buttonClose" );
182   buttonClose->setText( tr( "BUT_CLOSE"  ) );
183   buttonClose->setAutoDefault( TRUE );
184   GroupButtonsLayout->addWidget( buttonClose );
185   /***************************************************************/
186   
187   topLayout->addWidget( GroupPoint );
188   topLayout->addWidget( GroupDirection );
189   
190   topLayout->addWidget( PreviewChB );
191
192   topLayout->addWidget( GroupButtons );
193
194   /* initializations */
195
196   SpinBox_X->setValue( 0.0 );
197   SpinBox_Y->setValue( 0.0 );
198   SpinBox_Z->setValue( 0.0 );
199
200   SpinBox_Dx->setValue( 1.0 );
201   SpinBox_Dy->setValue( 1.0 );
202   SpinBox_Dz->setValue( 1.0 );
203
204   /* signals and slots connections */
205   connect( resetButton,  SIGNAL (clicked() ), this, SLOT( onReset() ) );
206   connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
207
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() ) );
214    
215   connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
216
217   connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
218   
219   connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
220   connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
221   
222   myBusy = false;
223
224   connect(view, SIGNAL(Show( QShowEvent * )), this, SLOT(onViewShow()));
225   connect(view, SIGNAL(Hide( QHideEvent * )), this, SLOT(onViewHide()));
226 }
227
228 /*!
229   Destructor
230   Destroys the object and frees any allocated resources
231 */
232 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
233 {
234   // no need to delete child widgets, Qt does it all for us
235 }
236
237
238 /*!
239   Custom handling of close event: erases preview
240 */
241 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
242 {
243   erasePreview();
244   
245   // Set the clipping plane back
246   Handle(V3d_View) aView3d = myView->getViewPort()->getView();
247   if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
248     aView3d->SetPlaneOn( myClippingPlane );
249   
250   if (!myView->isCuttingPlane())
251     myAction->setOn( false );
252   
253   QDialog::closeEvent( e );
254 }
255
256
257 /*!
258   Custom handling of show event: displays preview
259 */
260 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
261 {
262   ReserveClippingPlane();
263   
264   QDialog::showEvent( e );
265   onPreview( PreviewChB->isChecked() );
266 }
267
268
269 /*!
270   Custom handling of hide event: erases preview
271 */
272 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
273 {
274   erasePreview();
275   QDialog::hideEvent( e );
276 }
277
278
279 /*!
280   SLOT on close button click: erases preview and rejects dialog
281 */
282 void OCCViewer_ClippingDlg::ClickOnClose()
283 {
284   erasePreview();
285
286   // Set the clipping plane back
287   Handle(V3d_View) aView3d = myView->getViewPort()->getView();
288   if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
289     aView3d->SetPlaneOn( myClippingPlane );
290
291   if (!myView->isCuttingPlane())
292     myAction->setOn( false );
293   
294   reject();
295 }
296
297
298 /*!
299   SLOT on apply button click: sets cutting plane
300 */
301 void OCCViewer_ClippingDlg::ClickOnApply()
302 {
303   qApp->processEvents();
304   QApplication::setOverrideCursor( Qt::WaitCursor );
305   qApp->processEvents();
306   
307   myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
308                                  SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
309   
310   QApplication::restoreOverrideCursor(); 
311   
312   erasePreview();
313   
314   ReserveClippingPlane();
315 }
316
317 /*!
318   SLOT on reset button click: sets default values
319 */
320 void OCCViewer_ClippingDlg::onReset()
321 {
322   myBusy = true;
323   SpinBox_X->setValue(0);
324   SpinBox_Y->setValue(0);
325   SpinBox_Z->setValue(0);
326   myBusy = false;
327
328   if ( PreviewChB->isChecked() )
329     {
330       erasePreview();
331       displayPreview();
332     }
333 }
334
335 /*!
336   SLOT on invert button click: inverts normal of cutting plane
337 */
338 void OCCViewer_ClippingDlg::onInvert()
339 {
340   double Dx = SpinBox_Dx->value();
341   double Dy = SpinBox_Dy->value();
342   double Dz = SpinBox_Dz->value();
343   
344   myBusy = true;
345   SpinBox_Dx->setValue( -Dx );
346   SpinBox_Dy->setValue( -Dy );
347   SpinBox_Dz->setValue( -Dz );
348   myBusy = false;
349
350   if ( PreviewChB->isChecked() )
351     {
352       erasePreview();
353       displayPreview();
354     }
355 }
356
357 /*!
358   SLOT: called on mode changed
359 */
360 void OCCViewer_ClippingDlg::onModeChanged( int mode )
361 {
362   bool isUserMode = (mode==0);
363   
364   TextLabelX->setEnabled( isUserMode );
365   TextLabelY->setEnabled( isUserMode );
366   TextLabelZ->setEnabled( isUserMode );
367
368   SpinBox_X->setEnabled( isUserMode );
369   SpinBox_Y->setEnabled( isUserMode );
370   SpinBox_Z->setEnabled( isUserMode );
371
372   TextLabelDx->setEnabled( isUserMode );
373   TextLabelDy->setEnabled( isUserMode );
374   TextLabelDz->setEnabled( isUserMode );
375
376   SpinBox_Dx->setEnabled( isUserMode );
377   SpinBox_Dy->setEnabled( isUserMode );
378   SpinBox_Dz->setEnabled( isUserMode );
379   
380   if ( isUserMode )
381     return;
382
383   double aDx = 0, aDy = 0, aDz = 0;
384
385   if ( mode == 1 )
386     {
387       aDz = 1;
388       TextLabelZ->setEnabled( true );
389       SpinBox_Z->setEnabled( true );
390       SpinBox_Z->setFocus();
391     }
392   else if ( mode == 2 )
393     {
394       aDx = 1;
395       TextLabelX->setEnabled( true );
396       SpinBox_X->setEnabled( true );
397       SpinBox_X->setFocus();
398     }
399   else if ( mode == 3 )
400     {
401       aDy = 1;
402       TextLabelY->setEnabled( true );
403       SpinBox_Y->setEnabled( true );
404       SpinBox_Y->setFocus();
405     }
406   
407   myBusy = true;
408   SpinBox_Dx->setValue( aDx );
409   SpinBox_Dy->setValue( aDy );
410   SpinBox_Dz->setValue( aDz );
411   myBusy = false;
412
413   if ( PreviewChB->isChecked() )
414     {
415       erasePreview();
416       displayPreview();
417     }
418 }
419
420
421 /*!
422   Displays preview of clipping plane
423 */
424 void OCCViewer_ClippingDlg::displayPreview()
425 {
426   if ( myBusy || !isValid() )
427     return;
428
429   OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
430   if (!anOCCViewer)
431     return;
432   
433   Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
434
435   double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
436   aXMin = aYMin = aZMin = DBL_MAX;
437   aXMax = aYMax = aZMax = -DBL_MAX;
438
439   bool isFound = false;
440   AIS_ListOfInteractive aList;
441   ic->DisplayedObjects( aList );
442   for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
443   {
444     Handle(AIS_InteractiveObject) anObj = it.Value();
445     if ( !anObj.IsNull() && anObj->HasPresentation() &&
446          !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
447     {
448       Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
449       if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
450       {
451         isFound = true;
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 );
457       }
458     }
459   }
460
461   double aSize = 50;
462   
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;
466   
467   if ( isFound )
468     {
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;
472       aSize = aDiag * 1.1;
473
474       // compute clipping plane center ( redefine the base point )
475       IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
476       
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 );
480     }
481   
482   myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
483   myPreviewPlane->SetSize( aSize, aSize );
484   
485   // Deactivate clipping planes
486   myView->getViewPort()->getView()->SetPlaneOff();
487
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 );
493   
494   anOCCViewer->update();
495 }
496
497
498 /*!
499   Erases preview of clipping plane
500 */
501 void OCCViewer_ClippingDlg::erasePreview ()
502 {
503   OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
504   if (!anOCCViewer)
505     return;
506   
507   Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
508   
509   if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
510     {
511       ic->Erase( myPreviewPlane, false, false );
512       ic->Remove( myPreviewPlane, false );
513       myPreviewPlane.Nullify();
514     }
515   
516   anOCCViewer->update();
517 }
518
519
520 /*!
521   SLOT: called on value changes (co-ordinates of point or normal)
522 */
523 void OCCViewer_ClippingDlg::onValueChanged()
524 {
525   if ( PreviewChB->isChecked() )
526     {
527       erasePreview();
528       displayPreview();
529     }
530 }
531
532
533 /*!
534   SLOT: called on preview check box toggled
535 */
536 void OCCViewer_ClippingDlg::onPreview( bool on )
537 {
538   erasePreview();
539
540   if ( on ) 
541     displayPreview();
542 }
543
544 /*!
545   \return true if plane parameters are valid
546 */
547 bool OCCViewer_ClippingDlg::isValid()
548 {
549   return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
550 }
551
552 /*!
553   Remember the current clipping plane
554 */
555 void OCCViewer_ClippingDlg::ReserveClippingPlane()
556 {
557   Handle(V3d_View) aView3d = myView->getViewPort()->getView();
558   if ( !aView3d.IsNull() )
559     {
560       aView3d->InitActivePlanes();
561       if ( aView3d->MoreActivePlanes() )
562         myClippingPlane = aView3d->ActivePlane();
563     }
564 }
565
566 void OCCViewer_ClippingDlg::onViewShow()
567 {
568   if(myAction->isOn())
569     show();
570   else
571     hide();
572 }
573
574 void OCCViewer_ClippingDlg::onViewHide()
575 {
576   hide();
577 }
578