Salome HOME
2a6be1f101a68c6c669670bb93646e7271018cea
[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   throw (std::invalid_argument)
822 {
823   std::vector<double> coord(3);
824   coord[0] = x;
825   coord[1] = y;
826   coord[2] = z;
827   if (_coordsEnfVertexMap.count(coord)>0)
828     return _coordsEnfVertexMap[coord];
829   std::ostringstream msg ;
830   msg << "No enforced vertex at " << x << ", " << y << ", " << z;
831   throw std::invalid_argument(msg.str());
832 }
833
834 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* GHS3DPlugin_Hypothesis::GetEnforcedVertex(const std::string theEntry)
835   throw (std::invalid_argument)
836 {
837   if (_geomEntryEnfVertexMap.count(theEntry)>0)
838     return _geomEntryEnfVertexMap[theEntry];
839   
840   std::ostringstream msg ;
841   msg << "No enforced vertex with entry " << theEntry;
842   throw std::invalid_argument(msg.str());
843 }
844
845 //=======================================================================
846 //function : RemoveEnforcedVertex
847 //=======================================================================
848
849 bool GHS3DPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, const std::string theEntry)
850   throw (std::invalid_argument)
851 {
852   bool toNotify = false;
853   std::ostringstream msg;
854   TGHS3DEnforcedVertex *oldEnfVertex;
855   std::vector<double> coords(3);
856   coords[0] = x;
857   coords[1] = y;
858   coords[2] = z;
859   
860   // check that enf vertex with given enf vertex entry exists
861   TGeomEntryGHS3DEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry);
862   if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) {
863     // Success
864     MESSAGE("Found enforced vertex with geom entry " << theEntry);
865     oldEnfVertex = it_enfVertexEntry->second;
866     _geomEntryEnfVertexMap.erase(it_enfVertexEntry);
867   } else {
868     // Fail
869     MESSAGE("Enforced vertex with geom entry " << theEntry << " not found");
870     // check that enf vertex with given coords exists
871     TCoordsGHS3DEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
872     if (it_coords_enf != _coordsEnfVertexMap.end()) {
873       // Success
874       MESSAGE("Found enforced vertex with coords " << x << ", " << y << ", " << z);
875       oldEnfVertex = it_coords_enf->second;
876       _coordsEnfVertexMap.erase(it_coords_enf);
877       _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords));
878     } else {
879       // Fail
880       MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found");
881       throw std::invalid_argument(msg.str());
882     }
883   }
884
885   MESSAGE("Remove enf vertex from _enfVertexList");
886
887   // update _enfVertexList
888   TGHS3DEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
889   if (it != _enfVertexList.end()) {
890     if ((*it)->groupName != "")
891       _groupsToRemove.insert((*it)->groupName);
892     _enfVertexList.erase(it);
893     toNotify = true;
894     MESSAGE("Done");
895   }
896
897   if (toNotify)
898     NotifySubMeshesHypothesisModification();
899
900   return toNotify;
901 }
902
903 //=======================================================================
904 //function : ClearEnforcedVertices
905 //=======================================================================
906 void GHS3DPlugin_Hypothesis::ClearEnforcedVertices()
907 {
908   TGHS3DEnforcedVertexList::const_iterator it = _enfVertexList.begin();
909   for(;it != _enfVertexList.end();++it) {
910     if ((*it)->groupName != "")
911       _groupsToRemove.insert((*it)->groupName);
912   }
913   _enfVertexList.clear();
914   _coordsEnfVertexMap.clear();
915   _geomEntryEnfVertexMap.clear();
916   _enfVertexCoordsSizeList.clear();
917   _enfVertexEntrySizeList.clear();
918   NotifySubMeshesHypothesisModification();
919 }
920
921 //=======================================================================
922 //function : ClearEnforcedMeshes
923 //=======================================================================
924 void GHS3DPlugin_Hypothesis::ClearEnforcedMeshes()
925 {
926   TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin();
927   for(;it != _enfMeshList.end();++it) {
928     if ((*it)->groupName != "")
929       _groupsToRemove.insert((*it)->groupName);
930   }
931   _enfNodes.clear();
932   _enfEdges.clear();
933   _enfTriangles.clear();
934   _nodeIDToSizeMap.clear();
935   _enfMeshList.clear();
936   _entryEnfMeshMap.clear();
937   NotifySubMeshesHypothesisModification();
938 }
939
940 //================================================================================
941 /*!
942  * \brief At mesh loading, restore enforced elements by just loaded enforced meshes
943  */
944 //================================================================================
945
946 void GHS3DPlugin_Hypothesis::RestoreEnfElemsByMeshes()
947 {
948   TGHS3DEnforcedMeshList::const_iterator it = _enfMeshList.begin();
949   for(;it != _enfMeshList.end();++it) {
950     TGHS3DEnforcedMesh* enfMesh = *it;
951     if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
952       SetEnforcedMesh( *mesh,
953                        enfMesh->elementType,
954                        enfMesh->name,
955                        enfMesh->entry,
956                        enfMesh->groupName );
957     enfMesh->persistID = -1; // not to restore again
958   }
959 }
960
961 //=======================================================================
962 //function : SetGroupsToRemove
963 //=======================================================================
964
965 void GHS3DPlugin_Hypothesis::ClearGroupsToRemove()
966 {
967   _groupsToRemove.clear();
968 }
969
970
971 //=======================================================================
972 //function : DefaultMeshHoles
973 //=======================================================================
974
975 bool GHS3DPlugin_Hypothesis::DefaultMeshHoles()
976 {
977   return false; // PAL19680
978 }
979
980 //=======================================================================
981 //function : DefaultToMakeGroupsOfDomains
982 //=======================================================================
983
984 bool GHS3DPlugin_Hypothesis::DefaultToMakeGroupsOfDomains()
985 {
986   return false; // issue 0022172
987 }
988
989 //=======================================================================
990 //function : DefaultMaximumMemory
991 //=======================================================================
992
993 #if defined(WIN32)
994 #include <windows.h>
995 #elif !defined(__APPLE__)
996 #include <sys/sysinfo.h>
997 #endif
998
999 float GHS3DPlugin_Hypothesis::DefaultMaximumMemory()
1000 {
1001 #if defined(WIN32)
1002   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1003   MEMORYSTATUSEX statex;
1004   statex.dwLength = sizeof (statex);
1005   long err = GlobalMemoryStatusEx (&statex);
1006   if (err != 0) {
1007     double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1008     return (float)( 0.7 * totMB );
1009   }
1010 #elif !defined(__APPLE__)
1011   struct sysinfo si;
1012   long err = sysinfo( &si );
1013   if ( err == 0 ) {
1014     long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1015     return ( 0.7 * ramMB );
1016   }
1017 #endif
1018   return 1024;
1019 }
1020
1021 //=======================================================================
1022 //function : DefaultInitialMemory
1023 //=======================================================================
1024
1025 float GHS3DPlugin_Hypothesis::DefaultInitialMemory()
1026 {
1027   return DefaultMaximumMemory();
1028 }
1029
1030 //=======================================================================
1031 //function : DefaultOptimizationLevel
1032 //=======================================================================
1033
1034 short GHS3DPlugin_Hypothesis::DefaultOptimizationLevel()
1035 {
1036   return Medium;
1037 }
1038
1039 //=======================================================================
1040 //function : DefaultWorkingDirectory
1041 //=======================================================================
1042
1043 std::string GHS3DPlugin_Hypothesis::DefaultWorkingDirectory()
1044 {
1045   TCollection_AsciiString aTmpDir;
1046
1047   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1048   if(Tmp_dir != NULL) {
1049     aTmpDir = Tmp_dir;
1050   }
1051   else {
1052 #ifdef WIN32
1053     aTmpDir = TCollection_AsciiString("C:\\");
1054 #else
1055     aTmpDir = TCollection_AsciiString("/tmp/");
1056 #endif
1057   }
1058   return aTmpDir.ToCString();
1059 }
1060
1061 //=======================================================================
1062 //function : DefaultKeepFiles
1063 //=======================================================================
1064
1065 bool   GHS3DPlugin_Hypothesis::DefaultKeepFiles()
1066 {
1067   return false;
1068 }
1069
1070 //=======================================================================
1071 //function : DefaultRemoveLogOnSuccess
1072 //=======================================================================
1073
1074 bool   GHS3DPlugin_Hypothesis::DefaultRemoveLogOnSuccess()
1075 {
1076   return false;
1077 }
1078
1079
1080 //=======================================================================
1081 //function : DefaultVerboseLevel
1082 //=======================================================================
1083
1084 short  GHS3DPlugin_Hypothesis::DefaultVerboseLevel()
1085 {
1086   return 10;
1087 }
1088
1089 //=======================================================================
1090 //function : DefaultToCreateNewNodes
1091 //=======================================================================
1092
1093 bool GHS3DPlugin_Hypothesis::DefaultToCreateNewNodes()
1094 {
1095   return true;
1096 }
1097
1098 //=======================================================================
1099 //function : DefaultToUseBoundaryRecoveryVersion
1100 //=======================================================================
1101
1102 bool GHS3DPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion()
1103 {
1104   return false;
1105 }
1106
1107 //=======================================================================
1108 //function : DefaultToUseFEMCorrection
1109 //=======================================================================
1110
1111 bool GHS3DPlugin_Hypothesis::DefaultToUseFEMCorrection()
1112 {
1113   return false;
1114 }
1115
1116 //=======================================================================
1117 //function : DefaultToRemoveCentralPoint
1118 //=======================================================================
1119
1120 bool GHS3DPlugin_Hypothesis::DefaultToRemoveCentralPoint()
1121 {
1122   return false;
1123 }
1124
1125 //=======================================================================
1126 //function : DefaultStandardOutputLog
1127 //=======================================================================
1128
1129 bool GHS3DPlugin_Hypothesis::DefaultStandardOutputLog()
1130 {
1131   return false;
1132 }
1133
1134 // //=======================================================================
1135 // //function : DefaultID2SizeMap
1136 // //=======================================================================
1137 // 
1138 // GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::DefaultID2SizeMap()
1139 // {
1140 //   return GHS3DPlugin_Hypothesis::TID2SizeMap();
1141 // }
1142
1143
1144 //=======================================================================
1145 //function : SaveTo
1146 //=======================================================================
1147
1148 std::ostream & GHS3DPlugin_Hypothesis::SaveTo(std::ostream & save)
1149 {
1150   save << (int) myToMeshHoles                 << " ";
1151   save << myMaximumMemory                     << " ";
1152   save << myInitialMemory                     << " ";
1153   save << myOptimizationLevel                 << " ";
1154   save << myWorkingDirectory                  << " ";
1155   save << (int)myKeepFiles                    << " ";
1156   save << myVerboseLevel                      << " ";
1157   save << (int)myToCreateNewNodes             << " ";
1158   save << (int)myToUseBoundaryRecoveryVersion << " ";
1159   save << (int)myToUseFemCorrection           << " ";
1160   save << (int)myToRemoveCentralPoint         << " ";
1161   save << myGradation                         << " ";
1162   save << myToMakeGroupsOfDomains             << " ";
1163   // if (!myTextOption.empty()) {
1164   //   save << "__OPTIONS_BEGIN__ ";
1165   //   save << myTextOption                      << " ";
1166   //   save << "__OPTIONS_END__ ";
1167   // }
1168   
1169
1170   TGHS3DEnforcedVertexList::iterator it  = _enfVertexList.begin();
1171   if (it != _enfVertexList.end()) {
1172     save << " " << "__ENFORCED_VERTICES_BEGIN__ ";
1173     for ( ; it != _enfVertexList.end(); ++it ) {
1174       TGHS3DEnforcedVertex *enfVertex = (*it);
1175       save << " " << "__BEGIN_VERTEX__";
1176       if (!enfVertex->name.empty()) {
1177         save << " " << "__BEGIN_NAME__";
1178         save << " " << enfVertex->name;
1179         save << " " << "__END_NAME__";
1180       }
1181       if (!enfVertex->geomEntry.empty()) {
1182         save << " " << "__BEGIN_ENTRY__";
1183         save << " " << enfVertex->geomEntry;
1184         save << " " << enfVertex->isCompound;
1185         save << " " << "__END_ENTRY__";
1186       }
1187       if (!enfVertex->groupName.empty()) {
1188         save << " " << "__BEGIN_GROUP__";
1189         save << " " << enfVertex->groupName;
1190         save << " " << "__END_GROUP__";
1191       }
1192       if (enfVertex->coords.size()) {
1193         save << " " << "__BEGIN_COORDS__";
1194         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
1195           save << " " << enfVertex->coords[i];
1196         save << " " << "__END_COORDS__";
1197       }
1198       save << " " << "__BEGIN_SIZE__";
1199       save << " " << enfVertex->size;
1200       save << " " << "__END_SIZE__";
1201       save << " " << "__END_VERTEX__";
1202     }
1203     save << " " << "__ENFORCED_VERTICES_END__ ";
1204   }
1205
1206   TGHS3DEnforcedMeshList::iterator it_mesh  = _enfMeshList.begin();
1207   if (it_mesh != _enfMeshList.end()) {
1208     save << " " << "__ENFORCED_MESHES_BEGIN__ ";
1209     for ( ; it_mesh != _enfMeshList.end(); ++it_mesh ) {
1210       TGHS3DEnforcedMesh *enfMesh = (*it_mesh);
1211       save << " " << "__BEGIN_ENF_MESH__";
1212
1213       save << " " << "__BEGIN_NAME__";
1214       save << " " << enfMesh->name;
1215       save << " " << "__END_NAME__";
1216
1217       save << " " << "__BEGIN_ENTRY__";
1218       save << " " << enfMesh->entry;
1219       save << " " << "__END_ENTRY__";
1220
1221       save << " " << "__BEGIN_ELEM_TYPE__";
1222       save << " " << (int)enfMesh->elementType;
1223       save << " " << "__END_ELEM_TYPE__";
1224
1225       if (!enfMesh->groupName.empty()) {
1226         save << " " << "__BEGIN_GROUP__";
1227         save << " " << enfMesh->groupName;
1228         save << " " << "__END_GROUP__";
1229       }
1230       save << " " << "__PERSIST_ID__";
1231       save << " " << enfMesh->persistID;
1232       save << " " << "__END_ENF_MESH__";
1233       std::cout << "Saving of enforced mesh " << enfMesh->name.c_str() << " done" << std::endl;
1234     }
1235     save << " "  << "__ENFORCED_MESHES_END__ ";
1236   }
1237
1238   // New options in 2.9.6 (issue #17784)
1239
1240   save << " " << myUseVolumeProximity;
1241   save << " " << myNbVolumeProximityLayers;
1242   save << " " << myMinSize;
1243   save << " " << myMaxSize;
1244   save << " " << myMinSizeDefault;
1245   save << " " << myMaxSizeDefault;
1246
1247   save << " " << _option2value.size();
1248   TOptionValues::iterator o2v = _option2value.begin();
1249   for ( ; o2v != _option2value.end(); ++o2v )
1250     save << " -" << o2v->first << " -" << o2v->second;
1251   
1252   save << " " << _customOption2value.size();
1253   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
1254     save << " -" << o2v->first << " -" << o2v->second;
1255
1256   return save;
1257 }
1258
1259 //=======================================================================
1260 //function : LoadFrom
1261 //=======================================================================
1262
1263 std::istream & GHS3DPlugin_Hypothesis::LoadFrom(std::istream & load)
1264 {
1265   bool isOK = true;
1266   int i;
1267   double d;
1268
1269   isOK = static_cast<bool>(load >> i);
1270   if (isOK)
1271     myToMeshHoles = i;
1272   else
1273     load.clear(ios::badbit | load.rdstate());
1274
1275   isOK = static_cast<bool>(load >> d);
1276   if (isOK)
1277     myMaximumMemory = d;
1278   else
1279     load.clear(ios::badbit | load.rdstate());
1280
1281   isOK = static_cast<bool>(load >> d);
1282   if (isOK)
1283     myInitialMemory = d;
1284   else
1285     load.clear(ios::badbit | load.rdstate());
1286
1287   isOK = static_cast<bool>(load >> i);
1288   if (isOK)
1289     myOptimizationLevel = i;
1290   else
1291     load.clear(ios::badbit | load.rdstate());
1292
1293   isOK = static_cast<bool>(load >> myWorkingDirectory);
1294   if (isOK) {
1295     if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty
1296       myKeepFiles = false;
1297       myWorkingDirectory.clear();
1298     }
1299     else if ( myWorkingDirectory == "1" ) {
1300       myKeepFiles = true;
1301       myWorkingDirectory.clear();
1302     }
1303   }
1304   else
1305     load.clear(ios::badbit | load.rdstate());
1306
1307   if ( !myWorkingDirectory.empty() ) {
1308     isOK = static_cast<bool>(load >> i);
1309     if (isOK)
1310       myKeepFiles = i;
1311     else
1312       load.clear(ios::badbit | load.rdstate());
1313   }
1314
1315   isOK = static_cast<bool>(load >> i);
1316   if (isOK)
1317     myVerboseLevel = (short) i;
1318   else
1319     load.clear(ios::badbit | load.rdstate());
1320
1321   isOK = static_cast<bool>(load >> i);
1322   if (isOK)
1323     myToCreateNewNodes = (bool) i;
1324   else
1325     load.clear(ios::badbit | load.rdstate());
1326
1327   isOK = static_cast<bool>(load >> i);
1328   if (isOK)
1329     myToUseBoundaryRecoveryVersion = (bool) i;
1330   else
1331     load.clear(ios::badbit | load.rdstate());
1332
1333   isOK = static_cast<bool>(load >> i);
1334   if (isOK)
1335     myToUseFemCorrection = (bool) i;
1336   else
1337     load.clear(ios::badbit | load.rdstate());
1338
1339   isOK = static_cast<bool>(load >> i);
1340   if (isOK)
1341     myToRemoveCentralPoint = (bool) i;
1342   else
1343     load.clear(ios::badbit | load.rdstate());
1344
1345   isOK = static_cast<bool>(load >> d);
1346   if (isOK)
1347     myGradation = d;
1348   else
1349     load.clear(ios::badbit | load.rdstate());
1350
1351   std::string separator;
1352   bool hasOptions = false;
1353   bool hasEnforcedVertices = false;
1354   bool hasEnforcedMeshes = false;
1355   isOK = static_cast<bool>(load >> separator);
1356
1357   if ( isOK && ( separator == "0" || separator == "1" ))
1358   {
1359     myToMakeGroupsOfDomains = ( separator == "1" );
1360     isOK = static_cast<bool>(load >> separator);
1361   }
1362
1363   if (isOK) {
1364     if (separator == "__OPTIONS_BEGIN__")
1365       hasOptions = true;
1366     else if (separator == "__ENFORCED_VERTICES_BEGIN__")
1367       hasEnforcedVertices = true;
1368     else if (separator == "__ENFORCED_MESHES_BEGIN__")
1369       hasEnforcedMeshes = true;
1370   }
1371
1372   if (hasOptions) {
1373     std::string txt;
1374     while (isOK) {
1375       isOK = static_cast<bool>(load >> txt);
1376       if (isOK) {
1377         if (txt == "__OPTIONS_END__") {
1378           // if (!myTextOption.empty()) {
1379           //   // Remove last space
1380           //   myTextOption.erase(myTextOption.end()-1);
1381           // }
1382           isOK = false;
1383           break;
1384         }
1385         // myTextOption += txt;
1386         // myTextOption += " ";
1387       }
1388     }
1389   }
1390
1391   if (hasOptions) {
1392     isOK = static_cast<bool>(load >> separator);
1393     if (isOK && separator == "__ENFORCED_VERTICES_BEGIN__")
1394       hasEnforcedVertices = true;
1395     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1396       hasEnforcedMeshes = true;
1397   }
1398
1399   if (hasEnforcedVertices) {
1400     std::string txt, name, entry, groupName;
1401     double size, coords[3];
1402     bool isCompound;
1403     bool hasCoords = false;
1404     isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1405     while (isOK) {
1406       if (txt == "__ENFORCED_VERTICES_END__") {
1407         //isOK = false;
1408         break;
1409       }
1410       
1411       TGHS3DEnforcedVertex *enfVertex = new TGHS3DEnforcedVertex();
1412       while (isOK) {
1413         isOK = static_cast<bool>(load >> txt);
1414         if (txt == "__END_VERTEX__") {
1415           enfVertex->name = name;
1416           enfVertex->geomEntry = entry;
1417           enfVertex->isCompound = isCompound;
1418           enfVertex->groupName = groupName;
1419           enfVertex->coords.clear();
1420           if (hasCoords)
1421             enfVertex->coords.assign(coords,coords+3);
1422
1423           _enfVertexList.insert(enfVertex);
1424
1425           if (enfVertex->coords.size())
1426             _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
1427           if (!enfVertex->geomEntry.empty())
1428             _geomEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
1429
1430           name.clear();
1431           entry.clear();
1432           groupName.clear();
1433           hasCoords = false;
1434           isOK = false;
1435         }
1436
1437         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1438           while (isOK && (txt != "__END_NAME__")) {
1439             isOK = static_cast<bool>(load >> txt);
1440             if (txt != "__END_NAME__") {
1441               if (!name.empty())
1442                 name += " ";
1443               name += txt;
1444             }
1445           }
1446           MESSAGE("name: " <<name);
1447         }
1448
1449         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1450           isOK = static_cast<bool>(load >> entry);
1451           isOK = static_cast<bool>(load >> isCompound);
1452           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1453           if (txt != "__END_ENTRY__")
1454             throw std::exception();
1455           MESSAGE("entry: " << entry);
1456         }
1457
1458         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1459           while (isOK && (txt != "__END_GROUP__")) {
1460             isOK = static_cast<bool>(load >> txt);
1461             if (txt != "__END_GROUP__") {
1462               if (!groupName.empty())
1463                 groupName += " ";
1464               groupName += txt;
1465             }
1466           }
1467           MESSAGE("groupName: " << groupName);
1468         }
1469
1470         if (txt == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
1471           hasCoords = true;
1472           isOK = static_cast<bool>(load >> coords[0] >> coords[1] >> coords[2]);
1473           isOK = static_cast<bool>(load >> txt); // __END_COORDS__
1474           if (txt != "__END_COORDS__")
1475             throw std::exception();
1476           MESSAGE("coords: " << coords[0] <<","<< coords[1] <<","<< coords[2]);
1477         }
1478
1479         if (txt == "__BEGIN_SIZE__") {  // __BEGIN_ENTRY__
1480           isOK = static_cast<bool>(load >> size);
1481           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1482           if (txt != "__END_SIZE__") {
1483             throw std::exception();
1484           }
1485           MESSAGE("size: " << size);
1486         }
1487       }
1488       isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1489     }
1490   }
1491
1492   if (hasEnforcedVertices) {
1493     isOK = static_cast<bool>(load >> separator);
1494     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1495       hasEnforcedMeshes = true;
1496   }
1497
1498   if (hasEnforcedMeshes) {
1499     std::string txt, name, entry, groupName;
1500     int elementType = -1, persistID = -1;
1501     isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1502     while (isOK) {
1503       //                if (isOK) {
1504       if (txt == "__ENFORCED_MESHES_END__")
1505         isOK = false;
1506
1507       TGHS3DEnforcedMesh *enfMesh = new TGHS3DEnforcedMesh();
1508       while (isOK) {
1509         isOK = static_cast<bool>(load >> txt);
1510         if (txt == "__END_ENF_MESH__") {
1511           enfMesh->name = name;
1512           enfMesh->entry = entry;
1513           enfMesh->elementType = (SMESH::ElementType)elementType;
1514           enfMesh->groupName = groupName;
1515           enfMesh->persistID = persistID;
1516
1517           _enfMeshList.insert(enfMesh);
1518           //std::cout << "Restoring of enforced mesh " <<name  << " done" << std::endl;
1519
1520           name.clear();
1521           entry.clear();
1522           elementType = -1;
1523           groupName.clear();
1524           persistID = -1;
1525           isOK = false;
1526         }
1527
1528         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1529           while (isOK && (txt != "__END_NAME__")) {
1530             isOK = static_cast<bool>(load >> txt);
1531             if (txt != "__END_NAME__") {
1532               if (!name.empty())
1533                 name += " ";
1534               name += txt;
1535             }
1536           }
1537           MESSAGE("name: " <<name);
1538         }
1539
1540         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1541           isOK = static_cast<bool>(load >> entry);
1542           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1543           if (txt != "__END_ENTRY__")
1544             throw std::exception();
1545           MESSAGE("entry: " << entry);
1546         }
1547
1548         if (txt == "__BEGIN_ELEM_TYPE__") {  // __BEGIN_ELEM_TYPE__
1549           isOK = static_cast<bool>(load >> elementType);
1550           isOK = static_cast<bool>(load >> txt); // __END_ELEM_TYPE__
1551           if (txt != "__END_ELEM_TYPE__")
1552             throw std::exception();
1553           MESSAGE("elementType: " << elementType);
1554         }
1555
1556         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1557           while (isOK && (txt != "__END_GROUP__")) {
1558             isOK = static_cast<bool>(load >> txt);
1559             if (txt != "__END_GROUP__") {
1560               if (!groupName.empty())
1561                 groupName += " ";
1562               groupName += txt;
1563             }
1564           } // while
1565           MESSAGE("groupName: " << groupName);
1566         } // if
1567
1568         if (txt == "__PERSIST_ID__") {
1569           isOK = static_cast<bool>(load >> persistID);
1570           MESSAGE("persistID: " << persistID);
1571         }
1572         //std::cout << "isOK: " << isOK << std::endl;
1573       } // while
1574       //                } // if
1575       isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1576     } // while
1577   } // if
1578
1579   // New options in 2.9.6 (issue #17784)
1580
1581   if ( ! hasOptions && ! hasEnforcedVertices && ! hasEnforcedMeshes )
1582     myUseVolumeProximity = ( separator == "1" );
1583   else if ( static_cast<bool>( load >> i ))
1584     myUseVolumeProximity = (bool) i;
1585
1586   if ( static_cast<bool>( load >> myNbVolumeProximityLayers ))
1587   {
1588     load >> myMinSize;
1589     load >> myMaxSize;
1590     load >> myMinSizeDefault;
1591     load >> myMaxSizeDefault;
1592
1593     std::string option, value;
1594     if ( static_cast<bool>( load >> i ) && i >= 0 )
1595     {
1596       for ( int nbRead = 0; nbRead < i; ++nbRead )
1597       {
1598         load >> option >> value;
1599         _option2value[ std::string( option, 1 )] = std::string( value, 1 );
1600       }
1601     }
1602     if ( static_cast<bool>( load >> i ) && i >= 0 )
1603     {
1604       for ( int nbRead = 0; nbRead < i; ++nbRead )
1605       {
1606         load >> option >> value;
1607         _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
1608       }
1609     }
1610   }
1611
1612   return load;
1613 }
1614
1615 //=======================================================================
1616 //function : SetParametersByMesh
1617 //=======================================================================
1618
1619 bool GHS3DPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&)
1620 {
1621   return false;
1622 }
1623
1624
1625 //================================================================================
1626 /*!
1627  * \brief Sets myToMakeGroupsOfDomains depending on whether theMesh is on shape or not
1628  */
1629 //================================================================================
1630
1631 bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
1632                                                      const SMESH_Mesh* /*theMesh*/)
1633 {
1634   myToMakeGroupsOfDomains = ( !dflts._shape || dflts._shape->IsNull() );
1635
1636   double diagonal = dflts._elemLength * _gen->GetBoundaryBoxSegmentation();
1637   myMinSizeDefault = 1e-3 * diagonal;
1638   myMaxSizeDefault = diagonal / 5.;
1639
1640   return true;
1641 }
1642
1643 //================================================================================
1644 /*!
1645  * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
1646  */
1647 //================================================================================
1648
1649 std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* hyp,
1650                                                  const bool                    hasShapeToMesh,
1651                                                  const bool                    forExecutable)
1652 {
1653   std::string cmd = GetExeName();
1654   // check if any option is overridden by hyp->myTextOption
1655   bool max_memory     = hyp ? !hyp->HasOptionDefined("max_memory")               : true;
1656   bool auto_memory    = hyp ? !hyp->HasOptionDefined("automatic_memory")         : true;
1657   bool comp           = hyp ? !hyp->HasOptionDefined("components")               : true;
1658   bool optim_level    = hyp ? !hyp->HasOptionDefined("optimisation_level")       : true;
1659   bool no_int_points  = hyp ? !hyp->HasOptionDefined("no_internal_points")       : true;
1660   bool C              = hyp ? !hyp->HasOptionDefined("-C")                       : true;
1661   bool verbose        = hyp ? !hyp->HasOptionDefined("verbose")                  : true;
1662   bool gra            = hyp ? !hyp->HasOptionDefined("-Dcpropa")                 : true;
1663   bool rem            = hyp ? !hyp->HasOptionDefined("no_initial_central_point") : true;
1664   //bool fem            = hyp ? !hyp->HasOptionDefined("-FEM")                     : true;
1665
1666   // if use boundary recovery version, few options are allowed
1667   bool useBndRecovery = !C;
1668   if ( !useBndRecovery && hyp )
1669     useBndRecovery = hyp->myToUseBoundaryRecoveryVersion;
1670
1671   // MG-Tetra needs to know amount of memory it may use (MB).
1672   // Default memory is defined at MG-Tetra installation but it may be not enough,
1673   // so allow to use about all available memory
1674   if ( max_memory ) {
1675     float aMaximumMemory = hyp ? hyp->myMaximumMemory : -1;
1676     cmd += " --max_memory ";
1677     if ( aMaximumMemory < 0 ) cmd += SMESH_Comment( int( DefaultMaximumMemory() ));
1678     else                      cmd += SMESH_Comment( int( aMaximumMemory ));
1679   }
1680   if ( auto_memory && !useBndRecovery ) {
1681     float aInitialMemory = hyp ? hyp->myInitialMemory : -1;
1682     cmd += " --automatic_memory ";
1683     if ( aInitialMemory > 0 ) cmd += SMESH_Comment( int( aInitialMemory ));
1684     else                      cmd += "100";
1685   }
1686   // component to mesh
1687   if ( comp && !useBndRecovery ) {
1688     // We always run MG-Tetra with "to mesh holes'==TRUE (see PAL19680)
1689     if ( hasShapeToMesh )
1690       cmd += " --components all";
1691     else {
1692       bool aToMeshHoles = hyp ? hyp->myToMeshHoles : DefaultMeshHoles();
1693       if ( aToMeshHoles ) cmd += " --components all";
1694       else                cmd += " --components outside_components";
1695     }
1696   }
1697   const bool toCreateNewNodes = ( no_int_points && ( !hyp || hyp->myToCreateNewNodes ));
1698
1699   // optimization level
1700   if ( !toCreateNewNodes ) {
1701     cmd += " --optimisation_level none"; // issue 22608
1702   }
1703   else if ( optim_level && hyp && !useBndRecovery ) {
1704     if ( hyp->myOptimizationLevel >= 0 && hyp->myOptimizationLevel < 5 ) {
1705       const char* level[] = { "none" , "light" , "standard" , "standard+" , "strong" };
1706       cmd += " --optimisation_level ";
1707       cmd += level[ hyp->myOptimizationLevel ];
1708     }
1709   }
1710
1711   // to create internal nodes
1712   if ( no_int_points && !toCreateNewNodes ) {
1713     if ( forExecutable )
1714       cmd += " --no_internal_points";
1715     else
1716       cmd += " --internalpoints no";
1717   }
1718
1719   // verbose mode
1720   if ( verbose && hyp ) {
1721     cmd += " --verbose " + SMESH_Comment( hyp->myVerboseLevel );
1722   }
1723
1724   // boundary recovery version
1725   // if ( useBndRecovery ) {
1726   //   cmd += " -C";
1727   // }
1728
1729   // to use FEM correction
1730   // if ( fem && hyp && hyp->myToUseFemCorrection) {
1731   //   cmd += " -FEM";
1732   // }
1733
1734   // to remove initial central point.
1735   if ( rem && hyp && hyp->myToRemoveCentralPoint ) {
1736     if ( forExecutable )
1737       cmd += " --no_initial_central_point";
1738     else
1739       cmd += " --centralpoint no";
1740   }
1741
1742   // options as text
1743   // if ( hyp && !hyp->myTextOption.empty() ) {
1744   //   cmd += " " + hyp->myTextOption;
1745   // }
1746
1747   // min/max size
1748   if ( hyp )
1749   {
1750     if ( hyp->GetMinSize() > 0 )
1751       cmd += " --min_size " + SMESH_Comment( hyp->GetMinSize() );
1752     if ( hyp->GetMaxSize() > 0 )
1753       cmd += " --max_size " + SMESH_Comment( hyp->GetMaxSize() );
1754   }
1755
1756   // to define volumic gradation.
1757   if ( gra && hyp )
1758   {
1759     cmd += " --gradation " + SMESH_Comment( hyp->myGradation );
1760   }
1761
1762   if ( hyp )
1763   {
1764     // proximity
1765     if ( hyp->GetUseVolumeProximity() )
1766     {
1767       cmd += " --volume_proximity_layers " + SMESH_Comment( hyp->GetNbVolumeProximityLayers() );
1768     }
1769
1770     std::string option, value;
1771     bool isDefault;
1772     const TOptionValues* options[] = { & hyp->_option2value, & hyp->_customOption2value };
1773     for ( int iOp = 0; iOp < 2; ++iOp )
1774     {
1775       TOptionValues::const_iterator o2v = options[iOp]->begin();
1776       for ( ; o2v != options[iOp]->end(); ++o2v )
1777       {
1778         option = o2v->first;
1779         value = hyp->GetOptionValue( option, &isDefault );
1780
1781         if ( isDefault )
1782           continue;
1783         if ( value.empty() )//value == NoValue() )
1784         {
1785           if ( hyp->_defaultOptionValues.count( option ))
1786             continue; // non-custom option with no value
1787           //value.clear();
1788         }
1789         if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
1790         {
1791           if ( !value.empty() && ToBool( value ) == false )
1792             continue;
1793           value.clear();
1794         }
1795         if ( option[0] != '-' )
1796           cmd += " --";
1797         else
1798           cmd += " ";
1799         cmd += option + " " + value;
1800       }
1801     }
1802   }
1803
1804 #ifdef WIN32
1805   cmd += " < NUL";
1806 #endif
1807
1808   return cmd;
1809 }
1810
1811 //================================================================================
1812 /*!
1813  * \brief Return a unique file name
1814  */
1815 //================================================================================
1816
1817 std::string GHS3DPlugin_Hypothesis::GetFileName(const GHS3DPlugin_Hypothesis* hyp)
1818 {
1819   std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory();
1820   const char lastChar = *aTmpDir.rbegin();
1821 #ifdef WIN32
1822     if(lastChar != '\\') aTmpDir+='\\';
1823 #else
1824     if(lastChar != '/') aTmpDir+='/';
1825 #endif      
1826
1827   TCollection_AsciiString aGenericName = (char*)aTmpDir.c_str();
1828   aGenericName += "GHS3D_";
1829   aGenericName += getpid();
1830   aGenericName += "_";
1831   aGenericName += Abs((Standard_Integer)(long) aGenericName.ToCString());
1832
1833   return aGenericName.ToCString();
1834 }
1835
1836 //================================================================================
1837 /*
1838  * Return the name of executable
1839  */
1840 //================================================================================
1841
1842 std::string GHS3DPlugin_Hypothesis::GetExeName()
1843 {
1844   return "mg-tetra.exe";
1845 }
1846
1847 //================================================================================
1848 /*!
1849 * \brief Return the enforced vertices
1850 */
1851 //================================================================================
1852
1853 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList GHS3DPlugin_Hypothesis::GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp)
1854 {
1855   return hyp ? hyp->_GetEnforcedVertices(): TGHS3DEnforcedVertexList();
1856 }
1857
1858 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const GHS3DPlugin_Hypothesis* hyp)
1859 {  
1860   return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): TGHS3DEnforcedVertexCoordsValues();
1861 }
1862
1863 GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexEntryValues GHS3DPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const GHS3DPlugin_Hypothesis* hyp)
1864 {  
1865   return hyp ? hyp->_GetEnforcedVerticesEntrySize(): TGHS3DEnforcedVertexEntryValues();
1866 }
1867
1868 GHS3DPlugin_Hypothesis::TCoordsGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByCoords (const GHS3DPlugin_Hypothesis* hyp)
1869 {  
1870   return hyp ? hyp->_GetEnforcedVerticesByCoords(): TCoordsGHS3DEnforcedVertexMap();
1871 }
1872
1873 GHS3DPlugin_Hypothesis::TGeomEntryGHS3DEnforcedVertexMap GHS3DPlugin_Hypothesis::GetEnforcedVerticesByEntry (const GHS3DPlugin_Hypothesis* hyp)
1874 {  
1875   return hyp ? hyp->_GetEnforcedVerticesByEntry(): TGeomEntryGHS3DEnforcedVertexMap();
1876 }
1877
1878 GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap GHS3DPlugin_Hypothesis::GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp)
1879 {
1880   return hyp ? hyp->_GetEnforcedNodes():TIDSortedNodeGroupMap();
1881 }
1882
1883 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp)
1884 {
1885   return hyp ? hyp->_GetEnforcedEdges():TIDSortedElemGroupMap();
1886 }
1887
1888 GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap GHS3DPlugin_Hypothesis::GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp)
1889 {
1890   return hyp ? hyp->_GetEnforcedTriangles():TIDSortedElemGroupMap();
1891 }
1892
1893 GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp)
1894 {
1895   return hyp ? hyp->_GetNodeIDToSizeMap(): TID2SizeMap();
1896 }
1897
1898 GHS3DPlugin_Hypothesis::TSetStrings GHS3DPlugin_Hypothesis::GetGroupsToRemove(const GHS3DPlugin_Hypothesis* hyp)
1899 {
1900   return hyp ? hyp->_GetGroupsToRemove(): TSetStrings();
1901 }
1902
1903
1904 //=============================================================================
1905 void GHS3DPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
1906                                             const std::string& optionValue)
1907   throw (std::invalid_argument)
1908 {
1909   TOptionValues::iterator op_val = _option2value.find(optionName);
1910   if (op_val == _option2value.end())
1911   {
1912     op_val = _customOption2value.find( optionName );
1913     if ( op_val != _customOption2value.end() && op_val->second != optionValue )
1914       NotifySubMeshesHypothesisModification();
1915     _customOption2value[ optionName ] = optionValue;
1916     return;
1917   }
1918
1919   if (op_val->second != optionValue)
1920   {
1921     const char* ptr = optionValue.c_str();
1922     // strip white spaces
1923     while (ptr[0] == ' ')
1924       ptr++;
1925     int i = strlen(ptr);
1926     while (i != 0 && ptr[i - 1] == ' ')
1927       i--;
1928     // check value type
1929     bool typeOk = true;
1930     std::string typeName;
1931     if (i == 0) {
1932       // empty string
1933     } else if (_charOptions.count(optionName)) {
1934       // do not check strings
1935     } else if (_doubleOptions.count(optionName)) {
1936       // check if value is double
1937       ToDbl(ptr, &typeOk);
1938       typeName = "real";
1939     } else if (_boolOptions.count(optionName)) {
1940       // check if value is bool
1941       ToBool(ptr, &typeOk);
1942       typeName = "bool";
1943     } else {
1944       // check if value is int
1945       ToInt(ptr, &typeOk);
1946       typeName = "integer";
1947     }
1948     if ( typeOk ) // check some specific values ?
1949     {
1950     }
1951     if ( !typeOk )
1952     {
1953       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
1954       throw std::invalid_argument(msg);
1955     }
1956     std::string value( ptr, i );
1957     if ( _defaultOptionValues[ optionName ] == value )
1958       value.clear();
1959
1960     op_val->second = value;
1961
1962     NotifySubMeshesHypothesisModification();
1963   }
1964 }
1965
1966 //=============================================================================
1967 //! Return option value. If isDefault provided, it can be a default value,
1968 //  then *isDefault == true. If isDefault is not provided, the value will be
1969 //  empty if it equals a default one.
1970 std::string GHS3DPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
1971                                                    bool*              isDefault) const
1972   throw (std::invalid_argument)
1973 {
1974   TOptionValues::const_iterator op_val = _option2value.find(optionName);
1975   if (op_val == _option2value.end())
1976   {
1977     op_val = _customOption2value.find(optionName);
1978     if (op_val == _customOption2value.end())
1979     {
1980       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
1981       throw std::invalid_argument(msg);
1982     }
1983   }
1984   std::string val = op_val->second;
1985   if ( isDefault ) *isDefault = ( val.empty() );
1986
1987   if ( val.empty() && isDefault )
1988   {
1989     op_val = _defaultOptionValues.find( optionName );
1990     if (op_val != _defaultOptionValues.end())
1991       val = op_val->second;
1992   }
1993   return val;
1994 }
1995
1996
1997 //=============================================================================
1998 bool GHS3DPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
1999 {
2000   bool isDefault = false;
2001   try
2002   {
2003     GetOptionValue( optionName, &isDefault );
2004   }
2005   catch ( std::invalid_argument )
2006   {
2007     return false;
2008   }
2009   return !isDefault;
2010 }
2011
2012 //=============================================================================
2013 void GHS3DPlugin_Hypothesis::ClearOption(const std::string& optionName)
2014 {
2015   TOptionValues::iterator op_val = _customOption2value.find(optionName);
2016   if (op_val != _customOption2value.end())
2017    _customOption2value.erase(op_val);
2018   else {
2019     op_val = _option2value.find(optionName);
2020     if (op_val != _option2value.end())
2021       op_val->second.clear();
2022   }
2023 }
2024
2025 //=============================================================================
2026 GHS3DPlugin_Hypothesis::TOptionValues GHS3DPlugin_Hypothesis::GetOptionValues() const
2027 {
2028   TOptionValues vals;
2029   TOptionValues::const_iterator op_val = _option2value.begin();
2030   for ( ; op_val != _option2value.end(); ++op_val )
2031     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
2032
2033   return vals;
2034 }
2035
2036 //================================================================================
2037 /*!
2038  * \brief Converts a string to a bool
2039  */
2040 //================================================================================
2041
2042 bool GHS3DPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
2043   throw (std::invalid_argument)
2044 {
2045   std::string s = str;
2046   if ( isOk ) *isOk = true;
2047
2048   for ( size_t i = 0; i <= s.size(); ++i )
2049     s[i] = tolower( s[i] );
2050
2051   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
2052     return true;
2053
2054   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
2055     return false;
2056
2057   if ( isOk )
2058     *isOk = false;
2059   else {
2060     std::string msg = "Not a Boolean value:'" + str + "'";
2061     throw std::invalid_argument(msg);
2062   }
2063   return false;
2064 }
2065
2066 //================================================================================
2067 /*!
2068  * \brief Converts a string to a real value
2069  */
2070 //================================================================================
2071
2072 double GHS3DPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
2073   throw (std::invalid_argument)
2074 {
2075   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2076
2077   char * endPtr;
2078   double val = strtod(&str[0], &endPtr);
2079   bool ok = (&str[0] != endPtr);
2080
2081   if ( isOk ) *isOk = ok;
2082
2083   if ( !ok )
2084   {
2085     std::string msg = "Not a real value:'" + str + "'";
2086     throw std::invalid_argument(msg);
2087   }
2088   return val;
2089 }
2090
2091 //================================================================================
2092 /*!
2093  * \brief Converts a string to a integer value
2094  */
2095 //================================================================================
2096
2097 int GHS3DPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
2098   throw (std::invalid_argument)
2099 {
2100   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2101
2102   char * endPtr;
2103   int val = (int)strtol( &str[0], &endPtr, 10);
2104   bool ok = (&str[0] != endPtr);
2105
2106   if ( isOk ) *isOk = ok;
2107
2108   if ( !ok )
2109   {
2110     std::string msg = "Not an integer value:'" + str + "'";
2111     throw std::invalid_argument(msg);
2112   }
2113   return val;
2114 }
2115