]> SALOME platform Git repositories - plugins/ghs3dplugin.git/blob - src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx
Salome HOME
#18963 Minimize compiler warnings
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / GHS3DPlugin_Hypothesis.cxx
1 // Copyright (C) 2004-2020  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      : GHS3DPlugin_Hypothesis.cxx
22 // Created   : Wed Apr  2 12:36:29 2008
23 // Author    : Edward AGAPOV (eap)
24 //=============================================================================
25 //
26 #include "GHS3DPlugin_Hypothesis.hxx"
27
28 #include <SMESHDS_Mesh.hxx>
29
30 #include <TCollection_AsciiString.hxx>
31
32 #ifdef WIN32
33 #include <process.h>
34 #define getpid _getpid
35 #endif
36
37 using namespace std;
38
39 namespace
40 {
41   struct GET_DEFAULT // struct used to get default value from GetOptionValue()
42   {
43     bool isDefault;
44     operator bool* () { return &isDefault; }
45   };
46 }
47
48 //=======================================================================
49 //function : GHS3DPlugin_Hypothesis
50 //=======================================================================
51
52 GHS3DPlugin_Hypothesis::GHS3DPlugin_Hypothesis(int hypId, SMESH_Gen * gen)
53   : SMESH_Hypothesis(hypId, gen),
54     myToMeshHoles(DefaultMeshHoles()),
55     myToMakeGroupsOfDomains(DefaultToMakeGroupsOfDomains()),
56     myMaximumMemory(-1),
57     myInitialMemory(-1),
58     myOptimizationLevel(DefaultOptimizationLevel()),
59     myKeepFiles(DefaultKeepFiles()),
60     myWorkingDirectory(DefaultWorkingDirectory()),
61     myVerboseLevel(DefaultVerboseLevel()),
62     myToCreateNewNodes(DefaultToCreateNewNodes()),
63     myToUseBoundaryRecoveryVersion(DefaultToUseBoundaryRecoveryVersion()),
64     myToUseFemCorrection(DefaultToUseFEMCorrection()),
65     myToRemoveCentralPoint(DefaultToRemoveCentralPoint()),
66     myLogInStandardOutput(DefaultStandardOutputLog()),
67     myRemoveLogOnSuccess( DefaultRemoveLogOnSuccess() ),
68     myGradation(DefaultGradation()),
69     myUseVolumeProximity(DefaultUseVolumeProximity()),
70     myNbVolumeProximityLayers(DefaultNbVolumeProximityLayers()),
71     myMinSize(0),
72     myMinSizeDefault(0),
73     myMaxSize(0),
74     myMaxSizeDefault(0)
75 {
76   _name = GetHypType();
77   _param_algo_dim = 3;
78
79   const char* boolOptionNames[] = { "no_initial_central_point",                          // no
80                                     "force_max_size",                                    // no
81                                     "apply_gradation_on_skin_vertex_sizes",              // yes
82                                     "optimise_worst_elements",                           // no
83                                     "force_output_quadratic_mesh",                       // no
84                                     "rectify_jacobian",                                  // yes
85                                     "jacobian_rectification_respect_input_surface_mesh", // yes
86                                     "" // mark of end
87   };
88   const char* intOptionNames[] = { "max_number_of_errors_printed", // 1
89                                    "max_number_of_threads",        // 4
90                                    "" // mark of end
91   };
92   const char* doubleOptionNames[] = { "target_quality",  // 0
93                                       "sliver_angle",    // 5
94                                       "" // mark of end
95   };
96   const char* charOptionNames[] = { "pthreads_mode",                    // ""
97                                     "boundary_regeneration",            // standard
98                                     "split_overconstrained_tetrahedra", // no
99                                     "" // mark of end
100   };
101
102   int i = 0;
103   while (boolOptionNames[i][0])
104   {
105     _boolOptions.insert( boolOptionNames[i] );
106     _option2value[boolOptionNames[i++]].clear();
107   }
108   i = 0;
109   while (intOptionNames[i][0])
110     _option2value[intOptionNames[i++]].clear();
111   
112   i = 0;
113   while (doubleOptionNames[i][0]) {
114     _doubleOptions.insert(doubleOptionNames[i]);
115     _option2value[doubleOptionNames[i++]].clear();
116   }
117   i = 0;
118   while (charOptionNames[i][0]) {
119     _charOptions.insert(charOptionNames[i]);
120     _option2value[charOptionNames[i++]].clear();
121   }
122
123   // default values to be used while MG meshing
124
125   _defaultOptionValues["no_initial_central_point"                         ] = "no";
126   _defaultOptionValues["force_max_size"                                   ] = "no";
127   _defaultOptionValues["apply_gradation_on_skin_vertex_sizes"             ] = "yes";
128   _defaultOptionValues["optimise_worst_elements"                          ] = "no";
129   _defaultOptionValues["force_output_quadratic_mesh"                      ] = "no";
130   _defaultOptionValues["rectify_jacobian"                                 ] = "yes";
131   _defaultOptionValues["jacobian_rectification_respect_input_surface_mesh"] = "yes";
132   _defaultOptionValues["max_number_of_errors_printed"                     ] = "1";
133   _defaultOptionValues["max_number_of_threads"                            ] = "4";
134   _defaultOptionValues["target_quality"                                   ] = "";//NoValue();
135   _defaultOptionValues["sliver_angle"                                     ] = "5";
136   _defaultOptionValues["pthreads_mode"                                    ] = "";//NoValue();
137   _defaultOptionValues["boundary_regeneration"                            ] = "standard";
138   _defaultOptionValues["split_overconstrained_tetrahedra"                 ] = "no";
139
140 #ifdef _DEBUG_
141   // check validity of option names of _defaultOptionValues
142   TOptionValues::iterator n2v = _defaultOptionValues.begin();
143   for ( ; n2v != _defaultOptionValues.end(); ++n2v )
144     ASSERT( _option2value.count( n2v->first ));
145   ASSERT( _option2value.size() == _defaultOptionValues.size() );
146 #endif
147 }
148
149 //=======================================================================
150 //function : SetToMeshHoles
151 //=======================================================================
152
153 void GHS3DPlugin_Hypothesis::SetToMeshHoles(bool toMesh)
154 {
155   if ( myToMeshHoles != toMesh ) {
156     myToMeshHoles = toMesh;
157     NotifySubMeshesHypothesisModification();
158   }
159 }
160
161 //=======================================================================
162 //function : GetToMeshHoles
163 //=======================================================================
164
165 bool GHS3DPlugin_Hypothesis::GetToMeshHoles(bool checkFreeOption) const
166 {
167   if ( checkFreeOption )
168   {
169     std::string optionName = "components";
170     TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
171     if ( op_val != _customOption2value.end())
172     {
173       if ( op_val->second.find("all"))
174         return true;
175       if ( op_val->second.find("outside_components"))
176         return false;
177     }
178   }
179   return myToMeshHoles;
180 }
181
182 //=======================================================================
183 //function : SetToMakeGroupsOfDomains
184 //=======================================================================
185
186 void GHS3DPlugin_Hypothesis::SetToMakeGroupsOfDomains(bool toMakeGroups)
187 {
188   if ( myToMakeGroupsOfDomains != toMakeGroups ) {
189     myToMakeGroupsOfDomains = toMakeGroups;
190     NotifySubMeshesHypothesisModification();
191   }
192 }
193
194 //=======================================================================
195 //function : GetToMakeGroupsOfDomains
196 //=======================================================================
197
198 bool GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains() const
199 {
200   return myToMakeGroupsOfDomains;
201 }
202
203 //=======================================================================
204 //function : GetToMakeGroupsOfDomains
205 //=======================================================================
206
207 bool GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains(const GHS3DPlugin_Hypothesis* hyp)
208 {
209   bool res;
210   if ( hyp ) res = /*hyp->GetToMeshHoles(true) &&*/ hyp->GetToMakeGroupsOfDomains();
211   else       res = /*DefaultMeshHoles()        &&*/ DefaultToMakeGroupsOfDomains();
212   return res;
213 }
214
215 //=======================================================================
216 //function : SetMaximumMemory
217 //=======================================================================
218
219 void GHS3DPlugin_Hypothesis::SetMaximumMemory(float MB)
220 {
221   if ( myMaximumMemory != MB ) {
222     myMaximumMemory = MB;
223     NotifySubMeshesHypothesisModification();
224   }
225 }
226
227 //=======================================================================
228 //function : GetMaximumMemory
229 //           * automatic memory adjustment mode. Default is zero
230 //=======================================================================
231
232 float GHS3DPlugin_Hypothesis::GetMaximumMemory() const
233 {
234   return myMaximumMemory;
235 }
236
237 //=======================================================================
238 //function : SetInitialMemory
239 //=======================================================================
240
241 void GHS3DPlugin_Hypothesis::SetInitialMemory(float MB)
242 {
243   if ( myInitialMemory != MB ) {
244     myInitialMemory = MB;
245     NotifySubMeshesHypothesisModification();
246   }
247 }
248
249 //=======================================================================
250 //function : GetInitialMemory
251 //=======================================================================
252
253 float GHS3DPlugin_Hypothesis::GetInitialMemory() const
254 {
255   return myInitialMemory;
256 }
257
258 //=======================================================================
259 //function : SetOptimizationLevel
260 //=======================================================================
261
262 void GHS3DPlugin_Hypothesis::SetOptimizationLevel(OptimizationLevel level)
263 {
264   if ( myOptimizationLevel != level ) {
265     myOptimizationLevel = level;
266     NotifySubMeshesHypothesisModification();
267   }
268 }
269
270 //=======================================================================
271 //function : GetOptimizationLevel
272 //=======================================================================
273
274 GHS3DPlugin_Hypothesis::OptimizationLevel GHS3DPlugin_Hypothesis::GetOptimizationLevel() const
275 {
276   return (OptimizationLevel) myOptimizationLevel;
277 }
278
279 //=======================================================================
280 //function : SetWorkingDirectory
281 //=======================================================================
282
283 void GHS3DPlugin_Hypothesis::SetWorkingDirectory(const std::string& path)
284 {
285   if ( myWorkingDirectory != path ) {
286     myWorkingDirectory = path;
287     NotifySubMeshesHypothesisModification();
288   }
289 }
290
291 //=======================================================================
292 //function : GetWorkingDirectory
293 //=======================================================================
294
295 std::string GHS3DPlugin_Hypothesis::GetWorkingDirectory() const
296 {
297   return myWorkingDirectory;
298 }
299
300 //=======================================================================
301 //function : SetKeepFiles
302 //=======================================================================
303
304 void GHS3DPlugin_Hypothesis::SetKeepFiles(bool toKeep)
305 {
306   if ( myKeepFiles != toKeep ) {
307     myKeepFiles = toKeep;
308     NotifySubMeshesHypothesisModification();
309   }
310 }
311
312 //=======================================================================
313 //function : GetKeepFiles
314 //=======================================================================
315
316 bool GHS3DPlugin_Hypothesis::GetKeepFiles() const
317 {
318   return myKeepFiles;
319 }
320
321 //=======================================================================
322 //function : SetVerboseLevel
323 //=======================================================================
324
325 void GHS3DPlugin_Hypothesis::SetVerboseLevel(short level)
326 {
327   if ( myVerboseLevel != level ) {
328     myVerboseLevel = level;
329     NotifySubMeshesHypothesisModification();
330   }
331 }
332
333 //=======================================================================
334 //function : GetVerboseLevel
335 //=======================================================================
336
337 short GHS3DPlugin_Hypothesis::GetVerboseLevel() const
338 {
339   return myVerboseLevel;
340 }
341
342 //=======================================================================
343 //function : SetToCreateNewNodes
344 //=======================================================================
345
346 void GHS3DPlugin_Hypothesis::SetToCreateNewNodes(bool toCreate)
347 {
348   if ( myToCreateNewNodes != toCreate ) {
349     myToCreateNewNodes = toCreate;
350     NotifySubMeshesHypothesisModification();
351   }
352 }
353
354 //=======================================================================
355 //function : GetToCreateNewNodes
356 //=======================================================================
357
358 bool GHS3DPlugin_Hypothesis::GetToCreateNewNodes() const
359 {
360   return myToCreateNewNodes;
361 }
362
363 //=======================================================================
364 //function : SetToUseBoundaryRecoveryVersion
365 //=======================================================================
366
367 void GHS3DPlugin_Hypothesis::SetToUseBoundaryRecoveryVersion(bool toUse)
368 {
369   if ( myToUseBoundaryRecoveryVersion != toUse ) {
370     myToUseBoundaryRecoveryVersion = toUse;
371     NotifySubMeshesHypothesisModification();
372   }
373 }
374
375 //=======================================================================
376 //function : GetToUseBoundaryRecoveryVersion
377 //=======================================================================
378
379 bool GHS3DPlugin_Hypothesis::GetToUseBoundaryRecoveryVersion() const
380 {
381   return myToUseBoundaryRecoveryVersion;
382 }
383
384 //=======================================================================
385 //function : SetFEMCorrection
386 //=======================================================================
387
388 void GHS3DPlugin_Hypothesis::SetFEMCorrection(bool toUseFem)
389 {
390   if ( myToUseFemCorrection != toUseFem ) {
391     myToUseFemCorrection = toUseFem;
392     NotifySubMeshesHypothesisModification();
393   }
394 }
395
396 //=======================================================================
397 //function : GetFEMCorrection
398 //=======================================================================
399
400 bool GHS3DPlugin_Hypothesis::GetFEMCorrection() const
401 {
402   return myToUseFemCorrection;
403 }
404
405 //=======================================================================
406 //function : SetToRemoveCentralPoint
407 //=======================================================================
408
409 void GHS3DPlugin_Hypothesis::SetToRemoveCentralPoint(bool toRemove)
410 {
411   SetOptionValue( "no_initial_central_point", toRemove ? "yes" : "no" );
412   myToRemoveCentralPoint = toRemove;
413 }
414
415 //=======================================================================
416 //function : GetToRemoveCentralPoint
417 //=======================================================================
418
419 bool GHS3DPlugin_Hypothesis::GetToRemoveCentralPoint() const
420 {
421   return myToRemoveCentralPoint;
422 }
423
424 //=======================================================================
425 //function : SetAdvancedOption
426 //=======================================================================
427
428 void GHS3DPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
429 {
430   size_t wsPos = option.find(' ');
431   if ( wsPos == string::npos )
432   {
433     SetOptionValue( option, "" );
434   }
435   else
436   {
437     std::string opt( option, 0, wsPos );
438     std::string val( option, wsPos + 1 );
439     SetOptionValue( opt, val );
440   }
441 }
442
443 //=======================================================================
444 //function : GetAdvancedOption
445 //=======================================================================
446
447 std::string GHS3DPlugin_Hypothesis::GetAdvancedOption() const
448 {
449   SMESH_Comment txt;
450
451   TOptionValues::const_iterator o2v = _option2value.begin();
452   for ( ; o2v != _option2value.end(); ++o2v )
453     if ( !o2v->second.empty() )
454     {
455       if ( !txt.empty() )
456         txt << " ";
457       txt << o2v->first << " " << o2v->second;
458     }
459   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
460   {
461     if ( !txt.empty() )
462       txt << " ";
463     txt << o2v->first << " " << o2v->second;
464   }
465   return txt;
466 }
467
468 //=======================================================================
469 //function : SetGradation
470 //=======================================================================
471
472 void GHS3DPlugin_Hypothesis::SetGradation(double gradation)
473 {
474   if ( myGradation != gradation ) {
475     myGradation = gradation;
476     NotifySubMeshesHypothesisModification();
477   }
478 }
479
480 //=======================================================================
481 //function : GetGradation
482 //=======================================================================
483
484 double GHS3DPlugin_Hypothesis::GetGradation() const
485 {
486   return myGradation;
487 }
488
489 //=============================================================================
490 void GHS3DPlugin_Hypothesis::SetMinSize(double theMinSize)
491 {
492   if ( theMinSize != myMinSize )
493   {
494     myMinSize = theMinSize;
495     NotifySubMeshesHypothesisModification();
496   }
497 }
498
499 //=============================================================================
500 void GHS3DPlugin_Hypothesis::SetMaxSize(double theMaxSize)
501 {
502   if ( theMaxSize != myMaxSize )
503   {
504     myMaxSize = theMaxSize;
505     NotifySubMeshesHypothesisModification();
506   }
507 }
508
509 //=============================================================================
510 void GHS3DPlugin_Hypothesis::SetUseVolumeProximity( bool toUse )
511 {
512   if ( myUseVolumeProximity != toUse )
513   {
514     myUseVolumeProximity = toUse;
515     NotifySubMeshesHypothesisModification();
516   }
517 }
518
519 //=============================================================================
520 void GHS3DPlugin_Hypothesis::SetNbVolumeProximityLayers( int nbLayers )
521 {
522   if ( myNbVolumeProximityLayers != nbLayers )
523   {
524     myNbVolumeProximityLayers = nbLayers;
525     NotifySubMeshesHypothesisModification();
526   }
527 }
528
529 //=======================================================================
530 //function : SetStandardOutputLog
531 //=======================================================================
532
533 void GHS3DPlugin_Hypothesis::SetStandardOutputLog(bool logInStandardOutput)
534 {
535   if ( myLogInStandardOutput != logInStandardOutput ) {
536     myLogInStandardOutput = logInStandardOutput;
537     NotifySubMeshesHypothesisModification();
538   }
539 }
540
541 //=======================================================================
542 //function : GetStandardOutputLog
543 //=======================================================================
544
545 bool GHS3DPlugin_Hypothesis::GetStandardOutputLog() const
546 {
547   return myLogInStandardOutput;
548 }
549
550 //=======================================================================
551 //function : SetRemoveLogOnSuccess
552 //=======================================================================
553
554 void GHS3DPlugin_Hypothesis::SetRemoveLogOnSuccess(bool removeLogOnSuccess)
555 {
556   if ( myRemoveLogOnSuccess != removeLogOnSuccess ) {
557     myRemoveLogOnSuccess = removeLogOnSuccess;
558     NotifySubMeshesHypothesisModification();
559   }
560 }
561
562 //=======================================================================
563 //function : GetRemoveLogOnSuccess
564 //=======================================================================
565
566 bool GHS3DPlugin_Hypothesis::GetRemoveLogOnSuccess() const
567 {
568   return myRemoveLogOnSuccess;
569 }
570
571 //=======================================================================
572 //function : SetEnforcedVertex
573 //=======================================================================
574
575 bool GHS3DPlugin_Hypothesis::SetEnforcedVertex(std::string theName,
576                                                std::string theEntry,
577                                                std::string theGroupName,
578                                                double      size,
579                                                double x, double y, double z,
580                                                bool        isCompound)
581 {
582   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedVertex(\""<< theName << "\", \""<< theEntry << "\", \"" << theGroupName << "\", "
583                                                       << size << ", " << x << ", " << y << ", " << z  << ", "<< isCompound << ")");
584
585   bool toNotify = false;
586   bool toCreate = true;
587
588   TGHS3DEnforcedVertex *oldEnVertex;
589   TGHS3DEnforcedVertex *newEnfVertex = new TGHS3DEnforcedVertex();
590   newEnfVertex->name = theName;
591   newEnfVertex->geomEntry = theEntry;
592   newEnfVertex->coords.clear();
593   if (!isCompound) {
594     newEnfVertex->coords.push_back(x);
595     newEnfVertex->coords.push_back(y);
596     newEnfVertex->coords.push_back(z);
597   }
598   newEnfVertex->groupName = theGroupName;
599   newEnfVertex->size = size;
600   newEnfVertex->isCompound = isCompound;
601   
602   
603   // update _enfVertexList
604   TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(newEnfVertex);
605   if (it != _enfVertexList.end()) {
606     toCreate = false;
607     oldEnVertex = (*it);
608     MESSAGE("Enforced Vertex was found => Update");
609     if (oldEnVertex->name != theName) {
610       MESSAGE("Update name from \"" << oldEnVertex->name << "\" to \"" << theName << "\"");
611       oldEnVertex->name = theName;
612       toNotify = true;
613     }
614     if (oldEnVertex->groupName != theGroupName) {
615       MESSAGE("Update group name from \"" << oldEnVertex->groupName << "\" to \"" << theGroupName << "\"");
616       oldEnVertex->groupName = theGroupName;
617       toNotify = true;
618     }
619     if (oldEnVertex->size != size) {
620       MESSAGE("Update size from \"" << oldEnVertex->size << "\" to \"" << size << "\"");
621       oldEnVertex->size = size;
622       toNotify = true;
623     }
624     if (toNotify) {
625       // update map coords / enf vertex if needed
626       if (oldEnVertex->coords.size()) {
627         _coordsEnfVertexMap[oldEnVertex->coords] = oldEnVertex;
628         _enfVertexCoordsSizeList[oldEnVertex->coords] = size;
629       }
630
631       // update map geom entry / enf vertex if needed
632       if (oldEnVertex->geomEntry != "") {
633         _geomEntryEnfVertexMap[oldEnVertex->geomEntry] = oldEnVertex;
634         _enfVertexEntrySizeList[oldEnVertex->geomEntry] = size;
635       }
636     }
637   }
638
639 //   //////// CREATE ////////////
640   if (toCreate) {
641     toNotify = true;
642     MESSAGE("Creating new enforced vertex");
643     _enfVertexList.insert(newEnfVertex);
644     if (theEntry == "") {
645       _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
646       _enfVertexCoordsSizeList[newEnfVertex->coords] = size;
647     }
648     else {
649       _geomEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
650       _enfVertexEntrySizeList[newEnfVertex->geomEntry] = size;
651     }
652   }
653
654   if (toNotify)
655     NotifySubMeshesHypothesisModification();
656
657   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedVertex END");
658   return toNotify;
659 }
660
661
662 //=======================================================================
663 //function : SetEnforcedMesh
664 //=======================================================================
665 bool GHS3DPlugin_Hypothesis::SetEnforcedMesh(SMESH_Mesh& theMesh, SMESH::ElementType elementType, std::string name, std::string entry, std::string groupName)
666 {
667   TIDSortedElemSet theElemSet;
668   SMDS_ElemIteratorPtr eIt = theMesh.GetMeshDS()->elementsIterator(SMDSAbs_ElementType(elementType));
669   while ( eIt->more() )
670     theElemSet.insert( eIt->next() );
671   MESSAGE("Add "<<theElemSet.size()<<" types["<<elementType<<"] from source mesh");
672   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
673   if (added) {
674     TGHS3DEnforcedMesh* newEnfMesh = new TGHS3DEnforcedMesh();
675     newEnfMesh->persistID   = theMesh.GetMeshDS()->GetPersistentId();
676     newEnfMesh->name        = name;
677     newEnfMesh->entry       = entry;
678     newEnfMesh->elementType = elementType;
679     newEnfMesh->groupName   = groupName;
680     
681     TGHS3DEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
682     if (it == _enfMeshList.end()) {
683       _entryEnfMeshMap[entry].insert(newEnfMesh);
684       _enfMeshList.insert(newEnfMesh);
685     }
686     else {
687       delete newEnfMesh;
688     }
689   }
690   return added;
691 }
692
693 //=======================================================================
694 //function : SetEnforcedGroup
695 //=======================================================================
696 bool GHS3DPlugin_Hypothesis::SetEnforcedGroup(const SMESHDS_Mesh* theMeshDS, SMESH::long_array_var theIDs, SMESH::ElementType elementType, std::string name, std::string entry, std::string groupName)
697 {
698   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedGroup");
699   TIDSortedElemSet theElemSet;
700     if ( theIDs->length() == 0 ){MESSAGE("The source group is empty");}
701     for ( CORBA::ULong i=0; i < theIDs->length(); i++) {
702       CORBA::Long ind = theIDs[i];
703       if (elementType == SMESH::NODE)
704       {
705         const SMDS_MeshNode * node = theMeshDS->FindNode(ind);
706         if (node)
707           theElemSet.insert( node );
708       }
709       else
710       {
711         const SMDS_MeshElement * elem = theMeshDS->FindElement(ind);
712         if (elem)
713           theElemSet.insert( elem );
714       }
715     }
716
717 //   SMDS_ElemIteratorPtr it = theGroup->GetGroupDS()->GetElements();
718 //   while ( it->more() ) 
719 //     theElemSet.insert( it->next() );
720
721   MESSAGE("Add "<<theElemSet.size()<<" types["<<elementType<<"] from source group ");
722   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
723   if (added) {
724     TGHS3DEnforcedMesh* newEnfMesh = new TGHS3DEnforcedMesh();
725     newEnfMesh->name = name;
726     newEnfMesh->entry = entry;
727     newEnfMesh->elementType = elementType;
728     newEnfMesh->groupName = groupName;
729     
730     TGHS3DEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
731     if (it == _enfMeshList.end()) {
732       _entryEnfMeshMap[entry].insert(newEnfMesh);
733       _enfMeshList.insert(newEnfMesh);
734     }
735   }
736   return added;
737 }
738
739 //=======================================================================
740 //function : SetEnforcedElements
741 //=======================================================================
742 bool GHS3DPlugin_Hypothesis::SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, std::string groupName)
743 {
744   MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedElements");
745   TIDSortedElemSet::const_iterator it = theElemSet.begin();
746   const SMDS_MeshElement* elem;
747   const SMDS_MeshNode* node;
748   bool added = true;
749   pair<TIDSortedNodeGroupMap::iterator,bool> nodeRet;
750   pair<TIDSortedElemGroupMap::iterator,bool> elemRet;
751
752   for (;it != theElemSet.end();++it)
753   {
754     elem = (*it);
755     switch (elementType) {
756       case SMESH::NODE:
757         node = dynamic_cast<const SMDS_MeshNode*>(elem);
758         if (node) {
759           nodeRet = _enfNodes.insert(make_pair(node,groupName));
760           added = added && nodeRet.second;
761           string msg = added ? "yes":"no";
762           MESSAGE( "Node (" <<node->X()<<","<<node->Y()<<","<<node->Z()<< ") with ID " << node->GetID() <<" added ? " << msg);
763         }
764         else {
765           SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
766           for (;nodeIt->more();) {
767             node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
768             nodeRet = _enfNodes.insert(make_pair(node,groupName));
769             added = added && nodeRet.second;
770           }
771         }
772         break;
773       case SMESH::EDGE:
774         if (elem->GetType() == SMDSAbs_Edge) {
775           elemRet = _enfEdges.insert(make_pair(elem,groupName));
776           added = added && elemRet.second;
777         }
778         else if (elem->GetType() > SMDSAbs_Edge) {
779           // SMDS_ElemIteratorPtr it = elem->edgesIterator();
780           // for (;it->more();) {
781           //   const SMDS_MeshElement* anEdge = it->next();
782           //   elemRet = _enfEdges.insert(make_pair(anEdge,groupName));
783           //   added = added && elemRet.second;
784           // }
785         }
786         break;
787       case SMESH::FACE:
788         if (elem->GetType() == SMDSAbs_Face)
789         {
790           if (elem->NbCornerNodes() == 3) {
791             elemRet = _enfTriangles.insert(make_pair(elem,groupName));
792             added = added && elemRet.second;
793           }
794         }
795         else if (elem->GetType() > SMDSAbs_Face) { // Group of faces
796           // SMDS_ElemIteratorPtr it = elem->facesIterator();
797           // for (;it->more();) {
798           //   const SMDS_MeshElement* aFace = it->next();
799           //   if (aFace->NbCornerNodes() == 3) {
800           //     elemRet = _enfTriangles.insert(make_pair(aFace,groupName));
801           //     added = added && elemRet.second;
802           //   }
803           // }
804         }
805         break;
806       default:
807         break;
808     };
809   }
810   if (added)
811     NotifySubMeshesHypothesisModification();
812   return added;
813 }
814
815
816 //=======================================================================
817 //function : GetEnforcedVertex
818 //=======================================================================
819
820 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(double x, double y, double z)
821 {
822   std::vector<double> coord(3);
823   coord[0] = x;
824   coord[1] = y;
825   coord[2] = z;
826   if (_coordsEnfVertexMap.count(coord)>0)
827     return _coordsEnfVertexMap[coord];
828   std::ostringstream msg ;
829   msg << "No enforced vertex at " << x << ", " << y << ", " << z;
830   throw std::invalid_argument(msg.str());
831 }
832
833 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(const std::string theEntry)
834 {
835   if (_geomEntryEnfVertexMap.count(theEntry)>0)
836     return _geomEntryEnfVertexMap[theEntry];
837   
838   std::ostringstream msg ;
839   msg << "No enforced vertex with entry " << theEntry;
840   throw std::invalid_argument(msg.str());
841 }
842
843 //=======================================================================
844 //function : RemoveEnforcedVertex
845 //=======================================================================
846
847 bool GHS3DPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, const std::string theEntry)
848 {
849   bool toNotify = false;
850   std::ostringstream msg;
851   TGHS3DEnforcedVertex *oldEnfVertex;
852   std::vector<double> coords(3);
853   coords[0] = x;
854   coords[1] = y;
855   coords[2] = z;
856   
857   // check that enf vertex with given enf vertex entry exists
858   TGeomEntryGHS3DEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry);
859   if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) {
860     // Success
861     MESSAGE("Found enforced vertex with geom entry " << theEntry);
862     oldEnfVertex = it_enfVertexEntry->second;
863     _geomEntryEnfVertexMap.erase(it_enfVertexEntry);
864   } else {
865     // Fail
866     MESSAGE("Enforced vertex with geom entry " << theEntry << " not found");
867     // check that enf vertex with given coords exists
868     TCoordsGHS3DEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
869     if (it_coords_enf != _coordsEnfVertexMap.end()) {
870       // Success
871       MESSAGE("Found enforced vertex with coords " << x << ", " << y << ", " << z);
872       oldEnfVertex = it_coords_enf->second;
873       _coordsEnfVertexMap.erase(it_coords_enf);
874       _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords));
875     } else {
876       // Fail
877       MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found");
878       throw std::invalid_argument(msg.str());
879     }
880   }
881
882   MESSAGE("Remove enf vertex from _enfVertexList");
883
884   // update _enfVertexList
885   TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
886   if (it != _enfVertexList.end()) {
887     if ((*it)->groupName != "")
888       _groupsToRemove.insert((*it)->groupName);
889     _enfVertexList.erase(it);
890     toNotify = true;
891     MESSAGE("Done");
892   }
893
894   if (toNotify)
895     NotifySubMeshesHypothesisModification();
896
897   return toNotify;
898 }
899
900 //=======================================================================
901 //function : ClearEnforcedVertices
902 //=======================================================================
903 void GHS3DPlugin_Hypothesis::ClearEnforcedVertices()
904 {
905   TGHS3DEnforcedVertexList::const_iterator it = _enfVertexList.begin();
906   for(;it != _enfVertexList.end();++it) {
907     if ((*it)->groupName != "")
908       _groupsToRemove.insert((*it)->groupName);
909   }
910   _enfVertexList.clear();
911   _coordsEnfVertexMap.clear();
912   _geomEntryEnfVertexMap.clear();
913   _enfVertexCoordsSizeList.clear();
914   _enfVertexEntrySizeList.clear();
915   NotifySubMeshesHypothesisModification();
916 }
917
918 //=======================================================================
919 //function : ClearEnforcedMeshes
920 //=======================================================================
921 void GHS3DPlugin_Hypothesis::ClearEnforcedMeshes()
922 {
923   TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin();
924   for(;it != _enfMeshList.end();++it) {
925     if ((*it)->groupName != "")
926       _groupsToRemove.insert((*it)->groupName);
927   }
928   _enfNodes.clear();
929   _enfEdges.clear();
930   _enfTriangles.clear();
931   _nodeIDToSizeMap.clear();
932   _enfMeshList.clear();
933   _entryEnfMeshMap.clear();
934   NotifySubMeshesHypothesisModification();
935 }
936
937 //================================================================================
938 /*!
939  * \brief At mesh loading, restore enforced elements by just loaded enforced meshes
940  */
941 //================================================================================
942
943 void GHS3DPlugin_Hypothesis::RestoreEnfElemsByMeshes()
944 {
945   TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin();
946   for(;it != _enfMeshList.end();++it) {
947     TGHS3DEnforcedMesh* enfMesh = *it;
948     if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
949       SetEnforcedMesh( *mesh,
950                        enfMesh->elementType,
951                        enfMesh->name,
952                        enfMesh->entry,
953                        enfMesh->groupName );
954     enfMesh->persistID = -1; // not to restore again
955   }
956 }
957
958 //=======================================================================
959 //function : SetGroupsToRemove
960 //=======================================================================
961
962 void GHS3DPlugin_Hypothesis::ClearGroupsToRemove()
963 {
964   _groupsToRemove.clear();
965 }
966
967
968 //=======================================================================
969 //function : DefaultMeshHoles
970 //=======================================================================
971
972 bool GHS3DPlugin_Hypothesis::DefaultMeshHoles()
973 {
974   return false; // PAL19680
975 }
976
977 //=======================================================================
978 //function : DefaultToMakeGroupsOfDomains
979 //=======================================================================
980
981 bool GHS3DPlugin_Hypothesis::DefaultToMakeGroupsOfDomains()
982 {
983   return false; // issue 0022172
984 }
985
986 //=======================================================================
987 //function : DefaultMaximumMemory
988 //=======================================================================
989
990 #if defined(WIN32)
991 #include <windows.h>
992 #elif !defined(__APPLE__)
993 #include <sys/sysinfo.h>
994 #endif
995
996 float GHS3DPlugin_Hypothesis::DefaultMaximumMemory()
997 {
998 #if defined(WIN32)
999   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1000   MEMORYSTATUSEX statex;
1001   statex.dwLength = sizeof (statex);
1002   long err = GlobalMemoryStatusEx (&statex);
1003   if (err != 0) {
1004     double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1005     return (float)( 0.7 * totMB );
1006   }
1007 #elif !defined(__APPLE__)
1008   struct sysinfo si;
1009   long err = sysinfo( &si );
1010   if ( err == 0 ) {
1011     long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1012     return ( 0.7 * ramMB );
1013   }
1014 #endif
1015   return 1024;
1016 }
1017
1018 //=======================================================================
1019 //function : DefaultInitialMemory
1020 //=======================================================================
1021
1022 float GHS3DPlugin_Hypothesis::DefaultInitialMemory()
1023 {
1024   return DefaultMaximumMemory();
1025 }
1026
1027 //=======================================================================
1028 //function : DefaultOptimizationLevel
1029 //=======================================================================
1030
1031 short GHS3DPlugin_Hypothesis::DefaultOptimizationLevel()
1032 {
1033   return Medium;
1034 }
1035
1036 //=======================================================================
1037 //function : DefaultWorkingDirectory
1038 //=======================================================================
1039
1040 std::string GHS3DPlugin_Hypothesis::DefaultWorkingDirectory()
1041 {
1042   TCollection_AsciiString aTmpDir;
1043
1044   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1045   if(Tmp_dir != NULL) {
1046     aTmpDir = Tmp_dir;
1047   }
1048   else {
1049 #ifdef WIN32
1050     aTmpDir = TCollection_AsciiString("C:\\");
1051 #else
1052     aTmpDir = TCollection_AsciiString("/tmp/");
1053 #endif
1054   }
1055   return aTmpDir.ToCString();
1056 }
1057
1058 //=======================================================================
1059 //function : DefaultKeepFiles
1060 //=======================================================================
1061
1062 bool   GHS3DPlugin_Hypothesis::DefaultKeepFiles()
1063 {
1064   return false;
1065 }
1066
1067 //=======================================================================
1068 //function : DefaultRemoveLogOnSuccess
1069 //=======================================================================
1070
1071 bool   GHS3DPlugin_Hypothesis::DefaultRemoveLogOnSuccess()
1072 {
1073   return false;
1074 }
1075
1076
1077 //=======================================================================
1078 //function : DefaultVerboseLevel
1079 //=======================================================================
1080
1081 short  GHS3DPlugin_Hypothesis::DefaultVerboseLevel()
1082 {
1083   return 10;
1084 }
1085
1086 //=======================================================================
1087 //function : DefaultToCreateNewNodes
1088 //=======================================================================
1089
1090 bool GHS3DPlugin_Hypothesis::DefaultToCreateNewNodes()
1091 {
1092   return true;
1093 }
1094
1095 //=======================================================================
1096 //function : DefaultToUseBoundaryRecoveryVersion
1097 //=======================================================================
1098
1099 bool GHS3DPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion()
1100 {
1101   return false;
1102 }
1103
1104 //=======================================================================
1105 //function : DefaultToUseFEMCorrection
1106 //=======================================================================
1107
1108 bool GHS3DPlugin_Hypothesis::DefaultToUseFEMCorrection()
1109 {
1110   return false;
1111 }
1112
1113 //=======================================================================
1114 //function : DefaultToRemoveCentralPoint
1115 //=======================================================================
1116
1117 bool GHS3DPlugin_Hypothesis::DefaultToRemoveCentralPoint()
1118 {
1119   return false;
1120 }
1121
1122 //=======================================================================
1123 //function : DefaultStandardOutputLog
1124 //=======================================================================
1125
1126 bool GHS3DPlugin_Hypothesis::DefaultStandardOutputLog()
1127 {
1128   return false;
1129 }
1130
1131 // //=======================================================================
1132 // //function : DefaultID2SizeMap
1133 // //=======================================================================
1134 // 
1135 // GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::DefaultID2SizeMap()
1136 // {
1137 //   return GHS3DPlugin_Hypothesis::TID2SizeMap();
1138 // }
1139
1140
1141 //=======================================================================
1142 //function : SaveTo
1143 //=======================================================================
1144
1145 std::ostream & GHS3DPlugin_Hypothesis::SaveTo(std::ostream & save)
1146 {
1147   save << (int) myToMeshHoles                 << " ";
1148   save << myMaximumMemory                     << " ";
1149   save << myInitialMemory                     << " ";
1150   save << myOptimizationLevel                 << " ";
1151   save << myWorkingDirectory                  << " ";
1152   save << (int)myKeepFiles                    << " ";
1153   save << myVerboseLevel                      << " ";
1154   save << (int)myToCreateNewNodes             << " ";
1155   save << (int)myToUseBoundaryRecoveryVersion << " ";
1156   save << (int)myToUseFemCorrection           << " ";
1157   save << (int)myToRemoveCentralPoint         << " ";
1158   save << myGradation                         << " ";
1159   save << myToMakeGroupsOfDomains             << " ";
1160   // if (!myTextOption.empty()) {
1161   //   save << "__OPTIONS_BEGIN__ ";
1162   //   save << myTextOption                      << " ";
1163   //   save << "__OPTIONS_END__ ";
1164   // }
1165   
1166
1167   TGHS3DEnforcedVertexList::iterator it  = _enfVertexList.begin();
1168   if (it != _enfVertexList.end()) {
1169     save << " " << "__ENFORCED_VERTICES_BEGIN__ ";
1170     for ( ; it != _enfVertexList.end(); ++it ) {
1171       TGHS3DEnforcedVertex *enfVertex = (*it);
1172       save << " " << "__BEGIN_VERTEX__";
1173       if (!enfVertex->name.empty()) {
1174         save << " " << "__BEGIN_NAME__";
1175         save << " " << enfVertex->name;
1176         save << " " << "__END_NAME__";
1177       }
1178       if (!enfVertex->geomEntry.empty()) {
1179         save << " " << "__BEGIN_ENTRY__";
1180         save << " " << enfVertex->geomEntry;
1181         save << " " << enfVertex->isCompound;
1182         save << " " << "__END_ENTRY__";
1183       }
1184       if (!enfVertex->groupName.empty()) {
1185         save << " " << "__BEGIN_GROUP__";
1186         save << " " << enfVertex->groupName;
1187         save << " " << "__END_GROUP__";
1188       }
1189       if (enfVertex->coords.size()) {
1190         save << " " << "__BEGIN_COORDS__";
1191         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
1192           save << " " << enfVertex->coords[i];
1193         save << " " << "__END_COORDS__";
1194       }
1195       save << " " << "__BEGIN_SIZE__";
1196       save << " " << enfVertex->size;
1197       save << " " << "__END_SIZE__";
1198       save << " " << "__END_VERTEX__";
1199     }
1200     save << " " << "__ENFORCED_VERTICES_END__ ";
1201   }
1202
1203   TGHS3DEnforcedMeshList::iterator it_mesh  = _enfMeshList.begin();
1204   if (it_mesh != _enfMeshList.end()) {
1205     save << " " << "__ENFORCED_MESHES_BEGIN__ ";
1206     for ( ; it_mesh != _enfMeshList.end(); ++it_mesh ) {
1207       TGHS3DEnforcedMesh *enfMesh = (*it_mesh);
1208       save << " " << "__BEGIN_ENF_MESH__";
1209
1210       save << " " << "__BEGIN_NAME__";
1211       save << " " << enfMesh->name;
1212       save << " " << "__END_NAME__";
1213
1214       save << " " << "__BEGIN_ENTRY__";
1215       save << " " << enfMesh->entry;
1216       save << " " << "__END_ENTRY__";
1217
1218       save << " " << "__BEGIN_ELEM_TYPE__";
1219       save << " " << (int)enfMesh->elementType;
1220       save << " " << "__END_ELEM_TYPE__";
1221
1222       if (!enfMesh->groupName.empty()) {
1223         save << " " << "__BEGIN_GROUP__";
1224         save << " " << enfMesh->groupName;
1225         save << " " << "__END_GROUP__";
1226       }
1227       save << " " << "__PERSIST_ID__";
1228       save << " " << enfMesh->persistID;
1229       save << " " << "__END_ENF_MESH__";
1230       std::cout << "Saving of enforced mesh " << enfMesh->name.c_str() << " done" << std::endl;
1231     }
1232     save << " "  << "__ENFORCED_MESHES_END__ ";
1233   }
1234
1235   // New options in 2.9.6 (issue #17784)
1236
1237   save << " " << myUseVolumeProximity;
1238   save << " " << myNbVolumeProximityLayers;
1239   save << " " << myMinSize;
1240   save << " " << myMaxSize;
1241   save << " " << myMinSizeDefault;
1242   save << " " << myMaxSizeDefault;
1243
1244   save << " " << _option2value.size();
1245   TOptionValues::iterator o2v = _option2value.begin();
1246   for ( ; o2v != _option2value.end(); ++o2v )
1247     save << " -" << o2v->first << " -" << o2v->second;
1248   
1249   save << " " << _customOption2value.size();
1250   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
1251     save << " -" << o2v->first << " -" << o2v->second;
1252
1253   return save;
1254 }
1255
1256 //=======================================================================
1257 //function : LoadFrom
1258 //=======================================================================
1259
1260 std::istream & GHS3DPlugin_Hypothesis::LoadFrom(std::istream & load)
1261 {
1262   bool isOK = true;
1263   int i;
1264   double d;
1265
1266   isOK = static_cast<bool>(load >> i);
1267   if (isOK)
1268     myToMeshHoles = i;
1269   else
1270     load.clear(ios::badbit | load.rdstate());
1271
1272   isOK = static_cast<bool>(load >> d);
1273   if (isOK)
1274     myMaximumMemory = d;
1275   else
1276     load.clear(ios::badbit | load.rdstate());
1277
1278   isOK = static_cast<bool>(load >> d);
1279   if (isOK)
1280     myInitialMemory = d;
1281   else
1282     load.clear(ios::badbit | load.rdstate());
1283
1284   isOK = static_cast<bool>(load >> i);
1285   if (isOK)
1286     myOptimizationLevel = i;
1287   else
1288     load.clear(ios::badbit | load.rdstate());
1289
1290   isOK = static_cast<bool>(load >> myWorkingDirectory);
1291   if (isOK) {
1292     if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty
1293       myKeepFiles = false;
1294       myWorkingDirectory.clear();
1295     }
1296     else if ( myWorkingDirectory == "1" ) {
1297       myKeepFiles = true;
1298       myWorkingDirectory.clear();
1299     }
1300   }
1301   else
1302     load.clear(ios::badbit | load.rdstate());
1303
1304   if ( !myWorkingDirectory.empty() ) {
1305     isOK = static_cast<bool>(load >> i);
1306     if (isOK)
1307       myKeepFiles = i;
1308     else
1309       load.clear(ios::badbit | load.rdstate());
1310   }
1311
1312   isOK = static_cast<bool>(load >> i);
1313   if (isOK)
1314     myVerboseLevel = (short) i;
1315   else
1316     load.clear(ios::badbit | load.rdstate());
1317
1318   isOK = static_cast<bool>(load >> i);
1319   if (isOK)
1320     myToCreateNewNodes = (bool) i;
1321   else
1322     load.clear(ios::badbit | load.rdstate());
1323
1324   isOK = static_cast<bool>(load >> i);
1325   if (isOK)
1326     myToUseBoundaryRecoveryVersion = (bool) i;
1327   else
1328     load.clear(ios::badbit | load.rdstate());
1329
1330   isOK = static_cast<bool>(load >> i);
1331   if (isOK)
1332     myToUseFemCorrection = (bool) i;
1333   else
1334     load.clear(ios::badbit | load.rdstate());
1335
1336   isOK = static_cast<bool>(load >> i);
1337   if (isOK)
1338     myToRemoveCentralPoint = (bool) i;
1339   else
1340     load.clear(ios::badbit | load.rdstate());
1341
1342   isOK = static_cast<bool>(load >> d);
1343   if (isOK)
1344     myGradation = d;
1345   else
1346     load.clear(ios::badbit | load.rdstate());
1347
1348   std::string separator;
1349   bool hasOptions = false;
1350   bool hasEnforcedVertices = false;
1351   bool hasEnforcedMeshes = false;
1352   isOK = static_cast<bool>(load >> separator);
1353
1354   if ( isOK && ( separator == "0" || separator == "1" ))
1355   {
1356     myToMakeGroupsOfDomains = ( separator == "1" );
1357     isOK = static_cast<bool>(load >> separator);
1358   }
1359
1360   if (isOK) {
1361     if (separator == "__OPTIONS_BEGIN__")
1362       hasOptions = true;
1363     else if (separator == "__ENFORCED_VERTICES_BEGIN__")
1364       hasEnforcedVertices = true;
1365     else if (separator == "__ENFORCED_MESHES_BEGIN__")
1366       hasEnforcedMeshes = true;
1367   }
1368
1369   if (hasOptions) {
1370     std::string txt;
1371     while (isOK) {
1372       isOK = static_cast<bool>(load >> txt);
1373       if (isOK) {
1374         if (txt == "__OPTIONS_END__") {
1375           // if (!myTextOption.empty()) {
1376           //   // Remove last space
1377           //   myTextOption.erase(myTextOption.end()-1);
1378           // }
1379           isOK = false;
1380           break;
1381         }
1382         // myTextOption += txt;
1383         // myTextOption += " ";
1384       }
1385     }
1386   }
1387
1388   if (hasOptions) {
1389     isOK = static_cast<bool>(load >> separator);
1390     if (isOK && separator == "__ENFORCED_VERTICES_BEGIN__")
1391       hasEnforcedVertices = true;
1392     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1393       hasEnforcedMeshes = true;
1394   }
1395
1396   if (hasEnforcedVertices) {
1397     std::string txt, name, entry, groupName;
1398     double size, coords[3];
1399     bool isCompound;
1400     bool hasCoords = false;
1401     isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1402     while (isOK) {
1403       if (txt == "__ENFORCED_VERTICES_END__") {
1404         //isOK = false;
1405         break;
1406       }
1407       
1408       TGHS3DEnforcedVertex *enfVertex = new TGHS3DEnforcedVertex();
1409       while (isOK) {
1410         isOK = static_cast<bool>(load >> txt);
1411         if (txt == "__END_VERTEX__") {
1412           enfVertex->name = name;
1413           enfVertex->geomEntry = entry;
1414           enfVertex->isCompound = isCompound;
1415           enfVertex->groupName = groupName;
1416           enfVertex->coords.clear();
1417           if (hasCoords)
1418             enfVertex->coords.assign(coords,coords+3);
1419
1420           _enfVertexList.insert(enfVertex);
1421
1422           if (enfVertex->coords.size())
1423             _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
1424           if (!enfVertex->geomEntry.empty())
1425             _geomEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
1426
1427           name.clear();
1428           entry.clear();
1429           groupName.clear();
1430           hasCoords = false;
1431           isOK = false;
1432         }
1433
1434         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1435           while (isOK && (txt != "__END_NAME__")) {
1436             isOK = static_cast<bool>(load >> txt);
1437             if (txt != "__END_NAME__") {
1438               if (!name.empty())
1439                 name += " ";
1440               name += txt;
1441             }
1442           }
1443           MESSAGE("name: " <<name);
1444         }
1445
1446         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1447           isOK = static_cast<bool>(load >> entry);
1448           isOK = static_cast<bool>(load >> isCompound);
1449           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1450           if (txt != "__END_ENTRY__")
1451             throw std::exception();
1452           MESSAGE("entry: " << entry);
1453         }
1454
1455         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1456           while (isOK && (txt != "__END_GROUP__")) {
1457             isOK = static_cast<bool>(load >> txt);
1458             if (txt != "__END_GROUP__") {
1459               if (!groupName.empty())
1460                 groupName += " ";
1461               groupName += txt;
1462             }
1463           }
1464           MESSAGE("groupName: " << groupName);
1465         }
1466
1467         if (txt == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
1468           hasCoords = true;
1469           isOK = static_cast<bool>(load >> coords[0] >> coords[1] >> coords[2]);
1470           isOK = static_cast<bool>(load >> txt); // __END_COORDS__
1471           if (txt != "__END_COORDS__")
1472             throw std::exception();
1473           MESSAGE("coords: " << coords[0] <<","<< coords[1] <<","<< coords[2]);
1474         }
1475
1476         if (txt == "__BEGIN_SIZE__") {  // __BEGIN_ENTRY__
1477           isOK = static_cast<bool>(load >> size);
1478           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1479           if (txt != "__END_SIZE__") {
1480             throw std::exception();
1481           }
1482           MESSAGE("size: " << size);
1483         }
1484       }
1485       isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1486     }
1487   }
1488
1489   if (hasEnforcedVertices) {
1490     isOK = static_cast<bool>(load >> separator);
1491     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1492       hasEnforcedMeshes = true;
1493   }
1494
1495   if (hasEnforcedMeshes) {
1496     std::string txt, name, entry, groupName;
1497     int elementType = -1, persistID = -1;
1498     isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1499     while (isOK) {
1500       //                if (isOK) {
1501       if (txt == "__ENFORCED_MESHES_END__")
1502         isOK = false;
1503
1504       TGHS3DEnforcedMesh *enfMesh = new TGHS3DEnforcedMesh();
1505       while (isOK) {
1506         isOK = static_cast<bool>(load >> txt);
1507         if (txt == "__END_ENF_MESH__") {
1508           enfMesh->name = name;
1509           enfMesh->entry = entry;
1510           enfMesh->elementType = (SMESH::ElementType)elementType;
1511           enfMesh->groupName = groupName;
1512           enfMesh->persistID = persistID;
1513
1514           _enfMeshList.insert(enfMesh);
1515           //std::cout << "Restoring of enforced mesh " <<name  << " done" << std::endl;
1516
1517           name.clear();
1518           entry.clear();
1519           elementType = -1;
1520           groupName.clear();
1521           persistID = -1;
1522           isOK = false;
1523         }
1524
1525         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1526           while (isOK && (txt != "__END_NAME__")) {
1527             isOK = static_cast<bool>(load >> txt);
1528             if (txt != "__END_NAME__") {
1529               if (!name.empty())
1530                 name += " ";
1531               name += txt;
1532             }
1533           }
1534           MESSAGE("name: " <<name);
1535         }
1536
1537         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1538           isOK = static_cast<bool>(load >> entry);
1539           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1540           if (txt != "__END_ENTRY__")
1541             throw std::exception();
1542           MESSAGE("entry: " << entry);
1543         }
1544
1545         if (txt == "__BEGIN_ELEM_TYPE__") {  // __BEGIN_ELEM_TYPE__
1546           isOK = static_cast<bool>(load >> elementType);
1547           isOK = static_cast<bool>(load >> txt); // __END_ELEM_TYPE__
1548           if (txt != "__END_ELEM_TYPE__")
1549             throw std::exception();
1550           MESSAGE("elementType: " << elementType);
1551         }
1552
1553         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1554           while (isOK && (txt != "__END_GROUP__")) {
1555             isOK = static_cast<bool>(load >> txt);
1556             if (txt != "__END_GROUP__") {
1557               if (!groupName.empty())
1558                 groupName += " ";
1559               groupName += txt;
1560             }
1561           } // while
1562           MESSAGE("groupName: " << groupName);
1563         } // if
1564
1565         if (txt == "__PERSIST_ID__") {
1566           isOK = static_cast<bool>(load >> persistID);
1567           MESSAGE("persistID: " << persistID);
1568         }
1569         //std::cout << "isOK: " << isOK << std::endl;
1570       } // while
1571       //                } // if
1572       isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1573     } // while
1574   } // if
1575
1576   // New options in 2.9.6 (issue #17784)
1577
1578   if ( ! hasOptions && ! hasEnforcedVertices && ! hasEnforcedMeshes )
1579     myUseVolumeProximity = ( separator == "1" );
1580   else if ( static_cast<bool>( load >> i ))
1581     myUseVolumeProximity = (bool) i;
1582
1583   if ( static_cast<bool>( load >> myNbVolumeProximityLayers ))
1584   {
1585     load >> myMinSize;
1586     load >> myMaxSize;
1587     load >> myMinSizeDefault;
1588     load >> myMaxSizeDefault;
1589
1590     std::string option, value;
1591     if ( static_cast<bool>( load >> i ) && i >= 0 )
1592     {
1593       for ( int nbRead = 0; nbRead < i; ++nbRead )
1594       {
1595         load >> option >> value;
1596         _option2value[ std::string( option, 1 )] = std::string( value, 1 );
1597       }
1598     }
1599     if ( static_cast<bool>( load >> i ) && i >= 0 )
1600     {
1601       for ( int nbRead = 0; nbRead < i; ++nbRead )
1602       {
1603         load >> option >> value;
1604         _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
1605       }
1606     }
1607   }
1608
1609   return load;
1610 }
1611
1612 //=======================================================================
1613 //function : SetParametersByMesh
1614 //=======================================================================
1615
1616 bool GHS3DPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&)
1617 {
1618   return false;
1619 }
1620
1621
1622 //================================================================================
1623 /*!
1624  * \brief Sets myToMakeGroupsOfDomains depending on whether theMesh is on shape or not
1625  */
1626 //================================================================================
1627
1628 bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
1629                                                      const SMESH_Mesh* /*theMesh*/)
1630 {
1631   myToMakeGroupsOfDomains = ( !dflts._shape || dflts._shape->IsNull() );
1632
1633   double diagonal = dflts._elemLength * _gen->GetBoundaryBoxSegmentation();
1634   myMinSizeDefault = 1e-3 * diagonal;
1635   myMaxSizeDefault = diagonal / 5.;
1636
1637   return true;
1638 }
1639
1640 //================================================================================
1641 /*!
1642  * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
1643  */
1644 //================================================================================
1645
1646 std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* hyp,
1647                                                  const bool                    hasShapeToMesh,
1648                                                  const bool                    forExecutable)
1649 {
1650   std::string cmd = GetExeName();
1651   // check if any option is overridden by hyp->myTextOption
1652   bool max_memory     = hyp ? !hyp->HasOptionDefined("max_memory")               : true;
1653   bool auto_memory    = hyp ? !hyp->HasOptionDefined("automatic_memory")         : true;
1654   bool comp           = hyp ? !hyp->HasOptionDefined("components")               : true;
1655   bool optim_level    = hyp ? !hyp->HasOptionDefined("optimisation_level")       : true;
1656   bool no_int_points  = hyp ? !hyp->HasOptionDefined("no_internal_points")       : true;
1657   bool C              = hyp ? !hyp->HasOptionDefined("-C")                       : true;
1658   bool verbose        = hyp ? !hyp->HasOptionDefined("verbose")                  : true;
1659   bool gra            = hyp ? !hyp->HasOptionDefined("-Dcpropa")                 : true;
1660   bool rem            = hyp ? !hyp->HasOptionDefined("no_initial_central_point") : true;
1661   //bool fem            = hyp ? !hyp->HasOptionDefined("-FEM")                     : true;
1662
1663   // if use boundary recovery version, few options are allowed
1664   bool useBndRecovery = !C;
1665   if ( !useBndRecovery && hyp )
1666     useBndRecovery = hyp->myToUseBoundaryRecoveryVersion;
1667
1668   // MG-Tetra needs to know amount of memory it may use (MB).
1669   // Default memory is defined at MG-Tetra installation but it may be not enough,
1670   // so allow to use about all available memory
1671   if ( max_memory ) {
1672     float aMaximumMemory = hyp ? hyp->myMaximumMemory : -1;
1673     cmd += " --max_memory ";
1674     if ( aMaximumMemory < 0 ) cmd += SMESH_Comment( int( DefaultMaximumMemory() ));
1675     else                      cmd += SMESH_Comment( int( aMaximumMemory ));
1676   }
1677   if ( auto_memory && !useBndRecovery ) {
1678     float aInitialMemory = hyp ? hyp->myInitialMemory : -1;
1679     cmd += " --automatic_memory ";
1680     if ( aInitialMemory > 0 ) cmd += SMESH_Comment( int( aInitialMemory ));
1681     else                      cmd += "100";
1682   }
1683   // component to mesh
1684   if ( comp && !useBndRecovery ) {
1685     // We always run MG-Tetra with "to mesh holes'==TRUE (see PAL19680)
1686     if ( hasShapeToMesh )
1687       cmd += " --components all";
1688     else {
1689       bool aToMeshHoles = hyp ? hyp->myToMeshHoles : DefaultMeshHoles();
1690       if ( aToMeshHoles ) cmd += " --components all";
1691       else                cmd += " --components outside_components";
1692     }
1693   }
1694   const bool toCreateNewNodes = ( no_int_points && ( !hyp || hyp->myToCreateNewNodes ));
1695
1696   // optimization level
1697   if ( !toCreateNewNodes ) {
1698     cmd += " --optimisation_level none"; // issue 22608
1699   }
1700   else if ( optim_level && hyp && !useBndRecovery ) {
1701     if ( hyp->myOptimizationLevel >= 0 && hyp->myOptimizationLevel < 5 ) {
1702       const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" };
1703       cmd += " --optimisation_level ";
1704       cmd += level[ hyp->myOptimizationLevel ];
1705     }
1706   }
1707
1708   // to create internal nodes
1709   if ( no_int_points && !toCreateNewNodes ) {
1710     if ( forExecutable )
1711       cmd += " --no_internal_points";
1712     else
1713       cmd += " --internalpoints no";
1714   }
1715
1716   // verbose mode
1717   if ( verbose && hyp ) {
1718     cmd += " --verbose " + SMESH_Comment( hyp->myVerboseLevel );
1719   }
1720
1721   // boundary recovery version
1722   // if ( useBndRecovery ) {
1723   //   cmd += " -C";
1724   // }
1725
1726   // to use FEM correction
1727   // if ( fem && hyp && hyp->myToUseFemCorrection) {
1728   //   cmd += " -FEM";
1729   // }
1730
1731   // to remove initial central point.
1732   if ( rem && hyp && hyp->myToRemoveCentralPoint ) {
1733     if ( forExecutable )
1734       cmd += " --no_initial_central_point";
1735     else
1736       cmd += " --centralpoint no";
1737   }
1738
1739   // options as text
1740   // if ( hyp && !hyp->myTextOption.empty() ) {
1741   //   cmd += " " + hyp->myTextOption;
1742   // }
1743
1744   // min/max size
1745   if ( hyp )
1746   {
1747     if ( hyp->GetMinSize() > 0 )
1748       cmd += " --min_size " + SMESH_Comment( hyp->GetMinSize() );
1749     if ( hyp->GetMaxSize() > 0 )
1750       cmd += " --max_size " + SMESH_Comment( hyp->GetMaxSize() );
1751   }
1752
1753   // to define volumic gradation.
1754   if ( gra && hyp )
1755   {
1756     cmd += " --gradation " + SMESH_Comment( hyp->myGradation );
1757   }
1758
1759   if ( hyp )
1760   {
1761     // proximity
1762     if ( hyp->GetUseVolumeProximity() )
1763     {
1764       cmd += " --volume_proximity_layers " + SMESH_Comment( hyp->GetNbVolumeProximityLayers() );
1765     }
1766
1767     std::string option, value;
1768     bool isDefault;
1769     const TOptionValues* options[] = { & hyp->_option2value, & hyp->_customOption2value };
1770     for ( int iOp = 0; iOp < 2; ++iOp )
1771     {
1772       TOptionValues::const_iterator o2v = options[iOp]->begin();
1773       for ( ; o2v != options[iOp]->end(); ++o2v )
1774       {
1775         option = o2v->first;
1776         value = hyp->GetOptionValue( option, &isDefault );
1777
1778         if ( isDefault )
1779           continue;
1780         if ( value.empty() )//value == NoValue() )
1781         {
1782           if ( hyp->_defaultOptionValues.count( option ))
1783             continue; // non-custom option with no value
1784           //value.clear();
1785         }
1786         if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
1787         {
1788           if ( !value.empty() && ToBool( value ) == false )
1789             continue;
1790           value.clear();
1791         }
1792         if ( option[0] != '-' )
1793           cmd += " --";
1794         else
1795           cmd += " ";
1796         cmd += option + " " + value;
1797       }
1798     }
1799   }
1800
1801 #ifdef WIN32
1802   cmd += " < NUL";
1803 #endif
1804
1805   return cmd;
1806 }
1807
1808 //================================================================================
1809 /*!
1810  * \brief Return a unique file name
1811  */
1812 //================================================================================
1813
1814 std::string GHS3DPlugin_Hypothesis::GetFileName(const GHS3DPlugin_Hypothesis* hyp)
1815 {
1816   std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory();
1817   const char lastChar = *aTmpDir.rbegin();
1818 #ifdef WIN32
1819     if(lastChar != '\\') aTmpDir+='\\';
1820 #else
1821     if(lastChar != '/') aTmpDir+='/';
1822 #endif      
1823
1824   TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str();
1825   aGenericName += "GHS3D_";
1826   aGenericName += getpid();
1827   aGenericName += "_";
1828   aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString());
1829
1830   return aGenericName.ToCString();
1831 }
1832
1833 //================================================================================
1834 /*
1835  * Return the name of executable
1836  */
1837 //================================================================================
1838
1839 std::string GHS3DPlugin_Hypothesis::GetExeName()
1840 {
1841   return "mg-tetra.exe";
1842 }
1843
1844 //================================================================================
1845 /*!
1846 * \brief Return the enforced vertices
1847 */
1848 //================================================================================
1849
1850 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList GHS3DPlugin_Hypothesis::GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp)
1851 {
1852   return hyp ? hyp->_GetEnforcedVertices(): TGHS3DEnforcedVertexList();
1853 }
1854
1855 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const GHS3DPlugin_Hypothesis* hyp)
1856 {  
1857   return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): TGHS3DEnforcedVertexCoordsValues();
1858 }
1859
1860 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexEntryValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const GHS3DPlugin_Hypothesis* hyp)
1861 {  
1862   return hyp ? hyp->_GetEnforcedVerticesEntrySize(): TGHS3DEnforcedVertexEntryValues();
1863 }
1864
1865 GHS3DPlugin_Hypothesis::TCoordsGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByCoords (const GHS3DPlugin_Hypothesis* hyp)
1866 {  
1867   return hyp ? hyp->_GetEnforcedVerticesByCoords(): TCoordsGHS3DEnforcedVertexMap();
1868 }
1869
1870 GHS3DPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByEntry (const GHS3DPlugin_Hypothesis* hyp)
1871 {  
1872   return hyp ? hyp->_GetEnforcedVerticesByEntry(): TGeomEntryGHS3DEnforcedVertexMap();
1873 }
1874
1875 GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap GHS3DPlugin_Hypothesis::GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp)
1876 {
1877   return hyp ? hyp->_GetEnforcedNodes():TIDSortedNodeGroupMap();
1878 }
1879
1880 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp)
1881 {
1882   return hyp ? hyp->_GetEnforcedEdges():TIDSortedElemGroupMap();
1883 }
1884
1885 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp)
1886 {
1887   return hyp ? hyp->_GetEnforcedTriangles():TIDSortedElemGroupMap();
1888 }
1889
1890 GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp)
1891 {
1892   return hyp ? hyp->_GetNodeIDToSizeMap(): TID2SizeMap();
1893 }
1894
1895 GHS3DPlugin_Hypothesis::TSetStrings GHS3DPlugin_Hypothesis::GetGroupsToRemove(const GHS3DPlugin_Hypothesis* hyp)
1896 {
1897   return hyp ? hyp->_GetGroupsToRemove(): TSetStrings();
1898 }
1899
1900
1901 //=============================================================================
1902 void GHS3DPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
1903                                             const std::string& optionValue)
1904 {
1905   TOptionValues::iterator op_val = _option2value.find(optionName);
1906   if (op_val == _option2value.end())
1907   {
1908     op_val = _customOption2value.find( optionName );
1909     if ( op_val != _customOption2value.end() && op_val->second != optionValue )
1910       NotifySubMeshesHypothesisModification();
1911     _customOption2value[ optionName ] = optionValue;
1912     return;
1913   }
1914
1915   if (op_val->second != optionValue)
1916   {
1917     const char* ptr = optionValue.c_str();
1918     // strip white spaces
1919     while (ptr[0] == ' ')
1920       ptr++;
1921     int i = strlen(ptr);
1922     while (i != 0 && ptr[i - 1] == ' ')
1923       i--;
1924     // check value type
1925     bool typeOk = true;
1926     std::string typeName;
1927     if (i == 0) {
1928       // empty string
1929     } else if (_charOptions.count(optionName)) {
1930       // do not check strings
1931     } else if (_doubleOptions.count(optionName)) {
1932       // check if value is double
1933       ToDbl(ptr, &typeOk);
1934       typeName = "real";
1935     } else if (_boolOptions.count(optionName)) {
1936       // check if value is bool
1937       ToBool(ptr, &typeOk);
1938       typeName = "bool";
1939     } else {
1940       // check if value is int
1941       ToInt(ptr, &typeOk);
1942       typeName = "integer";
1943     }
1944     if ( typeOk ) // check some specific values ?
1945     {
1946     }
1947     if ( !typeOk )
1948     {
1949       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
1950       throw std::invalid_argument(msg);
1951     }
1952     std::string value( ptr, i );
1953     if ( _defaultOptionValues[ optionName ] == value )
1954       value.clear();
1955
1956     op_val->second = value;
1957
1958     NotifySubMeshesHypothesisModification();
1959   }
1960 }
1961
1962 //=============================================================================
1963 //! Return option value. If isDefault provided, it can be a default value,
1964 //  then *isDefault == true. If isDefault is not provided, the value will be
1965 //  empty if it equals a default one.
1966 std::string GHS3DPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
1967                                                    bool*              isDefault) const
1968 {
1969   TOptionValues::const_iterator op_val = _option2value.find(optionName);
1970   if (op_val == _option2value.end())
1971   {
1972     op_val = _customOption2value.find(optionName);
1973     if (op_val == _customOption2value.end())
1974     {
1975       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
1976       throw std::invalid_argument(msg);
1977     }
1978   }
1979   std::string val = op_val->second;
1980   if ( isDefault ) *isDefault = ( val.empty() );
1981
1982   if ( val.empty() && isDefault )
1983   {
1984     op_val = _defaultOptionValues.find( optionName );
1985     if (op_val != _defaultOptionValues.end())
1986       val = op_val->second;
1987   }
1988   return val;
1989 }
1990
1991
1992 //=============================================================================
1993 bool GHS3DPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
1994 {
1995   bool isDefault = false;
1996   try
1997   {
1998     GetOptionValue( optionName, &isDefault );
1999   }
2000   catch ( std::invalid_argument& )
2001   {
2002     return false;
2003   }
2004   return !isDefault;
2005 }
2006
2007 //=============================================================================
2008 void GHS3DPlugin_Hypothesis::ClearOption(const std::string& optionName)
2009 {
2010   TOptionValues::iterator op_val = _customOption2value.find(optionName);
2011   if (op_val != _customOption2value.end())
2012    _customOption2value.erase(op_val);
2013   else {
2014     op_val = _option2value.find(optionName);
2015     if (op_val != _option2value.end())
2016       op_val->second.clear();
2017   }
2018 }
2019
2020 //=============================================================================
2021 GHS3DPlugin_Hypothesis::TOptionValues GHS3DPlugin_Hypothesis::GetOptionValues() const
2022 {
2023   TOptionValues vals;
2024   TOptionValues::const_iterator op_val = _option2value.begin();
2025   for ( ; op_val != _option2value.end(); ++op_val )
2026     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
2027
2028   return vals;
2029 }
2030
2031 //================================================================================
2032 /*!
2033  * \brief Converts a string to a bool
2034  */
2035 //================================================================================
2036
2037 bool GHS3DPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
2038 {
2039   std::string s = str;
2040   if ( isOk ) *isOk = true;
2041
2042   for ( size_t i = 0; i <= s.size(); ++i )
2043     s[i] = tolower( s[i] );
2044
2045   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
2046     return true;
2047
2048   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
2049     return false;
2050
2051   if ( isOk )
2052     *isOk = false;
2053   else {
2054     std::string msg = "Not a Boolean value:'" + str + "'";
2055     throw std::invalid_argument(msg);
2056   }
2057   return false;
2058 }
2059
2060 //================================================================================
2061 /*!
2062  * \brief Converts a string to a real value
2063  */
2064 //================================================================================
2065
2066 double GHS3DPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
2067 {
2068   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2069
2070   char * endPtr;
2071   double val = strtod(&str[0], &endPtr);
2072   bool ok = (&str[0] != endPtr);
2073
2074   if ( isOk ) *isOk = ok;
2075
2076   if ( !ok )
2077   {
2078     std::string msg = "Not a real value:'" + str + "'";
2079     throw std::invalid_argument(msg);
2080   }
2081   return val;
2082 }
2083
2084 //================================================================================
2085 /*!
2086  * \brief Converts a string to a integer value
2087  */
2088 //================================================================================
2089
2090 int GHS3DPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
2091 {
2092   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2093
2094   char * endPtr;
2095   int val = (int)strtol( &str[0], &endPtr, 10);
2096   bool ok = (&str[0] != endPtr);
2097
2098   if ( isOk ) *isOk = ok;
2099
2100   if ( !ok )
2101   {
2102     std::string msg = "Not an integer value:'" + str + "'";
2103     throw std::invalid_argument(msg);
2104   }
2105   return val;
2106 }
2107