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