Salome HOME
#17784 [EDF] MESH-GEMS-2.9.6 Meshers options
[plugins/hexoticplugin.git] / src / HexoticPlugin / HexoticPlugin_Hypothesis.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF 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, 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   throw (std::invalid_argument)
269 {
270   TOptionValues::iterator op_val = _option2value.find(optionName);
271   if (op_val == _option2value.end())
272   {
273     op_val = _customOption2value.find( optionName );
274     if ( op_val != _customOption2value.end() && op_val->second != optionValue )
275       NotifySubMeshesHypothesisModification();
276     _customOption2value[ optionName ] = optionValue;
277     return;
278   }
279
280   if (op_val->second != optionValue)
281   {
282     const char* ptr = optionValue.c_str();
283     // strip white spaces
284     while (ptr[0] == ' ')
285       ptr++;
286     int i = strlen(ptr);
287     while (i != 0 && ptr[i - 1] == ' ')
288       i--;
289     // check value type
290     bool typeOk = true;
291     std::string typeName;
292     if (i == 0) {
293       // empty string
294     } else if (_charOptions.count(optionName)) {
295       // do not check strings
296     } else if (_doubleOptions.count(optionName)) {
297       // check if value is double
298       ToDbl(ptr, &typeOk);
299       typeName = "real";
300     } else if (_boolOptions.count(optionName)) {
301       // check if value is bool
302       ToBool(ptr, &typeOk);
303       typeName = "bool";
304     } else {
305       // check if value is int
306       ToInt(ptr, &typeOk);
307       typeName = "integer";
308     }
309     if ( typeOk ) // check some specific values ?
310     {
311     }
312     if ( !typeOk )
313     {
314       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
315       throw std::invalid_argument(msg);
316     }
317     std::string value( ptr, i );
318     if ( _defaultOptionValues[ optionName ] == value )
319       value.clear();
320
321     op_val->second = value;
322
323     NotifySubMeshesHypothesisModification();
324   }
325 }
326
327 //=============================================================================
328 //! Return option value. If isDefault provided, it can be a default value,
329 //  then *isDefault == true. If isDefault is not provided, the value will be
330 //  empty if it equals a default one.
331 std::string HexoticPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
332                                                      bool*              isDefault) const
333   throw (std::invalid_argument)
334 {
335   TOptionValues::const_iterator op_val = _option2value.find(optionName);
336   if (op_val == _option2value.end())
337   {
338     op_val = _customOption2value.find(optionName);
339     if (op_val == _customOption2value.end())
340     {
341       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
342       throw std::invalid_argument(msg);
343     }
344   }
345   std::string val = op_val->second;
346   if ( isDefault ) *isDefault = ( val.empty() );
347
348   if ( val.empty() && isDefault )
349   {
350     op_val = _defaultOptionValues.find( optionName );
351     if (op_val != _defaultOptionValues.end())
352       val = op_val->second;
353   }
354   return val;
355 }
356
357
358 //=============================================================================
359 bool HexoticPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
360 {
361   bool isDefault = false;
362   try
363   {
364     GetOptionValue( optionName, &isDefault );
365   }
366   catch ( std::invalid_argument )
367   {
368     return false;
369   }
370   return !isDefault;
371 }
372
373 //=============================================================================
374 void HexoticPlugin_Hypothesis::ClearOption(const std::string& optionName)
375 {
376   TOptionValues::iterator op_val = _customOption2value.find(optionName);
377   if (op_val != _customOption2value.end())
378     _customOption2value.erase(op_val);
379   else {
380     op_val = _option2value.find(optionName);
381     if (op_val != _option2value.end())
382       op_val->second.clear();
383   }
384 }
385
386 //=============================================================================
387 HexoticPlugin_Hypothesis::TOptionValues HexoticPlugin_Hypothesis::GetOptionValues() const
388 {
389   TOptionValues vals;
390   TOptionValues::const_iterator op_val = _option2value.begin();
391   for ( ; op_val != _option2value.end(); ++op_val )
392     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
393
394   return vals;
395 }
396
397 //================================================================================
398 /*!
399  * \brief Converts a string to a bool
400  */
401 //================================================================================
402
403 bool HexoticPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
404   throw (std::invalid_argument)
405 {
406   std::string s = str;
407   if ( isOk ) *isOk = true;
408
409   for ( size_t i = 0; i <= s.size(); ++i )
410     s[i] = tolower( s[i] );
411
412   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
413     return true;
414
415   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
416     return false;
417
418   if ( isOk )
419     *isOk = false;
420   else {
421     std::string msg = "Not a Boolean value:'" + str + "'";
422     throw std::invalid_argument(msg);
423   }
424   return false;
425 }
426
427 //================================================================================
428 /*!
429  * \brief Converts a string to a real value
430  */
431 //================================================================================
432
433 double HexoticPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
434   throw (std::invalid_argument)
435 {
436   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
437
438   char * endPtr;
439   double val = strtod(&str[0], &endPtr);
440   bool ok = (&str[0] != endPtr);
441
442   if ( isOk ) *isOk = ok;
443
444   if ( !ok )
445   {
446     std::string msg = "Not a real value:'" + str + "'";
447     throw std::invalid_argument(msg);
448   }
449   return val;
450 }
451
452 //================================================================================
453 /*!
454  * \brief Converts a string to a integer value
455  */
456 //================================================================================
457
458 int HexoticPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
459   throw (std::invalid_argument)
460 {
461   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
462
463   char * endPtr;
464   int val = (int)strtol( &str[0], &endPtr, 10);
465   bool ok = (&str[0] != endPtr);
466
467   if ( isOk ) *isOk = ok;
468
469   if ( !ok )
470   {
471     std::string msg = "Not an integer value:'" + str + "'";
472     throw std::invalid_argument(msg);
473   }
474   return val;
475 }
476
477 void HexoticPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
478 {
479   size_t wsPos = option.find(' ');
480   if ( wsPos == std::string::npos )
481   {
482     SetOptionValue( option, "" );
483   }
484   else
485   {
486     std::string opt( option, 0, wsPos );
487     std::string val( option, wsPos + 1 );
488     SetOptionValue( opt, val );
489   }
490 }
491
492 //=======================================================================
493 //function : GetAdvancedOption
494 //purpose  : Return only options having NO corresponding member fields
495 //=======================================================================
496
497 std::string HexoticPlugin_Hypothesis::GetAdvancedOption( bool customOnly ) const
498 {
499   // options having corresponding member fields
500   static std::set< std::string > toSkip = {
501     "min_level",
502     "max_level",
503     "compute_ridges",
504     "allow_invalid_elements",
505     "ridge_angle",
506     "max_number_of_threads",
507     "max_memory"
508   };
509
510   // Return only options having NO corresponding member fields
511
512   SMESH_Comment txt;
513
514   TOptionValues::const_iterator o2v = _option2value.begin();
515   if ( !customOnly )
516   {
517     for ( ; o2v != _option2value.end(); ++o2v )
518       if ( !o2v->second.empty() && !toSkip.count( o2v->first ))
519       {
520         if ( !txt.empty() )
521           txt << " ";
522         txt << "--" << o2v->first << " " << o2v->second;
523       }
524   }
525   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
526   {
527     if ( !txt.empty() )
528       txt << " ";
529     // if ( o2v->first[0] != '-' )
530     //   txt << "--";
531     txt << o2v->first << " " << o2v->second;
532   }
533   return txt;
534 }
535
536 bool HexoticPlugin_Hypothesis::AddSizeMap(std::string theEntry, double theSize)
537 {
538   THexoticSizeMaps::iterator it;
539   it=_sizeMaps.find(theEntry);
540
541   if(theSize <= 0)
542     return false;
543
544   if( it == _sizeMaps.end() ) // If no size map is defined on the given object
545   {
546     _sizeMaps[theEntry] = theSize;
547     MESSAGE("NEW size map, entry :"<<theEntry<<", size : "<<theSize);
548     NotifySubMeshesHypothesisModification();
549     return true;
550   }
551   else if( it->second != theSize ) // If a size map exists with a different size value
552   {
553     it->second = theSize;
554     MESSAGE("MODIFIED size map, entry :"<<theEntry<<"with size : "<<theSize);
555     NotifySubMeshesHypothesisModification();
556     return true;
557   }
558   else
559   {
560     MESSAGE("NO size map added");
561     return false; // No size map added
562   }
563 }
564
565 bool HexoticPlugin_Hypothesis::UnsetSizeMap(std::string theEntry) {
566   THexoticSizeMaps::iterator it;
567   it=_sizeMaps.find(theEntry);
568   if( it != _sizeMaps.end() )
569   {
570     _sizeMaps.erase(it);  
571     return true;
572   }
573   else
574     return false;
575 }
576
577 void HexoticPlugin_Hypothesis::SetNbLayers(int theVal) {
578   if (theVal != _nbLayers) {
579     _nbLayers = theVal;
580     NotifySubMeshesHypothesisModification();
581   }
582 }
583
584 void HexoticPlugin_Hypothesis::SetFirstLayerSize(double theVal) {
585   if (theVal != _firstLayerSize) {
586     _firstLayerSize = theVal;
587     NotifySubMeshesHypothesisModification();
588   }
589 }
590
591 void HexoticPlugin_Hypothesis::SetDirection(bool theVal) {
592   if (theVal != _direction) {
593     _direction = theVal;
594     NotifySubMeshesHypothesisModification();
595   }
596 }
597
598 void HexoticPlugin_Hypothesis::SetGrowth(double theVal) {
599   if (theVal != _growth) {
600     _growth = theVal;
601     NotifySubMeshesHypothesisModification();
602   }
603 }
604
605 bool HexoticPlugin_Hypothesis::SetFacesWithLayers(const std::vector<int>& theVal) {
606   if ( _facesWithLayers != theVal ) {
607           _facesWithLayers = theVal;
608     NotifySubMeshesHypothesisModification();
609     return true;
610   }
611   return false;
612 }
613
614 bool HexoticPlugin_Hypothesis::SetImprintedFaces(const std::vector<int>& theVal) {
615   if ( _imprintedFaces != theVal ) {
616           _imprintedFaces = theVal;
617     NotifySubMeshesHypothesisModification();
618     return true;
619   }
620   return false;
621 }
622
623 //=============================================================================
624 /*!
625  *  
626  */
627 //=============================================================================
628 std::ostream& HexoticPlugin_Hypothesis::SaveTo(std::ostream& save)
629 {
630   //explicit outputs for future code compatibility of saved .hdf
631   //save without any whitespaces!
632   //int dummy = -1;
633   save<<"hexesMinLevel="<<_hexesMinLevel<<";";
634   save<<"hexesMaxLevel="<<_hexesMaxLevel<<";";
635   save<<"hexoticIgnoreRidges="<<(int)_hexoticIgnoreRidges<<";";
636   save<<"hexoticInvalidElements="<<(int)_hexoticInvalidElements<<";";
637   save<<"hexoticSharpAngleThreshold="<<_hexoticSharpAngleThreshold<<";";
638   save<<"hexoticNbProc="<<_hexoticNbProc<<";";
639   save<<"hexoticWorkingDirectory="<<_hexoticWorkingDirectory<<";";
640   save<<"minSize="<<_minSize<<";";
641   save<<"maxSize="<<_maxSize<<";";
642   save<<"hexoticSdMode="<<_hexoticSdMode<<";";
643   save<<"hexoticVerbosity="<<_hexoticVerbosity<<";";
644   save<<"hexoticMaxMemory="<<_hexoticMaxMemory<<";";
645   std::string textOptions;// = _textOptions;
646   replace(textOptions.begin(), textOptions.end(), ' ', '*');
647   save<<"textOptions="<<textOptions<<";";
648   THexoticSizeMaps::iterator it = _sizeMaps.begin();
649   if ( it != _sizeMaps.end() )
650   {
651     save<<"sizeMaps=";
652     for ( ; it!=_sizeMaps.end() ; it++ )
653     {
654       save<< it->first << "/" << it->second << "#" ;
655     }
656     save<<";";
657   }
658   save<<"nbLayers="<<_nbLayers<<";";
659   save<<"firstLayerSize="<<_firstLayerSize<<";";
660   save<<"direction="<<_direction<<";";
661   save<<"growth="<<_growth<<";";
662   if ( !_facesWithLayers.empty() )
663   {
664     save<<"facesWithLayers=";
665     for ( size_t i = 0; i < _facesWithLayers.size(); i++ )
666     {
667       save<< _facesWithLayers.at(i) << "#" ;
668     }
669     save<<";";
670   }
671   if ( !_imprintedFaces.empty() )
672   {
673     save<<"imprintedFaces=";
674     for ( size_t i = 0; i < _imprintedFaces.size(); i++ )
675     {
676       save<< _imprintedFaces.at(i) << "#" ;
677     }
678     save<<";";
679   }
680
681   // New options in 2.9.6 (issue #17784)
682
683   save << " " << _approxAngle;
684   save << " " << _logInStandardOutput;
685   save << " " << _removeLogOnSuccess;
686   save << " " << _keepFiles;
687
688   save << " " << _option2value.size();
689   TOptionValues::iterator o2v = _option2value.begin();
690   for ( ; o2v != _option2value.end(); ++o2v )
691     save << " -" << o2v->first << " -" << o2v->second;
692
693   save << " " << _customOption2value.size();
694   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
695     save << " -" << o2v->first << " -" << o2v->second;
696
697   return save;
698 }
699
700 //=============================================================================
701 /*!
702  *
703  */
704 //=============================================================================
705 std::istream& HexoticPlugin_Hypothesis::LoadFrom(std::istream& load)
706 {
707    //explicit inputs for future code compatibility of saved .hdf
708    bool isOK = true;
709    std::string str1,str2,str3,str4;
710
711    //save without any whitespaces!
712    isOK = static_cast<bool>(load >> str1);
713    if (!(isOK)) {
714      //defaults values assumed
715      load.clear(std::ios::badbit | load.rdstate());
716      return load;
717    }
718    int pos = 0;
719    int len = str1.length();
720    while (pos < len) {
721       int found = str1.find(';',pos);
722       str2 = str1.substr(pos,found-pos);
723       int eqpos = str2.find('=',0);
724       str3 = str2.substr(0,eqpos);
725       str4 = str2.substr(eqpos+1);
726       pos = found + 1;
727
728       if (str3=="hexesMinLevel")              _hexesMinLevel              = atoi(str4.c_str());
729       if (str3=="hexesMaxLevel")              _hexesMaxLevel              = atoi(str4.c_str());
730       if (str3=="hexoticQuadrangles") {}
731       if (str3=="hexoticIgnoreRidges")        _hexoticIgnoreRidges    = (bool) atoi(str4.c_str());
732       if (str3=="hexoticInvalidElements")     _hexoticInvalidElements = (bool) atoi(str4.c_str());
733       if (str3=="hexoticSharpAngleThreshold") _hexoticSharpAngleThreshold = atof(str4.c_str());
734       if (str3=="hexoticNbProc")              _hexoticNbProc              = atoi(str4.c_str());
735       if (str3=="hexoticWorkingDirectory")    _hexoticWorkingDirectory    = str4;
736       if (str3=="minSize")                    _minSize                    = atof(str4.c_str());
737       if (str3=="maxSize")                    _maxSize                    = atof(str4.c_str());
738       if (str3=="hexoticSdMode")              _hexoticSdMode              = atoi(str4.c_str());
739       if (str3=="hexoticVerbosity")           _hexoticVerbosity           = atoi(str4.c_str());
740       if (str3=="hexoticMaxMemory")           _hexoticMaxMemory           = atoi(str4.c_str());
741       if (str3=="textOptions")
742       {
743         replace(str4.begin(), str4.end(), '*', ' ');
744         //_textOptions = str4;
745       }
746       if (str3=="sizeMaps")
747       {
748         std::string sm_substr, sm_substr1, sm_substr2;
749         int sm_pos = 0;
750         int sm_len = str4.length();
751         while ( sm_pos < sm_len )
752         {
753           int sm_found = str4.find('#',sm_pos);
754           sm_substr = str4.substr(sm_pos,sm_found-sm_pos);
755           int sm_slashpos = sm_substr.find('/',0);
756           sm_substr1 = sm_substr.substr(0,sm_slashpos);
757           sm_substr2 = sm_substr.substr(sm_slashpos+1);
758           _sizeMaps[sm_substr1] = atof(sm_substr2.c_str());
759           sm_pos = sm_found + 1;
760         }
761       }
762       if (str3 == "nbLayers")       _nbLayers       = atoi(str4.c_str());
763       if (str3 == "firstLayerSize") _firstLayerSize = atof(str4.c_str());
764       if (str3 == "direction")      _direction      = atoi(str4.c_str());
765       if (str3 == "growth")         _growth         = atof(str4.c_str());
766       if (str3 == "facesWithLayers")
767       {
768         std::string id;
769         size_t pos = 0;
770         while ( pos < str4.length() )
771         {
772           int found = str4.find('#',pos);
773           id = str4.substr(pos, found-pos);
774           _facesWithLayers.push_back(atoi(id.c_str()));
775           pos = found + 1;
776         }
777       }
778       if (str3 == "imprintedFaces")
779       {
780         std::string id;
781         size_t pos = 0;
782         while ( pos < str4.length() )
783         {
784           int found = str4.find('#',pos);
785           id = str4.substr(pos, found-pos);
786           _imprintedFaces.push_back(atoi(id.c_str()));
787           pos = found + 1;
788         }
789       }
790    }
791
792    // New options in 2.9.6 (issue #17784)
793
794    if ( static_cast<bool>( load >> _approxAngle ))
795    {
796      int i;
797      load >> i; _logInStandardOutput = (bool)i;
798      load >> i; _removeLogOnSuccess = (bool)i;
799      load >> i; _keepFiles = (bool)i;
800
801      std::string option, value;
802      if ( static_cast<bool>( load >> i ) && i >= 0 )
803      {
804        for ( int nbRead = 0; nbRead < i; ++nbRead )
805        {
806          load >> option >> value;
807          _option2value[ std::string( option, 1 )] = std::string( value, 1 );
808        }
809      }
810      if ( static_cast<bool>( load >> i ) && i >= 0 )
811      {
812        for ( int nbRead = 0; nbRead < i; ++nbRead )
813        {
814          load >> option >> value;
815          _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
816        }
817      }
818    }
819
820    return load;
821 }
822
823 //=============================================================================
824 /*!
825  *  
826  */
827 //=============================================================================
828 std::ostream& operator <<(std::ostream& save, HexoticPlugin_Hypothesis& hyp)
829 {
830   return hyp.SaveTo( save );
831 }
832
833 //=============================================================================
834 /*!
835  *  
836  */
837 //=============================================================================
838 std::istream& operator >>(std::istream& load, HexoticPlugin_Hypothesis& hyp)
839 {
840   return hyp.LoadFrom( load );
841 }
842
843
844 //================================================================================
845 /*!
846  * \brief Does nothing
847  * \param theMesh - the built mesh
848  * \param theShape - the geometry of interest
849  * \retval bool - always false
850  */
851 //================================================================================
852 bool HexoticPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh*   theMesh,
853                                                    const TopoDS_Shape& theShape)
854 {
855   return false;
856 }
857 //================================================================================
858 /*!
859  * \brief Initialize my parameter values by default parameters.
860  *  \retval bool - true if parameter values have been successfully defined
861  */
862 //================================================================================
863
864 bool HexoticPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  /*dflts*/,
865                                                        const SMESH_Mesh* /*theMesh*/)
866 {
867   return false;
868 }
869
870 //=============================================================================
871 int HexoticPlugin_Hypothesis::GetDefaultHexesMinLevel()
872 {
873   return 6;
874 }
875
876 int HexoticPlugin_Hypothesis::GetDefaultHexesMaxLevel()
877 {
878   return 10;
879 }
880
881 double HexoticPlugin_Hypothesis::GetDefaultMinSize()
882 {
883   return 0.0;
884 }
885
886 double HexoticPlugin_Hypothesis::GetDefaultMaxSize()
887 {
888   return 0.0;
889 }
890
891 bool HexoticPlugin_Hypothesis::GetDefaultHexoticIgnoreRidges()
892 {
893   return false;
894 }
895
896 bool HexoticPlugin_Hypothesis::GetDefaultHexoticInvalidElements()
897 {
898   return false;
899 }
900
901 double HexoticPlugin_Hypothesis::GetDefaultHexoticSharpAngleThreshold()
902 {
903   return 60.0;
904 }
905
906 int HexoticPlugin_Hypothesis::GetDefaultHexoticNbProc()
907 {
908   return 4;
909 }
910
911 std::string HexoticPlugin_Hypothesis::GetDefaultHexoticWorkingDirectory()
912 {
913   std::string aTmpDir;
914
915   char *Tmp_dir = getenv("SALOME_TMP_DIR");
916 #ifdef WIN32
917   if(Tmp_dir == NULL) {
918     Tmp_dir = getenv("TEMP");
919     if( Tmp_dir== NULL )
920       Tmp_dir = getenv("TMP");
921   }
922 #endif
923   if( Tmp_dir != NULL ) {
924     aTmpDir = std::string(Tmp_dir);
925 #ifdef WIN32
926     if(aTmpDir[aTmpDir.size()-1] != '\\') aTmpDir+='\\';
927 #else
928     if(aTmpDir[aTmpDir.size()-1] != '/') aTmpDir+='/';
929 #endif
930   }
931   else {
932 #ifdef WIN32
933     aTmpDir = "C:\\";
934 #else
935     aTmpDir = "/tmp/";
936 #endif
937   }
938   return aTmpDir;
939 }
940
941 int HexoticPlugin_Hypothesis::GetDefaultHexoticSdMode()
942 {
943   return 4;
944 }
945
946 int HexoticPlugin_Hypothesis::GetDefaultHexoticVerbosity()
947 {
948   return 1;
949 }
950
951 int HexoticPlugin_Hypothesis::GetDefaultHexoticMaxMemory()
952 {
953   return 2048;
954 }
955
956 std::string HexoticPlugin_Hypothesis::GetDefaultTextOptions()
957 {
958   return "";
959 }
960
961 HexoticPlugin_Hypothesis::THexoticSizeMaps HexoticPlugin_Hypothesis::GetDefaultHexoticSizeMaps()
962 {
963   return THexoticSizeMaps();
964 }
965
966 int HexoticPlugin_Hypothesis::GetDefaultNbLayers()
967 {
968   return 0;
969 }
970
971 double HexoticPlugin_Hypothesis::GetDefaultFirstLayerSize()
972 {
973   return 0.0;
974 }
975
976 bool HexoticPlugin_Hypothesis::GetDefaultDirection()
977 {
978   return true;
979 }
980
981 double HexoticPlugin_Hypothesis::GetDefaultGrowth()
982 {
983   return 0.0;
984 }
985
986 std::vector<int> HexoticPlugin_Hypothesis::GetDefaultFacesWithLayers()
987 {
988   return std::vector<int>();
989 }
990
991 std::vector<int> HexoticPlugin_Hypothesis::GetDefaultImprintedFaces()
992 {
993   return std::vector<int>();
994 }