Salome HOME
a431c87b5c030a1dbdde73d124c67b2aba4c9f79
[plugins/hexoticplugin.git] / src / HexoticPlugin / HexoticPlugin_Hypothesis.cxx
1 // Copyright (C) 2007-2023  CEA, EDF
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, or (at your option) any later version.
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/ or email : webmaster.salome@opencascade.com
18 //
19
20 // ---
21 // File   : HexoticPlugin_Hypothesis.cxx
22 // Author : Lioka RAZAFINDRAZAKA (CEA)
23 // ---
24 //
25 #include "HexoticPlugin_Hypothesis.hxx"
26 #include <utilities.h>
27
28 #include <TCollection_AsciiString.hxx>
29 #include <SMESH_Comment.hxx>
30
31 namespace
32 {
33   struct GET_DEFAULT // struct used to get default value from GetOptionValue()
34   {
35     bool isDefault;
36     operator bool* () { return &isDefault; }
37   };
38 }
39
40 //=============================================================================
41 /*!
42  *
43  */
44 //=============================================================================
45 HexoticPlugin_Hypothesis::HexoticPlugin_Hypothesis (int hypId, SMESH_Gen* gen)
46   : SMESH_Hypothesis(hypId, gen),
47     _hexesMinLevel( GetDefaultHexesMinLevel() ),
48     _hexesMaxLevel( GetDefaultHexesMaxLevel() ),
49     _minSize( GetDefaultMinSize() ),
50     _maxSize( GetDefaultMaxSize() ),
51     _approxAngle( GetDefaultGeomApproxAngle() ),
52     _hexoticIgnoreRidges( GetDefaultHexoticIgnoreRidges() ),
53     _hexoticInvalidElements( GetDefaultHexoticInvalidElements() ),
54     _hexoticSharpAngleThreshold( GetDefaultHexoticSharpAngleThreshold() ),
55     _hexoticNbProc( GetDefaultHexoticNbProc() ),
56     _hexoticSdMode(GetDefaultHexoticSdMode()),
57     _hexoticVerbosity(GetDefaultHexoticVerbosity()),
58     _hexoticMaxMemory(GetDefaultHexoticMaxMemory()),
59     _hexoticWorkingDirectory( GetDefaultHexoticWorkingDirectory() ),
60     _logInStandardOutput( GetDefaultStandardOutputLog() ),
61     _removeLogOnSuccess( GetDefaultRemoveLogOnSuccess() ),
62     _keepFiles( GetDefaultKeepFiles() ),
63     _nbLayers(GetDefaultNbLayers()),
64     _firstLayerSize(GetDefaultFirstLayerSize()),
65     _direction(GetDefaultDirection()),
66     _growth(GetDefaultGrowth()),
67     _facesWithLayers(GetDefaultFacesWithLayers()),
68     _imprintedFaces(GetDefaultImprintedFaces())
69 {
70   MESSAGE("HexoticPlugin_Hypothesis::HexoticPlugin_Hypothesis");
71   _name = GetHypType();
72   _param_algo_dim = 3;
73
74   const char* boolOptionNames[] = { "allow_invalid_elements",
75                                     "enforce_constant_layer_size",
76                                     "compute_ridges",
77                                     "flatten_hexa_sides",
78                                     "recover_sharp_angles",
79                                     "" // mark of end
80   };
81   const char* intOptionNames[] = { "max_memory",            // 2048
82                                    "max_number_of_threads", // 4
83                                    "min_level",             // 6
84                                    "max_level",             // 10
85                                    "sizemap_level",         // 10
86                                    "" // mark of end
87   };
88   const char* doubleOptionNames[] = { "ridge_angle",  // 60
89                                       "" // mark of end
90   };
91   const char* charOptionNames[] = { "element_order",   // linear
92                                     "tags",            // respect
93                                     "" // mark of end
94   };
95
96   int i = 0;
97   while (boolOptionNames[i][0])
98   {
99     _boolOptions.insert( boolOptionNames[i] );
100     _option2value[boolOptionNames[i++]].clear();
101   }
102   i = 0;
103   while (intOptionNames[i][0])
104     _option2value[intOptionNames[i++]].clear();
105
106   i = 0;
107   while (doubleOptionNames[i][0]) {
108     _doubleOptions.insert(doubleOptionNames[i]);
109     _option2value[doubleOptionNames[i++]].clear();
110   }
111   i = 0;
112   while (charOptionNames[i][0]) {
113     _charOptions.insert(charOptionNames[i]);
114     _option2value[charOptionNames[i++]].clear();
115   }
116
117   // default values to be used while MG meshing
118
119   _defaultOptionValues["allow_invalid_elements"     ] = "no";
120   _defaultOptionValues["enforce_constant_layer_size"] = "no";
121   _defaultOptionValues["compute_ridges"             ] = "yes";
122   _defaultOptionValues["flatten_hexa_sides"         ] = "no";
123   _defaultOptionValues["recover_sharp_angles"       ] = "yes";
124   _defaultOptionValues["max_memory"                 ] = "2048";
125   _defaultOptionValues["max_number_of_threads"      ] = "4";
126   _defaultOptionValues["min_level"                  ] = "6";
127   _defaultOptionValues["max_level"                  ] = "10";
128   _defaultOptionValues["sizemap_level"              ] = "10";
129   _defaultOptionValues["ridge_angle"                ] = "60";
130   _defaultOptionValues["element_order"              ] = "linear";
131   _defaultOptionValues["tags"                       ] = "respect";
132
133 #ifdef _DEBUG_
134   // check validity of option names of _defaultOptionValues
135   TOptionValues::iterator n2v = _defaultOptionValues.begin();
136   for ( ; n2v != _defaultOptionValues.end(); ++n2v )
137     ASSERT( _option2value.count( n2v->first ));
138   ASSERT( _option2value.size() == _defaultOptionValues.size() );
139 #endif
140 }
141
142 //=============================================================================
143 /*!
144  *
145  */
146 //=============================================================================
147
148 void HexoticPlugin_Hypothesis::SetHexesMinLevel(int theVal)
149 {
150   SetOptionValue( "min_level", SMESH_Comment( theVal ));
151   _hexesMinLevel = theVal;
152 }
153
154 void HexoticPlugin_Hypothesis::SetHexesMaxLevel(int theVal)
155 {
156   SetOptionValue( "max_level", SMESH_Comment( theVal ));
157   _hexesMaxLevel = theVal;
158 }
159
160 void HexoticPlugin_Hypothesis::SetMinSize(double theVal) {
161   if (theVal != _minSize) {
162     _minSize = theVal;
163     NotifySubMeshesHypothesisModification();
164   }
165 }
166
167 void HexoticPlugin_Hypothesis::SetMaxSize(double theVal) {
168   if (theVal != _maxSize) {
169     _maxSize = theVal;
170     NotifySubMeshesHypothesisModification();
171   }
172 }
173
174 void HexoticPlugin_Hypothesis::SetGeomApproxAngle(double theVal) {
175   if (theVal != _approxAngle) {
176     _approxAngle = theVal;
177     NotifySubMeshesHypothesisModification();
178   }
179 }
180
181 void HexoticPlugin_Hypothesis::SetHexoticIgnoreRidges(bool theVal) {
182   SetOptionValue( "compute_ridges", theVal ? "no" : "yes" );
183   _hexoticIgnoreRidges = theVal;
184 }
185
186 void HexoticPlugin_Hypothesis::SetHexoticInvalidElements(bool theVal)
187 {
188   SetOptionValue( "allow_invalid_elements", theVal ? "yes" : "no" );
189   _hexoticInvalidElements = theVal;
190 }
191
192 void HexoticPlugin_Hypothesis::SetHexoticSharpAngleThreshold(double theVal)
193 {
194   SetOptionValue( "ridge_angle", SMESH_Comment( theVal ));
195   _hexoticSharpAngleThreshold = theVal;
196 }
197
198 void HexoticPlugin_Hypothesis::SetHexoticNbProc(int theVal)
199 {
200   SetOptionValue( "max_number_of_threads", SMESH_Comment( theVal ));
201   _hexoticNbProc = theVal;
202 }
203
204 void HexoticPlugin_Hypothesis::SetHexoticWorkingDirectory(const std::string& path)
205 {
206   if ( _hexoticWorkingDirectory != path ) {
207     _hexoticWorkingDirectory = path;
208     if ( !path.empty() )
209     {
210 #ifdef WIN32
211       if( path[ path.size()-1 ] != '\\')
212         _hexoticWorkingDirectory += '\\';
213 #else
214       if( path[ path.size()-1 ] != '/')
215         _hexoticWorkingDirectory += '/';
216 #endif
217     }
218     NotifySubMeshesHypothesisModification();
219   }
220 }
221
222 void HexoticPlugin_Hypothesis::SetHexoticSdMode(int theVal) {
223   if (theVal != _hexoticSdMode) {
224     _hexoticSdMode = theVal;
225     NotifySubMeshesHypothesisModification();
226   }
227 }
228
229 void HexoticPlugin_Hypothesis::SetHexoticVerbosity(int theVal) {
230   if (theVal != _hexoticVerbosity) {
231     _hexoticVerbosity = theVal;
232     NotifySubMeshesHypothesisModification();
233   }
234 }
235
236 void HexoticPlugin_Hypothesis::SetHexoticMaxMemory(int theVal)
237 {
238   SetOptionValue( "max_memory", SMESH_Comment( theVal ));
239   _hexoticMaxMemory = theVal;
240 }
241
242 void HexoticPlugin_Hypothesis::SetKeepFiles(bool toKeep)
243 {
244   if ( _keepFiles != toKeep ) {
245     _keepFiles = toKeep;
246     NotifySubMeshesHypothesisModification();
247   }
248 }
249
250 void HexoticPlugin_Hypothesis::SetStandardOutputLog(bool logInStandardOutput)
251 {
252   if ( _logInStandardOutput != logInStandardOutput ) {
253     _logInStandardOutput = logInStandardOutput;
254     NotifySubMeshesHypothesisModification();
255   }
256 }
257
258 void HexoticPlugin_Hypothesis::SetRemoveLogOnSuccess(bool removeLogOnSuccess)
259 {
260   if ( _removeLogOnSuccess != removeLogOnSuccess ) {
261     _removeLogOnSuccess = removeLogOnSuccess;
262     NotifySubMeshesHypothesisModification();
263   }
264 }
265
266 void HexoticPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
267                                               const std::string& optionValue)
268 {
269   TOptionValues::iterator op_val = _option2value.find(optionName);
270   if (op_val == _option2value.end())
271   {
272     op_val = _customOption2value.find( optionName );
273     if ( op_val != _customOption2value.end() && op_val->second != optionValue )
274       NotifySubMeshesHypothesisModification();
275     _customOption2value[ optionName ] = optionValue;
276     return;
277   }
278
279   if (op_val->second != optionValue)
280   {
281     const char* ptr = optionValue.c_str();
282     // strip white spaces
283     while (ptr[0] == ' ')
284       ptr++;
285     int i = strlen(ptr);
286     while (i != 0 && ptr[i - 1] == ' ')
287       i--;
288     // check value type
289     bool typeOk = true;
290     std::string typeName;
291     if (i == 0) {
292       // empty string
293     } else if (_charOptions.count(optionName)) {
294       // do not check strings
295     } else if (_doubleOptions.count(optionName)) {
296       // check if value is double
297       ToDbl(ptr, &typeOk);
298       typeName = "real";
299     } else if (_boolOptions.count(optionName)) {
300       // check if value is bool
301       ToBool(ptr, &typeOk);
302       typeName = "bool";
303     } else {
304       // check if value is int
305       ToInt(ptr, &typeOk);
306       typeName = "integer";
307     }
308     if ( typeOk ) // check some specific values ?
309     {
310     }
311     if ( !typeOk )
312     {
313       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
314       throw std::invalid_argument(msg);
315     }
316     std::string value( ptr, i );
317     if ( _defaultOptionValues[ optionName ] == value )
318       value.clear();
319
320     op_val->second = value;
321
322     NotifySubMeshesHypothesisModification();
323   }
324 }
325
326 //=============================================================================
327 //! Return option value. If isDefault provided, it can be a default value,
328 //  then *isDefault == true. If isDefault is not provided, the value will be
329 //  empty if it equals a default one.
330 std::string HexoticPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
331                                                      bool*              isDefault) const
332 {
333   TOptionValues::const_iterator op_val = _option2value.find(optionName);
334   if (op_val == _option2value.end())
335   {
336     op_val = _customOption2value.find(optionName);
337     if (op_val == _customOption2value.end())
338     {
339       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
340       throw std::invalid_argument(msg);
341     }
342   }
343   std::string val = op_val->second;
344   if ( isDefault ) *isDefault = ( val.empty() );
345
346   if ( val.empty() && isDefault )
347   {
348     op_val = _defaultOptionValues.find( optionName );
349     if (op_val != _defaultOptionValues.end())
350       val = op_val->second;
351   }
352   return val;
353 }
354
355
356 //=============================================================================
357 bool HexoticPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
358 {
359   bool isDefault = false;
360   try
361   {
362     GetOptionValue( optionName, &isDefault );
363   }
364   catch ( std::invalid_argument& )
365   {
366     return false;
367   }
368   return !isDefault;
369 }
370
371 //=============================================================================
372 void HexoticPlugin_Hypothesis::ClearOption(const std::string& optionName)
373 {
374   TOptionValues::iterator op_val = _customOption2value.find(optionName);
375   if (op_val != _customOption2value.end())
376     _customOption2value.erase(op_val);
377   else {
378     op_val = _option2value.find(optionName);
379     if (op_val != _option2value.end())
380       op_val->second.clear();
381   }
382 }
383
384 //=============================================================================
385 HexoticPlugin_Hypothesis::TOptionValues HexoticPlugin_Hypothesis::GetOptionValues() const
386 {
387   TOptionValues vals;
388   TOptionValues::const_iterator op_val = _option2value.begin();
389   for ( ; op_val != _option2value.end(); ++op_val )
390     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
391
392   return vals;
393 }
394
395 //================================================================================
396 /*!
397  * \brief Converts a string to a bool
398  */
399 //================================================================================
400
401 bool HexoticPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
402 {
403   std::string s = str;
404   if ( isOk ) *isOk = true;
405
406   for ( size_t i = 0; i <= s.size(); ++i )
407     s[i] = tolower( s[i] );
408
409   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
410     return true;
411
412   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
413     return false;
414
415   if ( isOk )
416     *isOk = false;
417   else {
418     std::string msg = "Not a Boolean value:'" + str + "'";
419     throw std::invalid_argument(msg);
420   }
421   return false;
422 }
423
424 //================================================================================
425 /*!
426  * \brief Converts a string to a real value
427  */
428 //================================================================================
429
430 double HexoticPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
431 {
432   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
433
434   char * endPtr;
435   double val = strtod(&str[0], &endPtr);
436   bool ok = (&str[0] != endPtr);
437
438   if ( isOk ) *isOk = ok;
439
440   if ( !ok )
441   {
442     std::string msg = "Not a real value:'" + str + "'";
443     throw std::invalid_argument(msg);
444   }
445   return val;
446 }
447
448 //================================================================================
449 /*!
450  * \brief Converts a string to a integer value
451  */
452 //================================================================================
453
454 int HexoticPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
455 {
456   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
457
458   char * endPtr;
459   int val = (int)strtol( &str[0], &endPtr, 10);
460   bool ok = (&str[0] != endPtr);
461
462   if ( isOk ) *isOk = ok;
463
464   if ( !ok )
465   {
466     std::string msg = "Not an integer value:'" + str + "'";
467     throw std::invalid_argument(msg);
468   }
469   return val;
470 }
471
472 void HexoticPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
473 {
474   size_t wsPos = option.find(' ');
475   if ( wsPos == std::string::npos )
476   {
477     SetOptionValue( option, "" );
478   }
479   else
480   {
481     std::string opt( option, 0, wsPos );
482     std::string val( option, wsPos + 1 );
483     SetOptionValue( opt, val );
484   }
485 }
486
487 //=======================================================================
488 //function : GetAdvancedOption
489 //purpose  : Return only options having NO corresponding member fields
490 //=======================================================================
491
492 std::string HexoticPlugin_Hypothesis::GetAdvancedOption( bool customOnly ) const
493 {
494   // options having corresponding member fields
495   static std::set< std::string > toSkip = {
496     "min_level",
497     "max_level",
498     "compute_ridges",
499     "allow_invalid_elements",
500     "ridge_angle",
501     "max_number_of_threads",
502     "max_memory"
503   };
504
505   // Return only options having NO corresponding member fields
506
507   SMESH_Comment txt;
508
509   TOptionValues::const_iterator o2v = _option2value.begin();
510   if ( !customOnly )
511   {
512     for ( ; o2v != _option2value.end(); ++o2v )
513       if ( !o2v->second.empty() && !toSkip.count( o2v->first ))
514       {
515         if ( !txt.empty() )
516           txt << " ";
517         txt << "--" << o2v->first << " " << o2v->second;
518       }
519   }
520   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
521   {
522     if ( !txt.empty() )
523       txt << " ";
524     // if ( o2v->first[0] != '-' )
525     //   txt << "--";
526     txt << o2v->first << " " << o2v->second;
527   }
528   return txt;
529 }
530
531 bool HexoticPlugin_Hypothesis::AddSizeMap(std::string theEntry, double theSize)
532 {
533   THexoticSizeMaps::iterator it;
534   it=_sizeMaps.find(theEntry);
535
536   if(theSize <= 0)
537     return false;
538
539   if( it == _sizeMaps.end() ) // If no size map is defined on the given object
540   {
541     _sizeMaps[theEntry] = theSize;
542     MESSAGE("NEW size map, entry :"<<theEntry<<", size : "<<theSize);
543     NotifySubMeshesHypothesisModification();
544     return true;
545   }
546   else if( it->second != theSize ) // If a size map exists with a different size value
547   {
548     it->second = theSize;
549     MESSAGE("MODIFIED size map, entry :"<<theEntry<<"with size : "<<theSize);
550     NotifySubMeshesHypothesisModification();
551     return true;
552   }
553   else
554   {
555     MESSAGE("NO size map added");
556     return false; // No size map added
557   }
558 }
559
560 bool HexoticPlugin_Hypothesis::UnsetSizeMap(std::string theEntry) {
561   THexoticSizeMaps::iterator it;
562   it=_sizeMaps.find(theEntry);
563   if( it != _sizeMaps.end() )
564   {
565     _sizeMaps.erase(it);  
566     return true;
567   }
568   else
569     return false;
570 }
571
572 void HexoticPlugin_Hypothesis::SetNbLayers(int theVal) {
573   if (theVal != _nbLayers) {
574     _nbLayers = theVal;
575     NotifySubMeshesHypothesisModification();
576   }
577 }
578
579 void HexoticPlugin_Hypothesis::SetFirstLayerSize(double theVal) {
580   if (theVal != _firstLayerSize) {
581     _firstLayerSize = theVal;
582     NotifySubMeshesHypothesisModification();
583   }
584 }
585
586 void HexoticPlugin_Hypothesis::SetDirection(bool theVal) {
587   if (theVal != _direction) {
588     _direction = theVal;
589     NotifySubMeshesHypothesisModification();
590   }
591 }
592
593 void HexoticPlugin_Hypothesis::SetGrowth(double theVal) {
594   if (theVal != _growth) {
595     _growth = theVal;
596     NotifySubMeshesHypothesisModification();
597   }
598 }
599
600 bool HexoticPlugin_Hypothesis::SetFacesWithLayers(const std::vector<int>& theVal) {
601   if ( _facesWithLayers != theVal ) {
602           _facesWithLayers = theVal;
603     NotifySubMeshesHypothesisModification();
604     return true;
605   }
606   return false;
607 }
608
609 bool HexoticPlugin_Hypothesis::SetImprintedFaces(const std::vector<int>& theVal) {
610   if ( _imprintedFaces != theVal ) {
611           _imprintedFaces = theVal;
612     NotifySubMeshesHypothesisModification();
613     return true;
614   }
615   return false;
616 }
617
618 //=============================================================================
619 /*!
620  *  
621  */
622 //=============================================================================
623 std::ostream& HexoticPlugin_Hypothesis::SaveTo(std::ostream& save)
624 {
625   //explicit outputs for future code compatibility of saved .hdf
626   //save without any whitespaces!
627   //int dummy = -1;
628   save<<"hexesMinLevel="<<_hexesMinLevel<<";";
629   save<<"hexesMaxLevel="<<_hexesMaxLevel<<";";
630   save<<"hexoticIgnoreRidges="<<(int)_hexoticIgnoreRidges<<";";
631   save<<"hexoticInvalidElements="<<(int)_hexoticInvalidElements<<";";
632   save<<"hexoticSharpAngleThreshold="<<_hexoticSharpAngleThreshold<<";";
633   save<<"hexoticNbProc="<<_hexoticNbProc<<";";
634   save<<"hexoticWorkingDirectory="<<_hexoticWorkingDirectory<<";";
635   save<<"minSize="<<_minSize<<";";
636   save<<"maxSize="<<_maxSize<<";";
637   save<<"hexoticSdMode="<<_hexoticSdMode<<";";
638   save<<"hexoticVerbosity="<<_hexoticVerbosity<<";";
639   save<<"hexoticMaxMemory="<<_hexoticMaxMemory<<";";
640   std::string textOptions;// = _textOptions;
641   replace(textOptions.begin(), textOptions.end(), ' ', '*');
642   save<<"textOptions="<<textOptions<<";";
643   THexoticSizeMaps::iterator it = _sizeMaps.begin();
644   if ( it != _sizeMaps.end() )
645   {
646     save<<"sizeMaps=";
647     for ( ; it!=_sizeMaps.end() ; it++ )
648     {
649       save<< it->first << "/" << it->second << "#" ;
650     }
651     save<<";";
652   }
653   save<<"nbLayers="<<_nbLayers<<";";
654   save<<"firstLayerSize="<<_firstLayerSize<<";";
655   save<<"direction="<<_direction<<";";
656   save<<"growth="<<_growth<<";";
657   if ( !_facesWithLayers.empty() )
658   {
659     save<<"facesWithLayers=";
660     for ( size_t i = 0; i < _facesWithLayers.size(); i++ )
661     {
662       save<< _facesWithLayers.at(i) << "#" ;
663     }
664     save<<";";
665   }
666   if ( !_imprintedFaces.empty() )
667   {
668     save<<"imprintedFaces=";
669     for ( size_t i = 0; i < _imprintedFaces.size(); i++ )
670     {
671       save<< _imprintedFaces.at(i) << "#" ;
672     }
673     save<<";";
674   }
675
676   // New options in 2.9.6 (issue #17784)
677
678   save << " " << _approxAngle;
679   save << " " << _logInStandardOutput;
680   save << " " << _removeLogOnSuccess;
681   save << " " << _keepFiles;
682
683   save << " " << _option2value.size();
684   TOptionValues::iterator o2v = _option2value.begin();
685   for ( ; o2v != _option2value.end(); ++o2v )
686     save << " -" << o2v->first << " -" << o2v->second;
687
688   save << " " << _customOption2value.size();
689   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
690     save << " -" << o2v->first << " -" << o2v->second;
691
692   return save;
693 }
694
695 //=============================================================================
696 /*!
697  *
698  */
699 //=============================================================================
700 std::istream& HexoticPlugin_Hypothesis::LoadFrom(std::istream& load)
701 {
702    //explicit inputs for future code compatibility of saved .hdf
703    bool isOK = true;
704    std::string str1,str2,str3,str4;
705
706    //save without any whitespaces!
707    isOK = static_cast<bool>(load >> str1);
708    if (!(isOK)) {
709      //defaults values assumed
710      load.clear(std::ios::badbit | load.rdstate());
711      return load;
712    }
713    int pos = 0;
714    int len = str1.length();
715    while (pos < len) {
716       int found = str1.find(';',pos);
717       str2 = str1.substr(pos,found-pos);
718       int eqpos = str2.find('=',0);
719       str3 = str2.substr(0,eqpos);
720       str4 = str2.substr(eqpos+1);
721       pos = found + 1;
722
723       if (str3=="hexesMinLevel")              _hexesMinLevel              = atoi(str4.c_str());
724       if (str3=="hexesMaxLevel")              _hexesMaxLevel              = atoi(str4.c_str());
725       if (str3=="hexoticQuadrangles") {}
726       if (str3=="hexoticIgnoreRidges")        _hexoticIgnoreRidges    = (bool) atoi(str4.c_str());
727       if (str3=="hexoticInvalidElements")     _hexoticInvalidElements = (bool) atoi(str4.c_str());
728       if (str3=="hexoticSharpAngleThreshold") _hexoticSharpAngleThreshold = atof(str4.c_str());
729       if (str3=="hexoticNbProc")              _hexoticNbProc              = atoi(str4.c_str());
730       if (str3=="hexoticWorkingDirectory")    _hexoticWorkingDirectory    = str4;
731       if (str3=="minSize")                    _minSize                    = atof(str4.c_str());
732       if (str3=="maxSize")                    _maxSize                    = atof(str4.c_str());
733       if (str3=="hexoticSdMode")              _hexoticSdMode              = atoi(str4.c_str());
734       if (str3=="hexoticVerbosity")           _hexoticVerbosity           = atoi(str4.c_str());
735       if (str3=="hexoticMaxMemory")           _hexoticMaxMemory           = atoi(str4.c_str());
736       if (str3=="textOptions")
737       {
738         replace(str4.begin(), str4.end(), '*', ' ');
739         //_textOptions = str4;
740       }
741       if (str3=="sizeMaps")
742       {
743         std::string sm_substr, sm_substr1, sm_substr2;
744         int sm_pos = 0;
745         int sm_len = str4.length();
746         while ( sm_pos < sm_len )
747         {
748           int sm_found = str4.find('#',sm_pos);
749           sm_substr = str4.substr(sm_pos,sm_found-sm_pos);
750           int sm_slashpos = sm_substr.find('/',0);
751           sm_substr1 = sm_substr.substr(0,sm_slashpos);
752           sm_substr2 = sm_substr.substr(sm_slashpos+1);
753           _sizeMaps[sm_substr1] = atof(sm_substr2.c_str());
754           sm_pos = sm_found + 1;
755         }
756       }
757       if (str3 == "nbLayers")       _nbLayers       = atoi(str4.c_str());
758       if (str3 == "firstLayerSize") _firstLayerSize = atof(str4.c_str());
759       if (str3 == "direction")      _direction      = atoi(str4.c_str());
760       if (str3 == "growth")         _growth         = atof(str4.c_str());
761       if (str3 == "facesWithLayers")
762       {
763         std::string id;
764         size_t pos = 0;
765         while ( pos < str4.length() )
766         {
767           int found = str4.find('#',pos);
768           id = str4.substr(pos, found-pos);
769           _facesWithLayers.push_back(atoi(id.c_str()));
770           pos = found + 1;
771         }
772       }
773       if (str3 == "imprintedFaces")
774       {
775         std::string id;
776         size_t pos = 0;
777         while ( pos < str4.length() )
778         {
779           int found = str4.find('#',pos);
780           id = str4.substr(pos, found-pos);
781           _imprintedFaces.push_back(atoi(id.c_str()));
782           pos = found + 1;
783         }
784       }
785    }
786
787    // New options in 2.9.6 (issue #17784)
788
789    if ( static_cast<bool>( load >> _approxAngle ))
790    {
791      int i;
792      load >> i; _logInStandardOutput = (bool)i;
793      load >> i; _removeLogOnSuccess = (bool)i;
794      load >> i; _keepFiles = (bool)i;
795
796      std::string option, value;
797      if ( static_cast<bool>( load >> i ) && i >= 0 )
798      {
799        for ( int nbRead = 0; nbRead < i; ++nbRead )
800        {
801          load >> option >> value;
802          _option2value[ std::string( option, 1 )] = std::string( value, 1 );
803        }
804      }
805      if ( static_cast<bool>( load >> i ) && i >= 0 )
806      {
807        for ( int nbRead = 0; nbRead < i; ++nbRead )
808        {
809          load >> option >> value;
810          _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
811        }
812      }
813    }
814    else // pass old basic parameters to new advanced ones
815    {
816      SetHexesMinLevel             ( _hexesMinLevel );
817      SetHexesMaxLevel             ( _hexesMaxLevel );
818      SetHexoticIgnoreRidges       ( _hexoticIgnoreRidges );
819      SetHexoticInvalidElements    ( _hexoticInvalidElements );
820      SetHexoticSharpAngleThreshold( _hexoticSharpAngleThreshold );
821      SetHexoticNbProc             ( _hexoticNbProc );
822      SetHexoticMaxMemory          ( _hexoticMaxMemory );
823    }
824
825    return load;
826 }
827
828 //=============================================================================
829 /*!
830  *  
831  */
832 //=============================================================================
833 std::ostream& operator <<(std::ostream& save, HexoticPlugin_Hypothesis& hyp)
834 {
835   return hyp.SaveTo( save );
836 }
837
838 //=============================================================================
839 /*!
840  *  
841  */
842 //=============================================================================
843 std::istream& operator >>(std::istream& load, HexoticPlugin_Hypothesis& hyp)
844 {
845   return hyp.LoadFrom( load );
846 }
847
848
849 //================================================================================
850 /*!
851  * \brief Does nothing
852  * \param theMesh - the built mesh
853  * \param theShape - the geometry of interest
854  * \retval bool - always false
855  */
856 //================================================================================
857 bool HexoticPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh*   /*theMesh*/,
858                                                    const TopoDS_Shape& /*theShape*/)
859 {
860   return false;
861 }
862 //================================================================================
863 /*!
864  * \brief Initialize my parameter values by default parameters.
865  *  \retval bool - true if parameter values have been successfully defined
866  */
867 //================================================================================
868
869 bool HexoticPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  /*dflts*/,
870                                                        const SMESH_Mesh* /*theMesh*/)
871 {
872   return false;
873 }
874
875 //=============================================================================
876 int HexoticPlugin_Hypothesis::GetDefaultHexesMinLevel()
877 {
878   return 6;
879 }
880
881 int HexoticPlugin_Hypothesis::GetDefaultHexesMaxLevel()
882 {
883   return 10;
884 }
885
886 double HexoticPlugin_Hypothesis::GetDefaultMinSize()
887 {
888   return 0.0;
889 }
890
891 double HexoticPlugin_Hypothesis::GetDefaultMaxSize()
892 {
893   return 0.0;
894 }
895
896 bool HexoticPlugin_Hypothesis::GetDefaultHexoticIgnoreRidges()
897 {
898   return false;
899 }
900
901 bool HexoticPlugin_Hypothesis::GetDefaultHexoticInvalidElements()
902 {
903   return false;
904 }
905
906 double HexoticPlugin_Hypothesis::GetDefaultHexoticSharpAngleThreshold()
907 {
908   return 60.0;
909 }
910
911 int HexoticPlugin_Hypothesis::GetDefaultHexoticNbProc()
912 {
913   return 4;
914 }
915
916 std::string HexoticPlugin_Hypothesis::GetDefaultHexoticWorkingDirectory()
917 {
918   std::string aTmpDir;
919
920   char *Tmp_dir = getenv("SALOME_TMP_DIR");
921 #ifdef WIN32
922   if(Tmp_dir == NULL) {
923     Tmp_dir = getenv("TEMP");
924     if( Tmp_dir== NULL )
925       Tmp_dir = getenv("TMP");
926   }
927 #endif
928   if( Tmp_dir != NULL ) {
929     aTmpDir = std::string(Tmp_dir);
930 #ifdef WIN32
931     if(aTmpDir[aTmpDir.size()-1] != '\\') aTmpDir+='\\';
932 #else
933     if(aTmpDir[aTmpDir.size()-1] != '/') aTmpDir+='/';
934 #endif
935   }
936   else {
937 #ifdef WIN32
938     aTmpDir = "C:\\";
939 #else
940     aTmpDir = "/tmp/";
941 #endif
942   }
943   return aTmpDir;
944 }
945
946 int HexoticPlugin_Hypothesis::GetDefaultHexoticSdMode()
947 {
948   return 4;
949 }
950
951 int HexoticPlugin_Hypothesis::GetDefaultHexoticVerbosity()
952 {
953   return 1;
954 }
955
956 int HexoticPlugin_Hypothesis::GetDefaultHexoticMaxMemory()
957 {
958   return 2048;
959 }
960
961 std::string HexoticPlugin_Hypothesis::GetDefaultTextOptions()
962 {
963   return "";
964 }
965
966 HexoticPlugin_Hypothesis::THexoticSizeMaps HexoticPlugin_Hypothesis::GetDefaultHexoticSizeMaps()
967 {
968   return THexoticSizeMaps();
969 }
970
971 int HexoticPlugin_Hypothesis::GetDefaultNbLayers()
972 {
973   return 0;
974 }
975
976 double HexoticPlugin_Hypothesis::GetDefaultFirstLayerSize()
977 {
978   return 0.0;
979 }
980
981 bool HexoticPlugin_Hypothesis::GetDefaultDirection()
982 {
983   return true;
984 }
985
986 double HexoticPlugin_Hypothesis::GetDefaultGrowth()
987 {
988   return 0.0;
989 }
990
991 std::vector<int> HexoticPlugin_Hypothesis::GetDefaultFacesWithLayers()
992 {
993   return std::vector<int>();
994 }
995
996 std::vector<int> HexoticPlugin_Hypothesis::GetDefaultImprintedFaces()
997 {
998   return std::vector<int>();
999 }