Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[modules/visu.git] / src / VISUGUI / VisuGUI_Plot3DDlg.cxx
1 //  VISU VISUGUI : GUI of VISU component
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : VisuGUI_Plot3DDlg.cxx
25 //  Author : Laurent CORNABE & Hubert ROLLAND
26 //  Module : VISU
27 //  $Header$
28
29 #include "VisuGUI_Plot3DDlg.h"
30
31 #include "VisuGUI.h"
32 #include "VisuGUI_Tools.h"
33 #include "VisuGUI_ViewTools.h"
34
35 #include "VISU_ViewManager_i.hh"
36 #include "VISU_Plot3DPL.hxx"
37
38 #include "SVTK_ViewWindow.h"
39
40 #include "SALOME_Actor.h"
41 #include "SUIT_Desktop.h"
42
43 #include <qlayout.h>
44 #include <qvalidator.h>
45 #include <qtabwidget.h>
46
47 #include <vtkUnstructuredGrid.h>
48 #include <vtkDataSetMapper.h>
49 #include <vtkRenderer.h>
50 #include <vtkPlaneSource.h>
51 #include <vtkPolyData.h>
52 #include <vtkMath.h>
53
54 using namespace std;
55
56 #define SURFACE_PRS_ID 0
57 #define CONTOUR_PRS_ID 1
58
59 //=======================================================================
60 //function : renderViewFrame
61 //purpose  :
62 //=======================================================================
63 static void renderViewFrame (SVTK_ViewWindow* vw)
64 {
65   if (vw) {
66     vw->getRenderer()->ResetCameraClippingRange();
67     vw->Repaint();
68   }
69 }
70
71 //=======================================================================
72 //class    : TPlane
73 //purpose  : actor of plane preview
74 //=======================================================================
75 class TPlane : public SALOME_Actor
76 {
77   float                mySize;
78   vtkDataSetMapper*    myMapper;
79   vtkPlaneSource*      myPlaneSource;
80
81  public:
82   // constructor
83   TPlane(float planeSize): mySize(planeSize)
84   {
85     Init();
86   }
87   // set plane parameters
88   void Set(float origin[3], float normal[3])
89   {
90     float point2[3], point1[3];
91     vtkMath::Perpendiculars(normal, point1, point2, 0.);
92     for (int i = 0; i < 3; ++i) {
93       point1[ i ] = point1[ i ] * mySize + origin[ i ];
94       point2[ i ] = point2[ i ] * mySize + origin[ i ];
95     }
96     myPlaneSource->SetOrigin(origin);
97     myPlaneSource->SetPoint1(point1);
98     myPlaneSource->SetPoint2(point2);
99     myPlaneSource->SetCenter(origin);
100   }
101   vtkTypeMacro(TPlane,SALOME_Actor);
102
103  protected:
104   void Init() {
105     myPlaneSource = vtkPlaneSource::New();
106     myMapper = vtkDataSetMapper::New();
107     myMapper->SetInput(myPlaneSource->GetOutput());
108     // actor methods
109     VisibilityOff();
110     PickableOff();
111     SetInfinitive(true);
112     SetOpacity(0.85);
113     SetMapper(myMapper);
114   }
115   ~TPlane() {
116     myMapper->RemoveAllInputs();
117     myMapper->Delete();
118     myPlaneSource->UnRegisterAllOutputs();
119     myPlaneSource->Delete();
120   };
121   // Not implemented.
122   TPlane(const TPlane&);
123   void operator=(const TPlane&);
124 };
125
126 //=======================================================================
127 //function : VisuGUI_Plot3DPane
128 //purpose  :
129 //=======================================================================
130 VisuGUI_Plot3DPane::VisuGUI_Plot3DPane (QWidget* parent)
131      : QVBox(parent), myInitFromPrs(false), myPreviewActor(NULL),
132        myViewWindow(VISU::GetActiveViewWindow<SVTK_ViewWindow>()), myPrs(NULL), myPipeCopy(NULL)
133 {
134   layout()->setAlignment(Qt::AlignTop);
135   setSpacing(6);
136
137   // Orientation
138
139   GBOrientation = new QButtonGroup (tr("Orientation"), this, "GBOrientation");
140   GBOrientation->setTitle(tr("ORIENTATION"));
141   GBOrientation->setColumnLayout(0, Qt::Vertical);
142   GBOrientation->layout()->setSpacing(0);
143   GBOrientation->layout()->setMargin(0);
144   QGridLayout* BGOrientationLayout = new QGridLayout (GBOrientation->layout());
145   BGOrientationLayout->setAlignment(Qt::AlignTop);
146   BGOrientationLayout->setSpacing(6);
147   BGOrientationLayout->setMargin(11);
148
149   QRadioButton *RBxy, *RByz, *RBzx;
150   RBxy = new QRadioButton (tr("// X-Y"), GBOrientation, "RBxy");
151   RByz = new QRadioButton (tr("// Y-Z"), GBOrientation, "RByz");
152   RBzx = new QRadioButton (tr("// Z-X"), GBOrientation, "RBzx");
153   BGOrientationLayout->addWidget(RBxy, 0, 0);
154   BGOrientationLayout->addWidget(RByz, 0, 1);
155   BGOrientationLayout->addWidget(RBzx, 0, 2);
156
157   // Rotation
158
159   QGroupBox* GBrot = new QGroupBox (tr("ROTATIONS"), this, "GBrot");
160   GBrot->setColumnLayout(0, Qt::Vertical);
161   GBrot->layout()->setSpacing(0);
162   GBrot->layout()->setMargin(0);
163   QGridLayout* GBrotLayout = new QGridLayout (GBrot->layout());
164   GBrotLayout->setAlignment(Qt::AlignTop);
165   GBrotLayout->setSpacing(6);
166   GBrotLayout->setMargin(11);
167   // label 1
168   LabelRot1 = new QLabel (tr("ROTATION_X"), GBrot, "LabelRot1");
169   GBrotLayout->addWidget(LabelRot1, 0, 0);
170   // spin 1
171   Rot1 = new QtxDblSpinBox (-180, 180, 5, GBrot);
172   Rot1->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
173   GBrotLayout->addWidget(Rot1, 0, 1);
174   // label 2
175   LabelRot2 = new QLabel (tr("ROTATION_Y"), GBrot, "LabelRot2");
176   GBrotLayout->addWidget(LabelRot2, 1, 0);
177   // spin 2
178   Rot2 = new QtxDblSpinBox (-180, 180, 5, GBrot);
179   Rot2->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
180   GBrotLayout->addWidget(Rot2, 1, 1);
181
182   // Position
183
184   QGroupBox* GBpos = new QGroupBox (tr("POSITION"), this, "GBpos");
185   GBpos->setColumnLayout(0, Qt::Horizontal);
186   GBpos->layout()->setSpacing(0);
187   GBpos->layout()->setMargin(0);
188   QGridLayout* GBposLayout = new QGridLayout (GBpos->layout());
189   GBposLayout->setAlignment(Qt::AlignTop);
190   GBposLayout->setSpacing(6);
191   GBposLayout->setMargin(11);
192   // value label
193   QLabel * valueLabel = new QLabel (tr("POSITION_VALUE"), GBpos, "LabelRot1");
194   GBposLayout->addWidget(valueLabel, 0, 0);
195   // value spin
196   PositionSpn = new QtxDblSpinBox (0, 1, 0.1, GBpos);
197   GBposLayout->addWidget(PositionSpn, 0, 1);
198   // Relative CheckBox
199   RelativeChkB = new QCheckBox (tr("RELATIVE"), GBpos, "RelativeChkB");
200   RelativeChkB->setChecked(true);
201   GBposLayout->addWidget(RelativeChkB, 0, 2);
202
203   // Scale, Presentation type, Nb Contours, Preview
204
205   QFrame* bottomFrame = new QFrame (this);
206   QGridLayout* bottomLayout = new QGridLayout (bottomFrame);
207   bottomLayout->setAlignment(Qt::AlignTop);
208   bottomLayout->setSpacing(11);
209   bottomLayout->setMargin(0);
210   // scale
211   QLabel* scaleLabel = new QLabel (tr("SCALE"), bottomFrame);
212   ScaleSpn = new QtxDblSpinBox (-1.e6, 1.e6, 0.1, bottomFrame);
213   // Presentation type
214   GBPrsType = new QHButtonGroup (tr("PRESENTATION_TYPE"), bottomFrame);
215   new QRadioButton (tr("SURFACE"), GBPrsType);
216   new QRadioButton (tr("CONTOUR"), GBPrsType);
217   // nb Contours
218   QLabel* nbContLabel = new QLabel (tr("NUMBER_CONTOURS"), bottomFrame);
219   NbContoursSpn = new QSpinBox (1, 999, 1, bottomFrame, "NbContoursSpn");
220   // Preview
221   PreviewChkB = new QCheckBox (tr("PREVIEW"), bottomFrame);
222   PreviewChkB->setChecked(false);
223
224   bottomLayout->addWidget(scaleLabel,    0, 0);
225   bottomLayout->addWidget(ScaleSpn,      0, 1);
226   bottomLayout->addMultiCellWidget(GBPrsType, 1, 1, 0, 1);
227   bottomLayout->addWidget(nbContLabel,   2, 0);
228   bottomLayout->addWidget(NbContoursSpn, 2, 1);
229   bottomLayout->addWidget(PreviewChkB,   3, 0);
230
231   // signals and slots connections
232   connect(GBOrientation, SIGNAL(clicked(int)),         this, SLOT(orientationChanged(int)));
233   connect(Rot1,          SIGNAL(valueChanged(double)), this, SLOT(updatePreview()));
234   connect(Rot2,          SIGNAL(valueChanged(double)), this, SLOT(updatePreview()));
235   connect(PositionSpn,   SIGNAL(valueChanged(double)), this, SLOT(onPositionSpn()));
236   connect(RelativeChkB,  SIGNAL(toggled(bool)),        this, SLOT(onRelativePos(bool)));
237   connect(GBPrsType,     SIGNAL(clicked(int)),         this, SLOT(onPrsType(int)));
238   connect(PreviewChkB,   SIGNAL(toggled(bool)),        this, SLOT(updatePreview()));
239 }
240
241 //=======================================================================
242 //function : destructor
243 //purpose  :
244 //=======================================================================
245 VisuGUI_Plot3DPane::~VisuGUI_Plot3DPane()
246 {
247 }
248
249 //=======================================================================
250 //function : storePrsParams
251 //purpose  : create a copy of Prs parameters and then store current
252 //           control values into the Prs
253 //=======================================================================
254 void VisuGUI_Plot3DPane::storePrsParams()
255 {
256   if (!myPipeCopy)
257     myPipeCopy = VISU_Plot3DPL::New();
258   if (myPrs) {
259     myPipeCopy->SetIDMapper(myPrs->GetPL()->GetIDMapper());
260     myPipeCopy->ShallowCopy(myPrs->GetPL());
261     storeToPrsObject(myPrs);
262   }
263 }
264
265 //=======================================================================
266 //function : restorePrsParams
267 //purpose  : restore Prs parameters from the copy
268 //=======================================================================
269 void VisuGUI_Plot3DPane::restorePrsParams()
270 {
271   if (!myPipeCopy)
272     myPipeCopy = VISU_Plot3DPL::New();
273   if (myPrs)
274     myPrs->GetPL()->ShallowCopy(myPipeCopy);
275 }
276
277 //=======================================================================
278 //function : onPositionSpn
279 //purpose  : update absolute position range
280 //=======================================================================
281 void VisuGUI_Plot3DPane::onPositionSpn()
282 {
283   if (myPrs && !RelativeChkB->isChecked()) {
284     float minPos, maxPos;
285     storePrsParams();
286     myPrs->GetPlot3DPL()->GetMinMaxPosition(minPos, maxPos);
287     restorePrsParams();
288     if (minPos > PositionSpn->value())
289       minPos = PositionSpn->value();
290     if (maxPos < PositionSpn->value())
291       maxPos = PositionSpn->value();
292     PositionSpn->setRange(minPos, maxPos);
293   }
294   updatePreview();
295 }
296
297 //=======================================================================
298 //function : orientationChanged
299 //purpose  : update rotation labels and preview
300 //=======================================================================
301 void VisuGUI_Plot3DPane::orientationChanged(int Id)
302 {
303   if (Id == 0) { // RBxy->isChecked()
304     LabelRot1->setText(tr("ROTATION_X"));
305     LabelRot2->setText(tr("ROTATION_Y"));
306   } else if (Id == 1) { // RByz->isChecked()
307     LabelRot1->setText(tr("ROTATION_Y"));
308     LabelRot2->setText(tr("ROTATION_Z"));
309   } else {
310     LabelRot1->setText(tr("ROTATION_Z"));
311     LabelRot2->setText(tr("ROTATION_X"));
312   }
313   updatePreview();
314 }
315
316 //=======================================================================
317 //function : onRelativePos
318 //purpose  : update position value and range
319 //=======================================================================
320 void VisuGUI_Plot3DPane::onRelativePos(bool isRelativePos)
321 {
322   float minPos = 0., maxPos = 1., pos = PositionSpn->value();
323   if (myPrs) {
324     storePrsParams();
325     myPrs->GetPlot3DPL()->GetMinMaxPosition(minPos, maxPos);
326     restorePrsParams();
327     if (-1e-7 < (maxPos - minPos) && (maxPos - minPos) < 1e-7) {
328       pos = 0;
329     } else {
330       if (isRelativePos) // absolute -> relative
331         pos = (pos - minPos) / (maxPos - minPos);
332       else  // relative -> absolute
333         pos = minPos * (1. - pos) + maxPos * pos;
334     }
335   }
336   if (isRelativePos) {
337     minPos = 0.;
338     maxPos = 1.;
339   }
340   PositionSpn->setMinValue(minPos);
341   PositionSpn->setMaxValue(maxPos);
342   PositionSpn->setLineStep((maxPos - minPos) / 10.);
343   PositionSpn->setValue(pos);
344 }
345
346 //=======================================================================
347 //function : onPrsType
348 //purpose  :
349 //=======================================================================
350 void VisuGUI_Plot3DPane::onPrsType(int id)
351 {
352   NbContoursSpn->setEnabled(id == CONTOUR_PRS_ID);
353 }
354
355 //=======================================================================
356 //function : updatePreview
357 //purpose  :
358 //=======================================================================
359 void VisuGUI_Plot3DPane::updatePreview()
360 {
361   if (myInitFromPrs || !myPrs || !myViewWindow)
362     return;
363   bool fitall = false;
364   if (PreviewChkB->isChecked()) // place preview plane
365   {
366     // get plane preview actor
367     TPlane* planePreview = (TPlane*) myPreviewActor;
368     if (!planePreview) {
369       myPreviewActor = planePreview = new TPlane(myPrs->GetInput()->GetLength());
370       myViewWindow->AddActor(planePreview);
371       fitall = !VISU::GetActor(myPrs, myViewWindow);
372     }
373     // set plane parameters corresponding to control values
374     storePrsParams();
375     float normal[3], origin[3];
376     myPrs->GetPlot3DPL()->GetBasePlane(origin, normal, true);
377     planePreview->Set(origin, normal);
378     restorePrsParams();
379   }
380   if (myPreviewActor)
381     myPreviewActor->SetVisibility(PreviewChkB->isChecked());
382
383   renderViewFrame(myViewWindow);
384
385   if (fitall) {
386     myPreviewActor->SetInfinitive(false);
387     myViewWindow->onFitAll();
388     myPreviewActor->SetInfinitive(true);
389   }
390 }
391
392 //=======================================================================
393 //function : initFromPrsObject
394 //purpose  :
395 //=======================================================================
396 void VisuGUI_Plot3DPane::initFromPrsObject(VISU::Plot3D_i* thePrs)
397 {
398   myInitFromPrs = true;
399   myPrs = thePrs;
400
401   // orientation
402   int id;
403   switch (thePrs->GetOrientationType()) {
404   case VISU::Plot3D::XY: id = 0; break;
405   case VISU::Plot3D::YZ: id = 1; break;
406   default: id = 2;
407   }
408   GBOrientation->setButton(id);
409   orientationChanged(id);
410
411   // rotation
412   Rot1->setValue(thePrs->GetRotateX() * 180./PI);
413   Rot2->setValue(thePrs->GetRotateY() * 180./PI);
414
415   // position
416   RelativeChkB->setChecked(thePrs->IsPositionRelative());
417   onRelativePos(thePrs->IsPositionRelative()); // update range
418   PositionSpn->setValue(thePrs->GetPlanePosition());
419
420   // scale
421   ScaleSpn->setValue(thePrs->GetScaleFactor());
422
423   // prs type
424   id = thePrs->GetIsContourPrs() ? CONTOUR_PRS_ID : SURFACE_PRS_ID;
425   GBPrsType->setButton(id);
426   onPrsType(id);
427
428   // nb contours
429   NbContoursSpn->setValue(thePrs->GetNbOfContours());
430
431   // disable cutting plane controls if the mesh is planar
432
433   if (thePrs->GetPL()->IsPlanarInput())
434   {
435     GBOrientation->setEnabled(false);
436     Rot1         ->setEnabled(false);
437     Rot2         ->setEnabled(false);
438     PositionSpn  ->setEnabled(false);
439     RelativeChkB ->setEnabled(false);
440     PreviewChkB  ->setEnabled(false);
441   }
442
443   myInitFromPrs = false;
444   updatePreview();
445 }
446
447 //=======================================================================
448 //function : storeToPrsObject
449 //purpose  :
450 //=======================================================================
451 int VisuGUI_Plot3DPane::storeToPrsObject(VISU::Plot3D_i* thePrs)
452 {
453   if (myInitFromPrs)
454     return 0;
455   // orientation
456   int id = GBOrientation->id (GBOrientation->selected());
457   VISU::Plot3D::Orientation ori;
458   switch (id) {
459   case 0 : ori = VISU::Plot3D::XY; break;
460   case 1 : ori = VISU::Plot3D::YZ; break;
461   default: ori = VISU::Plot3D::ZX;
462   }
463   // rotation
464   thePrs->SetOrientation(ori, Rot1->value()*PI/180., Rot2->value()*PI/180.);
465
466   // position
467   thePrs->SetPlanePosition(PositionSpn->value(), RelativeChkB->isChecked());
468
469   // scale
470   thePrs->SetScaleFactor(ScaleSpn->value());
471
472   // prs type
473   id = GBPrsType->id (GBPrsType->selected());
474   thePrs->SetContourPrs(id == CONTOUR_PRS_ID);
475
476   // nb contours
477   thePrs->SetNbOfContours(NbContoursSpn->value());
478
479   return 1;
480 }
481
482 //=======================================================================
483 //function : check
484 //purpose  :
485 //=======================================================================
486 bool VisuGUI_Plot3DPane::check()
487 {
488   if (myPreviewActor && myViewWindow) // erase preview
489   {
490     myPreviewActor->SetVisibility(false);
491     myViewWindow->RemoveActor(myPreviewActor);
492     myPreviewActor->Delete();
493     myPreviewActor = 0;
494   }
495
496   return true;
497 }
498
499 //=======================================================================
500 //function : Constructor
501 //purpose  :
502 //=======================================================================
503 VisuGUI_Plot3DDlg::VisuGUI_Plot3DDlg (SalomeApp_Module* theModule)
504   : QDialog(VISU::GetDesktop(theModule), "VisuGUI_Plot3DDlg", false, WStyle_Customize |
505             WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
506 {
507   setCaption(tr("TITLE"));
508   setSizeGripEnabled(TRUE);
509
510   QVBoxLayout* TopLayout = new QVBoxLayout(this);
511   TopLayout->setSpacing(6);
512   TopLayout->setMargin(11);
513
514   QTabWidget* aTabBox = new QTabWidget (this);
515   myIsoPane = new VisuGUI_Plot3DPane (this);
516   myIsoPane->setMargin(5);
517   aTabBox->addTab(myIsoPane, tr("PLOT3D_TAB_TITLE"));
518   myScalarPane = new VisuGUI_ScalarBarPane (this, false);
519   myScalarPane->setMargin(5);
520   aTabBox->addTab(myScalarPane, tr("SCALAR_BAR_TAB_TITLE"));
521
522   TopLayout->addWidget(aTabBox);
523
524   QGroupBox* GroupButtons = new QGroupBox (this, "GroupButtons");
525   GroupButtons->setGeometry(QRect(10, 10, 281, 48));
526   GroupButtons->setColumnLayout(0, Qt::Vertical);
527   GroupButtons->layout()->setSpacing(0);
528   GroupButtons->layout()->setMargin(0);
529   QGridLayout* GroupButtonsLayout = new QGridLayout (GroupButtons->layout());
530   GroupButtonsLayout->setAlignment(Qt::AlignTop);
531   GroupButtonsLayout->setSpacing(6);
532   GroupButtonsLayout->setMargin(11);
533
534   QPushButton* buttonOk = new QPushButton (tr("&OK"), GroupButtons, "buttonOk");
535   buttonOk->setAutoDefault(TRUE);
536   buttonOk->setDefault(TRUE);
537   GroupButtonsLayout->addWidget(buttonOk, 0, 0);
538   GroupButtonsLayout->addItem(new QSpacerItem (5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, 1);
539   QPushButton* buttonCancel = new QPushButton (tr("&Cancel") , GroupButtons, "buttonCancel");
540   buttonCancel->setAutoDefault(TRUE);
541   GroupButtonsLayout->addWidget(buttonCancel, 0, 2);
542
543   TopLayout->addWidget(GroupButtons);
544
545   // signals and slots connections
546   connect(buttonOk,     SIGNAL(clicked()), this, SLOT(accept()));
547   connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
548 }
549
550 //=======================================================================
551 //function : accept
552 //purpose  :
553 //=======================================================================
554 void VisuGUI_Plot3DDlg::accept()
555 {
556   if (myIsoPane->check() && myScalarPane->check())
557     {
558       myScalarPane->deletePreview();
559       QDialog::accept();
560     }
561 }
562
563 //=======================================================================
564 //function : reject
565 //purpose  :
566 //=======================================================================
567 void VisuGUI_Plot3DDlg::reject()
568 {
569   myIsoPane->check(); // hide preview
570   myScalarPane->deletePreview();
571   
572   QDialog::reject();
573 }