Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[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/
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+06;
80   const double max =  1e+06;
81   const double step = 5;
82
83   TextLabelX = new QLabel( GroupPoint, "TextLabelX" );
84   TextLabelX->setText( tr("X:") );
85   GroupPointLayout->addWidget( TextLabelX, 0, 0 );
86   
87   SpinBox_X = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_X" );
88   GroupPointLayout->addWidget( SpinBox_X, 0, 1 );
89
90   TextLabelY = new QLabel( GroupPoint, "TextLabelY" );
91   TextLabelY->setText( tr("Y:") );
92   GroupPointLayout->addWidget( TextLabelY, 0, 2 );
93
94   SpinBox_Y = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Y" );
95   GroupPointLayout->addWidget( SpinBox_Y, 0, 3 );
96
97   TextLabelZ = new QLabel( GroupPoint, "TextLabelZ" );
98   TextLabelZ->setText( tr("Z:") );
99   GroupPointLayout->addWidget( TextLabelZ, 0, 4 );
100
101   SpinBox_Z = new QtxDblSpinBox( min, max, step, GroupPoint, "SpinBox_Z" );
102   GroupPointLayout->addWidget( SpinBox_Z, 0, 5 );
103
104   resetButton  = new QPushButton( GroupPoint, "resetButton" );
105   resetButton->setText( tr( "Reset"  ) );
106   GroupPointLayout->addWidget( resetButton, 0, 6 );
107
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 );
118   
119   // Controls
120   TextLabelDx = new QLabel( GroupDirection, "TextLabelDx" );
121   TextLabelDx->setText( tr("Dx:") );
122   GroupDirectionLayout->addWidget( TextLabelDx, 0, 0 );
123   
124   SpinBox_Dx = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dx" );
125   GroupDirectionLayout->addWidget( SpinBox_Dx, 0, 1 );
126
127   TextLabelDy = new QLabel( GroupDirection, "TextLabelDy" );
128   TextLabelDy->setText( tr("Dy:") );
129   GroupDirectionLayout->addWidget( TextLabelDy, 0, 2 );
130   
131   SpinBox_Dy = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dy" );
132   GroupDirectionLayout->addWidget( SpinBox_Dy, 0, 3 );
133
134   TextLabelDz = new QLabel( GroupDirection, "TextLabelDz" );
135   TextLabelDz->setText( tr("Dz:") );
136   GroupDirectionLayout->addWidget( TextLabelDz, 0, 4 );
137   
138   SpinBox_Dz = new QtxDblSpinBox( min, max, step, GroupDirection, "SpinBox_Dz" );
139   GroupDirectionLayout->addWidget( SpinBox_Dz, 0, 5 );
140
141   invertButton  = new QPushButton( GroupDirection, "invertButton" );
142   invertButton->setText( tr( "Invert"  ) );
143   GroupDirectionLayout->addWidget( invertButton, 0, 6 );
144  
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 );
151   
152   /***************************************************************/
153   
154   PreviewChB = new QCheckBox( tr("Preview") ,this, "PreviewChB" );
155   PreviewChB->setChecked( true );
156   
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 );
164   
165   buttonApply = new QPushButton( GroupButtons, "buttonApply" );
166   buttonApply->setText( tr( "BUT_APPLY"  ) );
167   buttonApply->setAutoDefault( TRUE ); 
168   buttonApply->setDefault( TRUE );
169   GroupButtonsLayout->addWidget( buttonApply );
170   
171   GroupButtonsLayout->addStretch();
172   
173   buttonClose = new QPushButton( GroupButtons, "buttonClose" );
174   buttonClose->setText( tr( "BUT_CLOSE"  ) );
175   buttonClose->setAutoDefault( TRUE );
176   GroupButtonsLayout->addWidget( buttonClose );
177   /***************************************************************/
178   
179   topLayout->addWidget( GroupPoint );
180   topLayout->addWidget( GroupDirection );
181   
182   topLayout->addWidget( PreviewChB );
183
184   topLayout->addWidget( GroupButtons );
185
186   /* initializations */
187
188   SpinBox_X->setValue( 0.0 );
189   SpinBox_Y->setValue( 0.0 );
190   SpinBox_Z->setValue( 0.0 );
191
192   SpinBox_Dx->setValue( 1.0 );
193   SpinBox_Dy->setValue( 1.0 );
194   SpinBox_Dz->setValue( 1.0 );
195
196   /* signals and slots connections */
197   connect( resetButton,  SIGNAL (clicked() ), this, SLOT( onReset() ) );
198   connect( invertButton, SIGNAL (clicked() ), this, SLOT( onInvert() ) ) ;
199
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() ) );
206    
207   connect( DirectionCB, SIGNAL ( activated ( int ) ), this, SLOT( onModeChanged( int ) ) ) ;
208
209   connect( PreviewChB, SIGNAL ( toggled ( bool ) ), this, SLOT( onPreview( bool ) ) ) ;
210   
211   connect( buttonClose, SIGNAL( clicked() ), this, SLOT( ClickOnClose() ) ) ;
212   connect( buttonApply, SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) );
213   
214   myBusy = false;
215 }
216
217 /*!
218   Destructor
219   Destroys the object and frees any allocated resources
220 */
221 OCCViewer_ClippingDlg::~ OCCViewer_ClippingDlg()
222 {
223   // no need to delete child widgets, Qt does it all for us
224 }
225
226
227 /*!
228   Custom handling of close event: erases preview
229 */
230 void OCCViewer_ClippingDlg::closeEvent( QCloseEvent* e )
231 {
232   erasePreview();
233   
234   // Set the clipping plane back
235   Handle(V3d_View) aView3d = myView->getViewPort()->getView();
236   if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
237     aView3d->SetPlaneOn( myClippingPlane );
238   
239   if (!myView->isCuttingPlane())
240     myAction->setOn( false );
241   
242   QDialog::closeEvent( e );
243 }
244
245
246 /*!
247   Custom handling of show event: displays preview
248 */
249 void OCCViewer_ClippingDlg::showEvent( QShowEvent* e )
250 {
251   ReserveClippingPlane();
252   
253   QDialog::showEvent( e );
254   onPreview( PreviewChB->isChecked() );
255 }
256
257
258 /*!
259   Custom handling of hide event: erases preview
260 */
261 void OCCViewer_ClippingDlg::hideEvent( QHideEvent* e )
262 {
263   erasePreview();
264   QDialog::hideEvent( e );
265 }
266
267
268 /*!
269   SLOT on close button click: erases preview and rejects dialog
270 */
271 void OCCViewer_ClippingDlg::ClickOnClose()
272 {
273   erasePreview();
274
275   // Set the clipping plane back
276   Handle(V3d_View) aView3d = myView->getViewPort()->getView();
277   if ( !aView3d.IsNull() && !myClippingPlane.IsNull() )
278     aView3d->SetPlaneOn( myClippingPlane );
279
280   if (!myView->isCuttingPlane())
281     myAction->setOn( false );
282   
283   reject();
284 }
285
286
287 /*!
288   SLOT on apply button click: sets cutting plane
289 */
290 void OCCViewer_ClippingDlg::ClickOnApply()
291 {
292   qApp->processEvents();
293   QApplication::setOverrideCursor( Qt::WaitCursor );
294   qApp->processEvents();
295   
296   myView->setCuttingPlane( true, SpinBox_X->value() , SpinBox_Y->value() , SpinBox_Z->value(),
297                                  SpinBox_Dx->value(), SpinBox_Dy->value(), SpinBox_Dz->value() );
298   
299   QApplication::restoreOverrideCursor(); 
300   
301   erasePreview();
302   
303   ReserveClippingPlane();
304 }
305
306 /*!
307   SLOT on reset button click: sets default values
308 */
309 void OCCViewer_ClippingDlg::onReset()
310 {
311   myBusy = true;
312   SpinBox_X->setValue(0);
313   SpinBox_Y->setValue(0);
314   SpinBox_Z->setValue(0);
315   myBusy = false;
316
317   if ( PreviewChB->isChecked() )
318     {
319       erasePreview();
320       displayPreview();
321     }
322 }
323
324 /*!
325   SLOT on invert button click: inverts normal of cutting plane
326 */
327 void OCCViewer_ClippingDlg::onInvert()
328 {
329   double Dx = SpinBox_Dx->value();
330   double Dy = SpinBox_Dy->value();
331   double Dz = SpinBox_Dz->value();
332   
333   myBusy = true;
334   SpinBox_Dx->setValue( -Dx );
335   SpinBox_Dy->setValue( -Dy );
336   SpinBox_Dz->setValue( -Dz );
337   myBusy = false;
338
339   if ( PreviewChB->isChecked() )
340     {
341       erasePreview();
342       displayPreview();
343     }
344 }
345
346 /*!
347   SLOT: called on mode changed
348 */
349 void OCCViewer_ClippingDlg::onModeChanged( int mode )
350 {
351   bool isUserMode = (mode==0);
352   
353   TextLabelX->setEnabled( isUserMode );
354   TextLabelY->setEnabled( isUserMode );
355   TextLabelZ->setEnabled( isUserMode );
356
357   SpinBox_X->setEnabled( isUserMode );
358   SpinBox_Y->setEnabled( isUserMode );
359   SpinBox_Z->setEnabled( isUserMode );
360
361   TextLabelDx->setEnabled( isUserMode );
362   TextLabelDy->setEnabled( isUserMode );
363   TextLabelDz->setEnabled( isUserMode );
364
365   SpinBox_Dx->setEnabled( isUserMode );
366   SpinBox_Dy->setEnabled( isUserMode );
367   SpinBox_Dz->setEnabled( isUserMode );
368   
369   if ( isUserMode )
370     return;
371
372   double aDx = 0, aDy = 0, aDz = 0;
373
374   if ( mode == 1 )
375     {
376       aDz = 1;
377       TextLabelZ->setEnabled( true );
378       SpinBox_Z->setEnabled( true );
379       SpinBox_Z->setFocus();
380     }
381   else if ( mode == 2 )
382     {
383       aDx = 1;
384       TextLabelX->setEnabled( true );
385       SpinBox_X->setEnabled( true );
386       SpinBox_X->setFocus();
387     }
388   else if ( mode == 3 )
389     {
390       aDy = 1;
391       TextLabelY->setEnabled( true );
392       SpinBox_Y->setEnabled( true );
393       SpinBox_Y->setFocus();
394     }
395   
396   myBusy = true;
397   SpinBox_Dx->setValue( aDx );
398   SpinBox_Dy->setValue( aDy );
399   SpinBox_Dz->setValue( aDz );
400   myBusy = false;
401
402   if ( PreviewChB->isChecked() )
403     {
404       erasePreview();
405       displayPreview();
406     }
407 }
408
409
410 /*!
411   Displays preview of clipping plane
412 */
413 void OCCViewer_ClippingDlg::displayPreview()
414 {
415   if ( myBusy || !isValid() )
416     return;
417
418   OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
419   if (!anOCCViewer)
420     return;
421   
422   Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
423
424   double aXMin, aYMin, aZMin, aXMax, aYMax, aZMax;
425   aXMin = aYMin = aZMin = DBL_MAX;
426   aXMax = aYMax = aZMax = -DBL_MAX;
427
428   bool isFound = false;
429   AIS_ListOfInteractive aList;
430   ic->DisplayedObjects( aList );
431   for ( AIS_ListIteratorOfListOfInteractive it( aList ); it.More(); it.Next() )
432   {
433     Handle(AIS_InteractiveObject) anObj = it.Value();
434     if ( !anObj.IsNull() && anObj->HasPresentation() &&
435          !anObj->IsKind( STANDARD_TYPE(AIS_Plane) ) )
436     {
437       Handle(Prs3d_Presentation) aPrs = anObj->Presentation();
438       if ( !aPrs->IsEmpty() && !aPrs->IsInfinite() )
439       {
440         isFound = true;
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 );
446       }
447     }
448   }
449
450   double aSize = 50;
451   
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;
455   
456   if ( isFound )
457     {
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;
461       aSize = aDiag * 1.1;
462
463       // compute clipping plane center ( redefine the base point )
464       IntAna_IntConicQuad intersector = IntAna_IntConicQuad();
465       
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 );
469     }
470   
471   myPreviewPlane = new AIS_Plane( new Geom_Plane( aBasePnt, aNormal ) );
472   myPreviewPlane->SetSize( aSize, aSize );
473   
474   // Deactivate clipping planes
475   myView->getViewPort()->getView()->SetPlaneOff();
476
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 );
482   
483   anOCCViewer->update();
484 }
485
486
487 /*!
488   Erases preview of clipping plane
489 */
490 void OCCViewer_ClippingDlg::erasePreview ()
491 {
492   OCCViewer_Viewer* anOCCViewer = (OCCViewer_Viewer*)myView->getViewManager()->getViewModel();
493   if (!anOCCViewer)
494     return;
495   
496   Handle(AIS_InteractiveContext) ic = anOCCViewer->getAISContext();
497   
498   if ( !myPreviewPlane.IsNull() && ic->IsDisplayed( myPreviewPlane ) )
499     {
500       ic->Erase( myPreviewPlane, false, false );
501       ic->Remove( myPreviewPlane, false );
502       myPreviewPlane.Nullify();
503     }
504   
505   anOCCViewer->update();
506 }
507
508
509 /*!
510   SLOT: called on value changes (co-ordinates of point or normal)
511 */
512 void OCCViewer_ClippingDlg::onValueChanged()
513 {
514   if ( PreviewChB->isChecked() )
515     {
516       erasePreview();
517       displayPreview();
518     }
519 }
520
521
522 /*!
523   SLOT: called on preview check box toggled
524 */
525 void OCCViewer_ClippingDlg::onPreview( bool on )
526 {
527   erasePreview();
528
529   if ( on ) 
530     displayPreview();
531 }
532
533 /*!
534   \return true if plane parameters are valid
535 */
536 bool OCCViewer_ClippingDlg::isValid()
537 {
538   return ( SpinBox_Dx->value()!=0 || SpinBox_Dy->value()!=0 || SpinBox_Dz->value()!=0 );
539 }
540
541 /*!
542   Remember the current clipping plane
543 */
544 void OCCViewer_ClippingDlg::ReserveClippingPlane()
545 {
546   Handle(V3d_View) aView3d = myView->getViewPort()->getView();
547   if ( !aView3d.IsNull() )
548     {
549       aView3d->InitActivePlanes();
550       if ( aView3d->MoreActivePlanes() )
551         myClippingPlane = aView3d->ActivePlane();
552     }
553 }