Salome HOME
23368: [CEA 1865] Possibility to define faces to mesh as a single one: transpatch...
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_NbSegmentsCreator.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
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 // File   : StdMeshersGUI_NbSegmentsCreator.cxx
24 // Author : Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "StdMeshersGUI_NbSegmentsCreator.h"
28 #ifndef DISABLE_PLOT2DVIEWER
29   #include "StdMeshersGUI_DistrPreview.h"
30 #endif
31 #include "StdMeshersGUI_DistrTable.h"
32 #include "StdMeshersGUI_PropagationHelperWdg.h"
33 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
34
35 #include <SMESHGUI.h>
36 #include <SMESHGUI_Utils.h>
37 #include <SMESHGUI_HypothesesUtils.h>
38 #include <SMESHGUI_SpinBox.h>
39
40 // IDL includes
41 #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
42
43 // SALOME GUI includes
44 #include <SalomeApp_Tools.h>
45 #include <SalomeApp_IntSpinBox.h>
46 #include <QtxComboBox.h>
47
48 // Qt includes
49 #include <QLabel>
50 #include <QGroupBox>
51 #include <QFrame>
52 #include <QLineEdit>
53 #include <QButtonGroup>
54 #include <QRadioButton>
55 #include <QGridLayout>
56 #include <QVBoxLayout>
57 #include <QHBoxLayout>
58 #include <QApplication>
59
60 #define SPACING 6
61 #define MARGIN  11
62
63 StdMeshersGUI_NbSegmentsCreator::StdMeshersGUI_NbSegmentsCreator()
64 : StdMeshersGUI_StdHypothesisCreator( "NumberOfSegments" ),
65   myNbSeg( 0 ),
66   myDistr( 0 ),
67   myScale( 0 ),
68   myTable( 0 ),
69 #ifndef DISABLE_PLOT2DVIEWER
70   myPreview( 0 ),
71 #endif
72   myExpr( 0 ),
73   myConvBox( 0 ),
74   myConv( 0 ),
75   myLScale( 0 ),
76   myLTable( 0 ),
77   myLExpr( 0 ),
78   myInfo( 0 ),
79   myGroupLayout( 0 ),
80   myTableRow( 0 ),
81   myPreviewRow( 0 )
82 {
83 }
84
85 StdMeshersGUI_NbSegmentsCreator::~StdMeshersGUI_NbSegmentsCreator()
86 {
87 }
88
89 bool StdMeshersGUI_NbSegmentsCreator::checkParams( QString& msg ) const
90 {
91   if( !SMESHGUI_GenericHypothesisCreator::checkParams( msg ) )
92     return false;
93   NbSegmentsHypothesisData data_old, data_new;
94   readParamsFromHypo( data_old );
95   readParamsFromWidgets( data_new );
96   bool res = storeParamsToHypo( data_new );
97   res = myNbSeg->isValid( msg, true ) && res;
98   res = myScale->isValid( msg, true ) && res;
99   if ( !res )
100     storeParamsToHypo( data_old );
101   return res;
102 }
103
104 QFrame* StdMeshersGUI_NbSegmentsCreator::buildFrame()
105 {
106   QFrame* fr = new QFrame();
107   fr->setMinimumWidth(460);
108
109   QVBoxLayout* lay = new QVBoxLayout( fr );
110   lay->setMargin( 0 );
111   lay->setSpacing( SPACING );
112
113   QGroupBox* GroupC1 = new QGroupBox( tr( "SMESH_ARGUMENTS" ), fr );
114   lay->addWidget( GroupC1 );
115
116   StdMeshers::StdMeshers_NumberOfSegments_var h =
117     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
118
119   myGroupLayout = new QGridLayout( GroupC1 );
120   myGroupLayout->setSpacing( SPACING );
121   myGroupLayout->setMargin( MARGIN );
122   myGroupLayout->setColumnStretch( 0, 0 );
123   myGroupLayout->setColumnStretch( 1, 1 );
124
125   int row = 0;
126   // 0)  name
127   myName = 0;
128   if( isCreation() )
129   {
130     myName = new QLineEdit( GroupC1 );
131     myGroupLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), GroupC1 ), row, 0 );
132     myGroupLayout->addWidget( myName, row, 1 );
133     row++;
134   }
135
136
137   // 1)  number of segments
138   myGroupLayout->addWidget( new QLabel( tr( "SMESH_NB_SEGMENTS_PARAM" ), GroupC1 ), row, 0 );
139   myNbSeg = new SalomeApp_IntSpinBox( GroupC1 );
140   myNbSeg->setMinimum( 1 );
141   myNbSeg->setMaximum( 9999 );
142   myGroupLayout->addWidget( myNbSeg, row, 1 );
143   row++;
144
145   
146   // 2)  type of distribution
147   myGroupLayout->addWidget( new QLabel( tr( "SMESH_DISTR_TYPE" ), GroupC1 ), row, 0 );
148   myDistr = new QtxComboBox( GroupC1 );
149   QStringList types;
150   types.append( tr( "SMESH_DISTR_REGULAR" ) );
151   types.append( tr( "SMESH_DISTR_SCALE"   ) );
152   types.append( tr( "SMESH_DISTR_TAB"     ) );
153   types.append( tr( "SMESH_DISTR_EXPR"    ) );
154   myDistr->addItems( types );
155   myGroupLayout->addWidget( myDistr, row, 1 );
156   row++;
157
158   
159   // 3)  scale
160   myGroupLayout->addWidget( myLScale = new QLabel( tr( "SMESH_NB_SEGMENTS_SCALE_PARAM" ), GroupC1 ), row, 0 );
161   myScale = new SMESHGUI_SpinBox( GroupC1 );
162   myScale->RangeStepAndValidator( 1E-5, 1E+5, 0.1, "parametric_precision" );
163   myGroupLayout->addWidget( myScale, row, 1 );
164   row++;
165
166   
167   // 4) Distribution definition
168   QGridLayout* myDistLayout = new QGridLayout(GroupC1);
169   myGroupLayout->addLayout( myDistLayout, row, 0, 1, 2 );
170   myGroupLayout->setRowStretch( row, 1 );
171   row ++;
172
173        // a)  expression
174   QHBoxLayout* myExprLayout = new QHBoxLayout(GroupC1);
175   myExprLayout->addWidget( myLExpr = new QLabel( "f(t)=", GroupC1 ), 0);
176   myExpr = new QLineEdit( GroupC1 );
177   myExprLayout->addWidget( myExpr,1);
178   myDistLayout->addLayout(myExprLayout,1 ,0);
179   myDistLayout->setRowStretch(2, 1);
180
181        // b)  warning
182   myInfo = new QLabel( tr( "SMESH_FUNC_DOMAIN" ), GroupC1 );
183   myDistLayout->addWidget( myInfo, 0, 0, 1, 2);
184   
185        // c)  table
186   myTable = new StdMeshersGUI_DistrTableFrame( GroupC1 );
187   myTable->setMinimumHeight(220);
188   myDistLayout->addWidget( myTable, 1, 0, 2, 1 );
189
190 #ifndef DISABLE_PLOT2DVIEWER
191        // d) preview
192   myPreview = new StdMeshersGUI_DistrPreview( GroupC1, h.in() );  
193   myDistLayout->addWidget( myPreview, 1, 1, 2, 1 );
194 #endif
195   
196   // 5)  conversion (radiogroup)
197   myConvBox = new QGroupBox( tr( "SMESH_CONV_MODE" ), GroupC1 );
198   myConv = new QButtonGroup( GroupC1 );
199
200   QHBoxLayout* convLay = new QHBoxLayout( myConvBox );
201   convLay->setMargin( MARGIN );
202   convLay->setSpacing( SPACING );
203
204   QRadioButton* rbExp = new QRadioButton( tr( "SMESH_EXP_MODE" ), myConvBox );
205   QRadioButton* myCutNeg = new QRadioButton( tr( "SMESH_CUT_NEG_MODE" ), myConvBox );
206
207   convLay->addWidget( rbExp );
208   convLay->addWidget( myCutNeg );
209   myConv->addButton( rbExp, 0 );
210   myConv->addButton( myCutNeg, 1 );
211
212   myGroupLayout->addWidget( myConvBox, row, 0, 1, 2 );
213   row++;
214
215
216   // 6) reverse edge parameters
217   myReversedEdgesBox = new QGroupBox(tr( "SMESH_REVERSED_EDGES" ), fr);
218   QHBoxLayout* edgeLay = new QHBoxLayout( myReversedEdgesBox );
219
220   myDirectionWidget = new StdMeshersGUI_SubShapeSelectorWdg( myReversedEdgesBox );
221   QString aGeomEntry = getShapeEntry();
222   QString aMainEntry = getMainShapeEntry();
223   if ( aGeomEntry == "" )
224     aGeomEntry = h->GetObjectEntry();
225   myDirectionWidget->SetGeomShapeEntry( aGeomEntry, aMainEntry );
226   myDirectionWidget->SetListOfIDs( h->GetReversedEdges() );
227   edgeLay->addWidget( myDirectionWidget );
228
229   lay->addWidget( myReversedEdgesBox );
230   lay->setStretchFactor( GroupC1, 1);
231   lay->setStretchFactor( myReversedEdgesBox, 1);
232
233   myReversedEdgesHelper = 0;
234   if ( !aGeomEntry.isEmpty() || !aMainEntry.isEmpty() )
235   {
236     myReversedEdgesHelper = new StdMeshersGUI_PropagationHelperWdg( myDirectionWidget, fr, false );
237     lay->addWidget( myReversedEdgesHelper );
238     lay->setStretchFactor( myReversedEdgesHelper, 1 );
239   }
240
241   connect( myNbSeg, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
242   connect( myDistr, SIGNAL( activated( int ) ), this, SLOT( onValueChanged() ) );
243   connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SLOT( onValueChanged() ) );
244   connect( myExpr,  SIGNAL( textChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
245   connect( myConv,  SIGNAL( buttonClicked( int ) ), this, SLOT( onValueChanged() ) );
246
247   onValueChanged();
248
249   return fr;
250 }
251
252 void StdMeshersGUI_NbSegmentsCreator::retrieveParams() const
253 {
254   NbSegmentsHypothesisData data;
255   readParamsFromHypo( data );
256
257   if( myName )
258     myName->setText( data.myName );
259   if(data.myNbSegVarName.isEmpty())
260     myNbSeg->setValue( data.myNbSeg );
261   else
262     myNbSeg->setText( data.myNbSegVarName );
263   
264   myDistr->setCurrentIndex( data.myDistrType );
265   if(data.myScaleVarName.isEmpty())
266     myScale->setValue( data.myScale );
267   else
268     myScale->setText( data.myScaleVarName );
269   myConv->button( data.myConv )->setChecked( true );
270   myTable->setFuncMinValue(myConv->checkedId()==0 ? -1E20 : 0);
271   myTable->setData( data.myTable );
272   myExpr->setText( data.myExpr );
273
274   if ( dlg() )
275     dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
276 }
277
278 QString StdMeshersGUI_NbSegmentsCreator::storeParams() const
279 {
280   NbSegmentsHypothesisData data;
281   readParamsFromWidgets( data );
282   storeParamsToHypo( data );
283     
284   QString valStr = QString::number( data.myNbSeg ) += "; ";
285
286   enum DistrType
287   {
288     Regular, //!< equidistant distribution
289     Scale,   //!< scale distribution
290     TabFunc, //!< distribution with density function presented by table
291     ExprFunc //!< distribution with density function presented by expression
292   };
293   bool hasConv = false;
294   switch ( data.myDistrType ) {
295   case Regular :
296     valStr += tr("SMESH_DISTR_REGULAR");
297     break;
298   case Scale   :
299     valStr += tr("SMESH_NB_SEGMENTS_SCALE_PARAM") + " = " + QString::number( data.myScale );
300     break;
301   case TabFunc : {
302     //valStr += tr("SMESH_TAB_FUNC");
303     bool param = true;
304     for( CORBA::ULong i = 0; i < data.myTable.length(); i++, param = !param ) {
305       if ( param )
306         valStr += "[";
307       valStr += QString::number( data.myTable[ i ]);
308       valStr += ( param ? "," : "]" );
309     }
310     hasConv = true;
311     break;
312   }
313   case ExprFunc:
314     valStr += data.myExpr;
315     hasConv = true;
316     break;
317   }
318   if ( hasConv )
319   {
320     if ( data.myConv )
321       valStr += "; " + tr("SMESH_CUT_NEG_MODE");
322     else
323       valStr += "; " + tr("SMESH_EXP_MODE");
324   }
325
326   return valStr;
327 }
328
329 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromHypo( NbSegmentsHypothesisData& h_data ) const
330 {
331   StdMeshers::StdMeshers_NumberOfSegments_var h =
332     StdMeshers::StdMeshers_NumberOfSegments::_narrow( initParamsHypothesis() );
333
334   h_data.myName = hypName();
335
336   h_data.myNbSeg = (int) h->GetNumberOfSegments();
337
338   CORBA::String_var aVaribaleName = h->GetVarParameter( "SetNumberOfSegments" );
339   h_data.myNbSegVarName = aVaribaleName.in();
340
341   int distr = (int) h->GetDistrType();
342   h_data.myDistrType = distr;
343   h_data.myScale = distr==1 ? h->GetScaleFactor() : 1.0;
344   
345   if(distr==1) {
346     aVaribaleName = h->GetVarParameter( "SetScaleFactor" );
347     h_data.myScaleVarName = aVaribaleName.in();
348   }
349   else 
350     h_data.myScaleVarName = QString("");
351
352   if( distr==2 )
353   {
354     SMESH::double_array* a = h->GetTableFunction();
355     h_data.myTable = *a;
356     delete a;
357   }
358   else
359   {
360     SMESH::double_array& a = h_data.myTable;
361     // by default, constant table function f(t)=1
362     a.length( 4 );
363     a[0] = 0.0; a[1] = 1.0;
364     a[2] = 1.0; a[3] = 1.0; 
365   }
366
367   h_data.myExpr = distr==3 ? h->GetExpressionFunction() : "1";
368   h_data.myConv = distr==2 || distr==3 ? h->ConversionMode() : 1; /*cut negative by default*/
369
370   return true;
371 }
372
373 bool StdMeshersGUI_NbSegmentsCreator::storeParamsToHypo( const NbSegmentsHypothesisData& h_data ) const
374 {
375   StdMeshers::StdMeshers_NumberOfSegments_var h =
376     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
377
378   bool ok = true;
379   try
380   {
381     if( isCreation() )
382       SMESH::SetName( SMESH::FindSObject( h ), h_data.myName.toLatin1().data() );
383
384     h->SetVarParameter( h_data.myNbSegVarName.toLatin1().constData(), "SetNumberOfSegments" );
385     h->SetNumberOfSegments( h_data.myNbSeg );
386     
387     int distr = h_data.myDistrType;
388     if ( distr == 0 )
389       h->SetDistrType( distr ); // this is actually needed at non-uniform -> uniform switch
390     if( distr==1 ) {
391       h->SetVarParameter( h_data.myScaleVarName.toLatin1().constData(), "SetScaleFactor" );
392       h->SetScaleFactor( h_data.myScale );
393     }
394     if( distr==2 || distr==3 )
395       h->SetConversionMode( h_data.myConv );
396
397     if( distr==1 || distr==2 || distr==3 ) {
398       h->SetReversedEdges( myDirectionWidget->GetListOfIDs() );
399       h->SetObjectEntry( myDirectionWidget->GetMainShapeEntry() );
400     }
401
402     if( distr==2 )
403       h->SetTableFunction( h_data.myTable );
404
405     if( distr==3 )
406       h->SetExpressionFunction( h_data.myExpr.toLatin1().data() );
407     //setting of function must follow after setConversionMode, because otherwise
408     //the function will be checked with old conversion mode, so that it may occurs
409     //unexpected errors for user
410   }
411   catch(const SALOME::SALOME_Exception& ex)
412   {
413     SalomeApp_Tools::QtCatchCorbaException(ex);
414     ok = false;
415   }
416   return ok;
417 }
418
419 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromWidgets( NbSegmentsHypothesisData& h_data ) const
420 {
421   h_data.myName      = myName ? myName->text() : "";
422   h_data.myNbSeg     = myNbSeg->value();
423   h_data.myNbSegVarName =  myNbSeg->text();
424   h_data.myScaleVarName =  myScale->text();
425   h_data.myDistrType = myDistr->currentIndex();
426   h_data.myConv      = myConv->checkedId();
427   h_data.myScale     = myScale->value();
428   myTable->data( h_data.myTable );
429   h_data.myExpr      = myExpr->text();
430   return true;
431 }
432
433 void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
434 {
435   int distr = myDistr->currentIndex();
436
437 /*  if( distr==2 ) //table func
438     myCutNeg->setText( tr( "SMESH_NO_CONV" ) );
439   else if( distr==3 )
440     myCutNeg->setText( tr( "SMESH_CUT_NEG_MODE" ) );*/
441
442   if( distr==2 && sender()==myConv ) //table func
443   {
444     myTable->setFuncMinValue( myConv->checkedId()==0 ? -1E20 : 0 );
445     SMESH::double_array arr;
446     myTable->data( arr );
447     myTable->setData( arr ); //update data in table
448   }
449
450   myScale->setVisible( distr==1 );
451   myLScale->setVisible( distr==1 );
452   myReversedEdgesBox->setVisible( distr!=0 );
453   if ( myReversedEdgesHelper ) {
454     myReversedEdgesHelper->Clear();
455     myReversedEdgesHelper->setVisible( distr!=0 );
456   }
457   myDirectionWidget->ShowPreview( distr!=0 );
458
459   bool isFunc = distr==2 || distr==3;
460 #ifndef DISABLE_PLOT2DVIEWER
461   myPreview->setVisible( isFunc );
462 #endif
463   myConvBox->setVisible( isFunc );
464   
465   myTable->setVisible( distr==2 );
466   myExpr->setVisible( distr==3 );
467   myLExpr->setVisible( distr==3 );
468   myInfo->setVisible( distr==3);
469
470 #ifndef DISABLE_PLOT2DVIEWER
471   //change of preview
472   int nbSeg = myNbSeg->value();
473   if( distr==2 ) //preview for table-described function
474   {
475     SMESH::double_array a;
476     myTable->data( a );
477     myPreview->setParams( a, nbSeg, false );
478   }
479   else if( distr==3 ) //preview for analytic-described function
480     myPreview->setParams( myExpr->text(), nbSeg, 100, false );
481
482   if( isFunc )
483     myPreview->setConversion( StdMeshersGUI_DistrPreview::Conversion( myConv->checkedId() ) );
484 #endif
485
486   if ( (QtxComboBox*)sender() == myDistr && dlg() ) {
487     QApplication::instance()->processEvents();
488     myGroupLayout->invalidate();
489     dlg()->layout()->invalidate();
490     dlg()->updateGeometry();
491     dlg()->setMinimumSize( dlg()->minimumSizeHint() );
492     dlg()->resize( dlg()->minimumSize() );
493     QApplication::instance()->processEvents();
494   }
495 }