Salome HOME
e11642888130939b0eebfcd40d84d6b2c8405742
[modules/gui.git] / src / OCCViewer / OCCViewer_ClippingDlg.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "OCCViewer_ClippingDlg.h"
24
25 #include <QtxDoubleSpinBox.h>
26 #include <QtxAction.h>
27
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"
34
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>
43 #include <gp_Lin.hxx>
44 #include <gp_Pln.hxx>
45
46 // QT Includes
47 #include <QApplication>
48 #include <QGroupBox>
49 #include <QHBoxLayout>
50 #include <QVBoxLayout>
51 #include <QGridLayout>
52 #include <QLabel>
53 #include <QPushButton>
54 #include <QComboBox>
55 #include <QCheckBox>
56
57 /*!
58   Constructor
59   \param view - view window
60   \param parent - parent widget
61   \param name - dialog name
62   \param modal - is this dialog modal
63   \param fl - flags
64 */
65 OCCViewer_ClippingDlg::OCCViewer_ClippingDlg( OCCViewer_ViewWindow* view, const char* name, bool modal, Qt::WindowFlags fl )
66 : QDialog( view, Qt::WindowTitleHint | Qt::WindowSystemMenuHint ),
67   myView( view )
68 {
69   setObjectName( "OCCViewer_ClippingDlg" );
70   setModal( modal );
71
72   setWindowTitle( tr( "Clipping" ) );
73   
74   QVBoxLayout* topLayout = new QVBoxLayout( this );
75   topLayout->setMargin( 11 ); topLayout->setSpacing( 6 );
76   
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 );
85   
86   // Controls
87   const double min = -1e+7;
88   const double max =  1e+7;
89   const double step = 5;
90   const int precision = -7;
91
92   TextLabelX = new QLabel( GroupPoint );
93   TextLabelX->setObjectName( "TextLabelX" );
94   TextLabelX->setText( tr("X:") );
95   GroupPointLayout->addWidget( TextLabelX, 0, 0 );
96   
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 );
101
102   TextLabelY = new QLabel( GroupPoint );
103   TextLabelY->setObjectName( "TextLabelY" );
104   TextLabelY->setText( tr("Y:") );
105   GroupPointLayout->addWidget( TextLabelY, 0, 2 );
106
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 );
111
112   TextLabelZ = new QLabel( GroupPoint );
113   TextLabelZ->setObjectName( "TextLabelZ" );
114   TextLabelZ->setText( tr("Z:") );
115   GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
116
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 );
121
122   resetButton  = new QPushButton( GroupPoint );
123   resetButton->setObjectName( "resetButton" );
124   resetButton->setText( tr( "Reset"  ) );
125   GroupPointLayout->addWidget( resetButton, 0, 6 );
126
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 );
135   
136   // Controls
137   TextLabelDx = new QLabel( GroupDirection );
138   TextLabelDx->setObjectName( "TextLabelDx" );
139   TextLabelDx->setText( tr("Dx:") );
140   GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
141   
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 );
146
147   TextLabelDy = new QLabel( GroupDirection );
148   TextLabelDy->setObjectName( "TextLabelDy" );
149   TextLabelDy->setText( tr("Dy:") );
150   GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
151   
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 );
156
157   TextLabelDz = new QLabel( GroupDirection );
158   TextLabelDz->setObjectName( "TextLabelDz" );
159   TextLabelDz->setText( tr("Dz:") );
160   GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
161   
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 );
166
167   invertButton  = new QPushButton( GroupDirection );
168   invertButton->setObjectName( "invertButton" );
169   invertButton->setText( tr( "Invert"  ) );
170   GroupDirectionLayout->addWidget( invertButton, 0, 6 );
171  
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 );
179   
180   /***************************************************************/
181   
182   PreviewChB = new QCheckBox( tr("Preview") ,this );
183   PreviewChB->setObjectName( "PreviewChB" );
184   PreviewChB->setChecked( true );
185   
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 );
192   
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 );
199   
200   GroupButtonsLayout->addStretch();
201   
202   buttonClose = new QPushButton( GroupButtons );
203   buttonClose->setObjectName( "buttonClose" );
204   buttonClose->setText( tr( "BUT_CLOSE"  ) );
205   buttonClose->setAutoDefault( TRUE );
206   GroupButtonsLayout->addWidget( buttonClose );
207
208   /***************************************************************/
209   
210   topLayout->addWidget( GroupPoint );
211   topLayout->addWidget( GroupDirection );
212   
213   topLayout->addWidget( PreviewChB );
214
215   topLayout->addWidget( GroupButtons );
216
217   /* initializations */
218
219   SpinBox_X->setValue( 0.0 );
220   SpinBox_Y->setValue( 0.0 );
221   SpinBox_Z->setValue( 0.0 );
222
223   SpinBox_Dx->setValue( 1.0 );
224   SpinBox_Dy->setValue( 1.0 );
225   SpinBox_Dz->setValue( 1.0 );
226
227   /* signals and slots connections */
228   connect( resetButton,  SIGNAL (clicked() ), this, SLOT( onReset() ) );
229   connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
230
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() ) );
237    
238   connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
239
240   connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
241   
242   connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
243   connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
244   
245   myBusy = false;
246
247   connect(view, SIGNAL(Show( QShowEvent * )), this, SLOT(onViewShow()));
248   connect(view, SIGNAL(Hide( QHideEvent * )), this, SLOT(onViewHide()));
249 }
250
251 /*!
252   Destructor
253   Destroys the object and frees any allocated resources
254 */
255 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
256 {
257   // no need to delete child widgets, Qt does it all for us
258 }
259
260
261 /*!
262   Custom handling of close event: erases preview
263 */
264 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
265 {
266   erasePreview();
267   
268   // Set the clipping plane back
269   /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
270   if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
271   aView3d->SetPlaneOn( myClippingPlane );*/
272   
273   myAction->setChecked( false );
274   
275   QDialog::closeEvent( e );
276 }
277
278
279 /*!
280   Custom handling of show event: displays preview
281 */
282 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
283 {
284   //ReserveClippingPlane();
285   
286   QDialog::showEvent( e );
287   onPreview( PreviewChB->isChecked() );
288 }
289
290
291 /*!
292   Custom handling of hide event: erases preview
293 */
294 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
295 {
296   erasePreview();
297   QDialog::hideEvent( e );
298 }
299
300
301 /*!
302   SLOT on close button click: erases preview and rejects dialog
303 */
304 void OCCViewer_ClippingDlg::ClickOnClose()
305 {
306   erasePreview();
307
308   // Set the clipping plane back
309   /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
310   if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
311     aView3d->SetPlaneOn( myClippingPlane );
312   */
313   myAction->setChecked( false );
314   
315   reject();
316 }
317
318
319 /*!
320   SLOT on apply button click: sets cutting plane
321 */
322 void OCCViewer_ClippingDlg::ClickOnApply()
323 {
324   qApp->processEvents();
325   QApplication::setOverrideCursor( Qt::WaitCursor );
326   qApp->processEvents();
327   
328   myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
329                                  SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
330   
331   QApplication::restoreOverrideCursor(); 
332   
333   erasePreview();
334   
335   //ReserveClippingPlane();
336 }
337
338 /*!
339   SLOT on reset button click: sets default values
340 */
341 void OCCViewer_ClippingDlg::onReset()
342 {
343   myBusy = true;
344   SpinBox_X->setValue(0);
345   SpinBox_Y->setValue(0);
346   SpinBox_Z->setValue(0);
347   myBusy = false;
348
349   if ( PreviewChB->isChecked() )
350     {
351       erasePreview();
352       displayPreview();
353     }
354 }
355
356 /*!
357   SLOT on invert button click: inverts normal of cutting plane
358 */
359 void OCCViewer_ClippingDlg::onInvert()
360 {
361   double Dx = SpinBox_Dx->value();
362   double Dy = SpinBox_Dy->value();
363   double Dz = SpinBox_Dz->value();
364   
365   myBusy = true;
366   SpinBox_Dx->setValue( -Dx );
367   SpinBox_Dy->setValue( -Dy );
368   SpinBox_Dz->setValue( -Dz );
369   myBusy = false;
370
371   if ( PreviewChB->isChecked() )
372     {
373       erasePreview();
374       displayPreview();
375     }
376 }
377
378 /*!
379   SLOT: called on mode changed
380 */
381 void OCCViewer_ClippingDlg::onModeChanged( int mode )
382 {
383   bool isUserMode = (mode==0);
384   
385   TextLabelX->setEnabled( isUserMode );
386   TextLabelY->setEnabled( isUserMode );
387   TextLabelZ->setEnabled( isUserMode );
388
389   SpinBox_X->setEnabled( isUserMode );
390   SpinBox_Y->setEnabled( isUserMode );
391   SpinBox_Z->setEnabled( isUserMode );
392
393   TextLabelDx->setEnabled( isUserMode );
394   TextLabelDy->setEnabled( isUserMode );
395   TextLabelDz->setEnabled( isUserMode );
396
397   SpinBox_Dx->setEnabled( isUserMode );
398   SpinBox_Dy->setEnabled( isUserMode );
399   SpinBox_Dz->setEnabled( isUserMode );
400   
401   if ( isUserMode )
402     return;
403
404   double aDx = 0, aDy = 0, aDz = 0;
405
406   if ( mode == 1 )
407     {
408       aDz = 1;
409       TextLabelZ->setEnabled( true );
410       SpinBox_Z->setEnabled( true );
411       SpinBox_Z->setFocus();
412     }
413   else if ( mode == 2 )
414     {
415       aDx = 1;
416       TextLabelX->setEnabled( true );
417       SpinBox_X->setEnabled( true );
418       SpinBox_X->setFocus();
419     }
420   else if ( mode == 3 )
421     {
422       aDy = 1;
423       TextLabelY->setEnabled( true );
424       SpinBox_Y->setEnabled( true );
425       SpinBox_Y->setFocus();
426     }
427   
428   myBusy = true;
429   SpinBox_Dx->setValue( aDx );
430   SpinBox_Dy->setValue( aDy );
431   SpinBox_Dz->setValue( aDz );
432   myBusy = false;
433
434   if ( PreviewChB->isChecked() )
435     {
436       erasePreview();
437       displayPreview();
438     }
439 }
440
441
442 /*!
443   Displays preview of clipping plane
444 */
445 void OCCViewer_ClippingDlg::displayPreview()
446 {
447   if ( myBusy || !isValid() )
448     return;
449
450   OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
451   if (!anOCCViewer)
452     return;
453   
454   Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
455
456   double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
457   aXMin = aYMin = aZMin = DBL_MAX;
458   aXMax = aYMax = aZMax = -DBL_MAX;
459
460   bool isFound = false;
461   AIS_ListOfInteractive aList;
462   ic->DisplayedObjects( aList );
463   for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
464   {
465     Handle(AIS_InteractiveObject) anObj = it.Value();
466     if ( !anObj.IsNull() && anObj->HasPresentation() &&
467          !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
468     {
469       Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
470       if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
471       {
472         isFound = true;
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 );
478       }
479     }
480   }
481
482   double aSize = 50;
483   
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;
487   
488   if ( isFound )
489     {
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;
493       aSize = aDiag * 1.1;
494
495       // compute clipping plane center ( redefine the base point )
496       IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
497       
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 );
501     }
502   
503   myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
504   myPreviewPlane->SetSize( aSize, aSize );
505   
506   // Deactivate clipping planes
507   //myView->getViewPort()->getView()->SetPlaneOff();
508   //myView->setPlaneOff();
509
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 );
515   
516   anOCCViewer->update();
517 }
518
519
520 /*!
521   Erases preview of clipping plane
522 */
523 void OCCViewer_ClippingDlg::erasePreview ()
524 {
525   OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
526   if (!anOCCViewer)
527     return;
528   
529   Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
530   
531   if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
532     {
533       ic->Erase( myPreviewPlane, false, false );
534       ic->Remove( myPreviewPlane, false );
535       myPreviewPlane.Nullify();
536     }
537   
538   anOCCViewer->update();
539 }
540
541
542 /*!
543   SLOT: called on value changes (co-ordinates of point or normal)
544 */
545 void OCCViewer_ClippingDlg::onValueChanged()
546 {
547   if ( PreviewChB->isChecked() )
548     {
549       erasePreview();
550       displayPreview();
551     }
552 }
553
554
555 /*!
556   SLOT: called on preview check box toggled
557 */
558 void OCCViewer_ClippingDlg::onPreview( bool on )
559 {
560   erasePreview();
561
562   if ( on ) 
563     displayPreview();
564 }
565
566 /*!
567   \return true if plane parameters are valid
568 */
569 bool OCCViewer_ClippingDlg::isValid()
570 {
571   return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
572 }
573
574 /*!
575   Remember the current clipping plane
576 */
577 void OCCViewer_ClippingDlg::ReserveClippingPlane()
578 {
579   /*Handle(V3d_View) aView3d = myView->getViewPort()->getView();
580   if ( !aView3d.IsNull() )
581     {
582       aView3d->InitActivePlanes();
583       if ( aView3d->MoreActivePlanes() )
584         myClippingPlane = aView3d->ActivePlane();
585         }*/
586 }
587
588 void OCCViewer_ClippingDlg::onViewShow()
589 {
590   if(myAction->isChecked())
591     show();
592   else
593     hide();
594 }
595
596 void OCCViewer_ClippingDlg::onViewHide()
597 {
598   hide();
599 }
600