Salome HOME
Copyright update 2022
[plugins/hybridplugin.git] / src / HYBRIDPlugin / HYBRIDPlugin_Hypothesis.cxx
1 // Copyright (C) 2007-2022  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      : HYBRIDPlugin_Hypothesis.cxx
22 // Created   : Wed Apr  2 12:36:29 2008
23 // Author    : Edward AGAPOV (eap)
24 //=============================================================================
25 //
26 #include "HYBRIDPlugin_Hypothesis.hxx"
27
28 #include <SMESHDS_Mesh.hxx>
29
30 #include <TopExp_Explorer.hxx>
31
32 #ifdef WIN32
33 #include <process.h>
34 #define getpid _getpid
35 #endif
36
37 namespace
38 {
39   struct GET_DEFAULT // struct used to get default value from GetOptionValue()
40   {
41     bool isDefault;
42     operator bool* () { return &isDefault; }
43   };
44 }
45
46 //=======================================================================
47 //function : HYBRIDPlugin_Hypothesis
48 //=======================================================================
49
50 HYBRIDPlugin_Hypothesis::HYBRIDPlugin_Hypothesis(int hypId, SMESH_Gen * gen)
51   : SMESH_Hypothesis(hypId, gen),
52     myNbOfBoundaryLayers(DefaultNbOfBoundaryLayers()),
53     myHeightFirstLayer(DefaultHeightFirstLayer()),
54     myHeightIsRelative(DefaultHeightIsRelative()),
55     myBoundaryLayersGrowth(DefaultBoundaryLayersGrowth()),
56     myBoundaryLayersMaxElemAngle(DefaultBoundaryLayersMaxElemAngle()),
57     myBoundaryLayersProgression(DefaultBoundaryLayersProgression()),
58     myElementGeneration(DefaultElementGeneration()),
59     myCoreSize(DefaultCoreSize()),
60     myLayersOnAllWrap(DefaultLayersOnAllWrap()),
61     myCollisionMode(DefaultCollisionMode()),
62     myAddMultinormals(DefaultAddMultinormals()),
63     mySmoothNormals(DefaultSmoothNormals()),
64     myMultinormalsAngle(DefaultMultinormalsAngle()),
65     myGradation(DefaultGradation()),
66     myWorkingDirectory(DefaultWorkingDirectory()),
67     myVerboseLevel(DefaultVerboseLevel()),
68     myLogInStandardOutput(DefaultStandardOutputLog()),
69     myRemoveLogOnSuccess(DefaultRemoveLogOnSuccess()),
70     myKeepFiles(DefaultKeepFiles()),
71     myOptimizationLevel(DefaultOptimizationLevel()),
72     myToMakeGroupsOfDomains(DefaultToMakeGroupsOfDomains()),
73     myToMeshHoles(DefaultMeshHoles()),
74     myMaximumMemory(-1),
75     myInitialMemory(-1),
76     myToCreateNewNodes(DefaultToCreateNewNodes()),
77     myToUseBoundaryRecoveryVersion(DefaultToUseBoundaryRecoveryVersion()),
78     myToUseFemCorrection(DefaultToUseFEMCorrection()),
79     myToRemoveCentralPoint(DefaultToRemoveCentralPoint())
80 {
81   _name = "HYBRID_Parameters";
82   _param_algo_dim = 3;
83
84   const char* boolOptionNames[] = { "add_multinormals", // no
85                                     "smooth_normals",   // no
86                                     "" // mark of end
87   };
88   const char* intOptionNames[] = { "max_number_of_threads", // 4
89                                    "" // mark of end
90   };
91   const char* doubleOptionNames[] = { //"global_physical_size",  // 0.0 = not set -- myCoreSize
92                                       "gradation",    // 2.0
93                                       //"boundary_layer_max_element_angle", // 165.0 -- myBoundaryLayersMaxElemAngle
94                                       "multinormal_angle_threshold", // 30.0
95                                       "" // mark of end
96   };
97   const char* charOptionNames[] = { "collision_mode",                   // stop/decrease
98                                     "" // mark of end
99   };
100
101   int i = 0;
102   while (boolOptionNames[i][0])
103   {
104     _boolOptions.insert( boolOptionNames[i] );
105     _option2value[boolOptionNames[i++]].clear();
106   }
107   i = 0;
108   while (intOptionNames[i][0])
109     _option2value[intOptionNames[i++]].clear();
110
111   i = 0;
112   while (doubleOptionNames[i][0]) {
113     _doubleOptions.insert(doubleOptionNames[i]);
114     _option2value[doubleOptionNames[i++]].clear();
115   }
116   i = 0;
117   while (charOptionNames[i][0]) {
118     _charOptions.insert(charOptionNames[i]);
119     _option2value[charOptionNames[i++]].clear();
120   }
121
122   // default values to be used while MG meshing
123
124   _defaultOptionValues["add_multinormals"                ] = "no";
125   _defaultOptionValues["smooth_normals"                  ] = "no";
126   _defaultOptionValues["max_number_of_threads"           ] = "4";
127   //_defaultOptionValues["global_physical_size"            ] = "0";
128   _defaultOptionValues["gradation"                       ] = "2";
129   //_defaultOptionValues["boundary_layer_max_element_angle"] = "165";
130   _defaultOptionValues["multinormal_angle_threshold"     ] = "30";
131   _defaultOptionValues["collision_mode"                  ] = "stop";
132
133 #ifdef _DEBUG_
134   // check validity of option names of _defaultOptionValues
135   TOptionValues::iterator n2v = _defaultOptionValues.begin();
136   for ( ; n2v != _defaultOptionValues.end(); ++n2v )
137     ASSERT( _option2value.count( n2v->first ));
138   ASSERT( _option2value.size() == _defaultOptionValues.size() );
139 #endif
140 }
141
142 //=======================================================================
143 //function : SetHeightIsRelative
144 //=======================================================================
145
146 void HYBRIDPlugin_Hypothesis::SetHeightIsRelative(bool isRelative)
147 {
148   if ( myHeightIsRelative != isRelative ) {
149     myHeightIsRelative = isRelative;
150     NotifySubMeshesHypothesisModification();
151   }
152 }
153
154 //=======================================================================
155 //function : SetBoundaryLayersMaxElemAngle
156 //=======================================================================
157
158 void HYBRIDPlugin_Hypothesis::SetBoundaryLayersMaxElemAngle( double angle )
159 {
160   if ( myBoundaryLayersMaxElemAngle != angle ) {
161     myBoundaryLayersMaxElemAngle = angle;
162     NotifySubMeshesHypothesisModification();
163   }
164 }
165
166
167 //=======================================================================
168 //function : SetLayersOnAllWrap
169 //=======================================================================
170
171 void HYBRIDPlugin_Hypothesis::SetLayersOnAllWrap(bool toMesh)
172 {
173   if ( myLayersOnAllWrap != toMesh ) {
174     myLayersOnAllWrap = toMesh;
175     NotifySubMeshesHypothesisModification();
176   }
177 }
178
179 //=======================================================================
180 //function : GetLayersOnAllWrap
181 //=======================================================================
182
183 bool HYBRIDPlugin_Hypothesis::GetLayersOnAllWrap(bool /*checkFreeOption*/) const
184 {
185   return myLayersOnAllWrap;
186 }
187
188 //=======================================================================
189 //function : SetFacesWithLayers
190 //purpose  : Set IDs of faces to grow the layers on
191 //=======================================================================
192
193 bool HYBRIDPlugin_Hypothesis::SetFacesWithLayers(const std::vector<int>& theVal)
194 {
195   if ( myFacesWithLayers != theVal )
196   {
197     myFacesWithLayers = theVal;
198     NotifySubMeshesHypothesisModification();
199     return true;
200   }
201   return false;
202 }
203
204 //=======================================================================
205 //function : GetFacesWithLayers
206 //purpose  : Return IDs of faces to grow the layers on
207 //=======================================================================
208
209 const std::vector<int>& HYBRIDPlugin_Hypothesis::GetFacesWithLayers() const
210 {
211   return myFacesWithLayers;
212 }
213
214 //=======================================================================
215 //function : SetFacesWithImprinting
216 //purpose  : Set IDs of faces to grow the layers on
217 //=======================================================================
218
219 bool HYBRIDPlugin_Hypothesis::SetFacesWithImprinting(const std::vector<int>& theVal)
220 {
221   if ( myFacesWithImprinting != theVal )
222   {
223     myFacesWithImprinting = theVal;
224     NotifySubMeshesHypothesisModification();
225     return true;
226   }
227   return false;
228 }
229
230 //=======================================================================
231 //function : GetFacesWithImprinting
232 //purpose  : Return IDs of faces to grow the layers on
233 //=======================================================================
234
235 const std::vector<int>& HYBRIDPlugin_Hypothesis::GetFacesWithImprinting() const
236 {
237   return myFacesWithImprinting;
238 }
239
240 //=======================================================================
241 //function : SetFacesWithSnapping
242 //purpose  : Set IDs of faces that already have surface layers
243 //=======================================================================
244
245 bool HYBRIDPlugin_Hypothesis::SetFacesWithSnapping(const std::vector<int>& theVal)
246 {
247   if ( myFacesWithSnapping != theVal )
248   {
249     myFacesWithSnapping = theVal;
250     NotifySubMeshesHypothesisModification();
251     return true;
252   }
253   return false;
254 }
255
256 //=======================================================================
257 //function : GetFacesWithSnapping
258 //purpose  : Return IDs of faces that already have surface layers
259 //=======================================================================
260
261 const std::vector<int>& HYBRIDPlugin_Hypothesis::GetFacesWithSnapping() const
262 {
263   return myFacesWithSnapping;
264 }
265
266 //=======================================================================
267 //function : SetToMeshHoles
268 //=======================================================================
269
270 void HYBRIDPlugin_Hypothesis::SetToMeshHoles(bool toMesh)
271 {
272   if ( myToMeshHoles != toMesh ) {
273     myToMeshHoles = toMesh;
274     NotifySubMeshesHypothesisModification();
275   }
276 }
277
278 //=======================================================================
279 //function : GetToMeshHoles
280 //=======================================================================
281
282 bool HYBRIDPlugin_Hypothesis::GetToMeshHoles(bool /*checkFreeOption*/) const
283 {
284   return myToMeshHoles;
285 }
286
287 //=======================================================================
288 //function : SetToMakeGroupsOfDomains
289 //=======================================================================
290
291 void HYBRIDPlugin_Hypothesis::SetToMakeGroupsOfDomains(bool toMakeGroups)
292 {
293   if ( myToMakeGroupsOfDomains != toMakeGroups ) {
294     myToMakeGroupsOfDomains = toMakeGroups;
295     NotifySubMeshesHypothesisModification();
296   }
297 }
298
299 //=======================================================================
300 //function : GetToMakeGroupsOfDomains
301 //=======================================================================
302
303 bool HYBRIDPlugin_Hypothesis::GetToMakeGroupsOfDomains() const
304 {
305   return myToMakeGroupsOfDomains;
306 }
307
308 //=======================================================================
309 //function : GetToMakeGroupsOfDomains
310 //=======================================================================
311
312 bool HYBRIDPlugin_Hypothesis::GetToMakeGroupsOfDomains(const HYBRIDPlugin_Hypothesis* hyp)
313 {
314   bool res;
315   if ( hyp ) res = /*hyp->GetToMeshHoles(true) &&*/ hyp->GetToMakeGroupsOfDomains();
316   else       res = /*DefaultMeshHoles()        &&*/ DefaultToMakeGroupsOfDomains();
317   return res;
318 }
319
320 //=======================================================================
321 //function : SetMaximumMemory
322 //=======================================================================
323
324 void HYBRIDPlugin_Hypothesis::SetMaximumMemory(double MB)
325 {
326   if ( myMaximumMemory != MB ) {
327     myMaximumMemory = MB;
328     NotifySubMeshesHypothesisModification();
329   }
330 }
331
332 //=======================================================================
333 //function : GetMaximumMemory
334 //           * automatic memory adjustment mode. Default is zero
335 //=======================================================================
336
337 double HYBRIDPlugin_Hypothesis::GetMaximumMemory() const
338 {
339   return myMaximumMemory;
340 }
341
342 //=======================================================================
343 //function : SetInitialMemory
344 //=======================================================================
345
346 void HYBRIDPlugin_Hypothesis::SetInitialMemory(double MB)
347 {
348   if ( myInitialMemory != MB ) {
349     myInitialMemory = MB;
350     NotifySubMeshesHypothesisModification();
351   }
352 }
353
354 //=======================================================================
355 //function : GetInitialMemory
356 //=======================================================================
357
358 double HYBRIDPlugin_Hypothesis::GetInitialMemory() const
359 {
360   return myInitialMemory;
361 }
362
363 //=======================================================================
364 //function : SetOptimizationLevel
365 //=======================================================================
366
367 void HYBRIDPlugin_Hypothesis::SetOptimizationLevel(OptimizationLevel level)
368 {
369   if ( myOptimizationLevel != level ) {
370     myOptimizationLevel = level;
371     NotifySubMeshesHypothesisModification();
372   }
373 }
374
375 //=======================================================================
376 //function : GetOptimizationLevel
377 //=======================================================================
378 HYBRIDPlugin_Hypothesis::OptimizationLevel HYBRIDPlugin_Hypothesis::GetOptimizationLevel() const
379 {
380   return (OptimizationLevel) myOptimizationLevel;
381 }
382
383 //=======================================================================
384 //function : SetCollisionMode
385 //=======================================================================
386 void HYBRIDPlugin_Hypothesis::SetCollisionMode(CollisionMode mode)
387 {
388   SetOptionValue( "collision_mode", mode == Decrease ? "decrease" : "stop" );
389   myCollisionMode = mode;
390 }
391
392 //=======================================================================
393 //function : GetCollisionMode
394 //=======================================================================
395 HYBRIDPlugin_Hypothesis::CollisionMode HYBRIDPlugin_Hypothesis::GetCollisionMode() const
396 {
397   return (CollisionMode) myCollisionMode;
398 }
399
400 //=======================================================================
401 //function : SetBoundaryLayersGrowth
402 //=======================================================================
403 void HYBRIDPlugin_Hypothesis::SetBoundaryLayersGrowth(BoundaryLayersGrowth mode)
404 {
405   if ( myBoundaryLayersGrowth != mode ) {
406     myBoundaryLayersGrowth = mode;
407     NotifySubMeshesHypothesisModification();
408   }
409 }
410
411 //=======================================================================
412 //function : GetBoundaryLayersGrowth
413 //=======================================================================
414 HYBRIDPlugin_Hypothesis::BoundaryLayersGrowth HYBRIDPlugin_Hypothesis::GetBoundaryLayersGrowth() const
415 {
416   return (BoundaryLayersGrowth) myBoundaryLayersGrowth;
417 }
418
419 //=======================================================================
420 //function : SetElementGeneration
421 //=======================================================================
422 void HYBRIDPlugin_Hypothesis::SetElementGeneration(ElementGeneration mode)
423 {
424   if ( myElementGeneration != mode ) {
425     myElementGeneration = mode;
426     NotifySubMeshesHypothesisModification();
427   }
428 }
429
430 //=======================================================================
431 //function : GetElementGeneration
432 //=======================================================================
433 HYBRIDPlugin_Hypothesis::ElementGeneration HYBRIDPlugin_Hypothesis::GetElementGeneration() const
434 {
435   return (ElementGeneration) myElementGeneration;
436 }
437
438 //=======================================================================
439 //function : SetAddMultinormals
440 //=======================================================================
441 void HYBRIDPlugin_Hypothesis::SetAddMultinormals(bool toAddMultinormals)
442 {
443   SetOptionValue( "add_multinormals", toAddMultinormals ? "yes" : "no" );
444   myAddMultinormals = toAddMultinormals;
445 }
446
447 //=======================================================================
448 //function : GetAddMultinormals
449 //=======================================================================
450
451 bool HYBRIDPlugin_Hypothesis::GetAddMultinormals() const
452 {
453   return myAddMultinormals;
454 }
455
456 //=======================================================================
457 //function : SetSmoothNormals
458 //=======================================================================
459
460 void HYBRIDPlugin_Hypothesis::SetSmoothNormals(bool toSmoothNormals)
461 {
462   SetOptionValue( "smooth_normals", toSmoothNormals ? "yes" : "no" );
463   mySmoothNormals = toSmoothNormals;
464 }
465
466 //=======================================================================
467 //function : GetSmoothNormals
468 //=======================================================================
469
470 bool HYBRIDPlugin_Hypothesis::GetSmoothNormals() const
471 {
472   return mySmoothNormals;
473 }
474
475 //=======================================================================
476 //function : SetHeightFirstLayer
477 //=======================================================================
478
479 void HYBRIDPlugin_Hypothesis::SetHeightFirstLayer(double toHeightFirstLayer)
480 {
481   if ( myHeightFirstLayer != toHeightFirstLayer ) {
482     myHeightFirstLayer = toHeightFirstLayer;
483     NotifySubMeshesHypothesisModification();
484   }
485 }
486
487 //=======================================================================
488 //function : GetHeightFirstLayer
489 //=======================================================================
490
491 double HYBRIDPlugin_Hypothesis::GetHeightFirstLayer() const
492 {
493   return myHeightFirstLayer;
494 }
495
496 //=======================================================================
497 //function : SetBoundaryLayersProgression
498 //=======================================================================
499
500 void HYBRIDPlugin_Hypothesis::SetBoundaryLayersProgression(double toBoundaryLayersProgression)
501 {
502   if ( myBoundaryLayersProgression != toBoundaryLayersProgression ) {
503     myBoundaryLayersProgression = toBoundaryLayersProgression;
504     NotifySubMeshesHypothesisModification();
505   }
506 }
507
508 //=======================================================================
509 //function : GetBoundaryLayersProgression
510 //=======================================================================
511
512 double HYBRIDPlugin_Hypothesis::GetBoundaryLayersProgression() const
513 {
514   return myBoundaryLayersProgression;
515 }
516
517 //=======================================================================
518 //function : SetCoreSize
519 //=======================================================================
520
521 void HYBRIDPlugin_Hypothesis::SetCoreSize(double toCoreSize)
522 {
523   if ( myCoreSize != toCoreSize ) {
524     myCoreSize = toCoreSize;
525     NotifySubMeshesHypothesisModification();
526   }
527 }
528
529 //=======================================================================
530 //function : GetCoreSize
531 //=======================================================================
532
533 double HYBRIDPlugin_Hypothesis::GetCoreSize() const
534 {
535   return myCoreSize;
536 }
537
538 //=======================================================================
539 //function : SetMultinormalsAngle
540 //=======================================================================
541
542 void HYBRIDPlugin_Hypothesis::SetMultinormalsAngle(double toMultinormalsAngle)
543 {
544   SetOptionValue( "multinormal_angle_threshold", SMESH_Comment( toMultinormalsAngle ));
545   myMultinormalsAngle = toMultinormalsAngle;
546 }
547
548 //=======================================================================
549 //function : GetMultinormalsAngle
550 //=======================================================================
551
552 double HYBRIDPlugin_Hypothesis::GetMultinormalsAngle() const
553 {
554   return myMultinormalsAngle;
555 }
556
557 //=======================================================================
558 //function : SetNbOfBoundaryLayers
559 //=======================================================================
560
561 void HYBRIDPlugin_Hypothesis::SetNbOfBoundaryLayers(short toNbOfBoundaryLayers)
562 {
563   if ( myNbOfBoundaryLayers != toNbOfBoundaryLayers ) {
564     myNbOfBoundaryLayers = toNbOfBoundaryLayers;
565     NotifySubMeshesHypothesisModification();
566   }
567 }
568
569 //=======================================================================
570 //function : GetCoreSize
571 //=======================================================================
572
573 short HYBRIDPlugin_Hypothesis::GetNbOfBoundaryLayers() const
574 {
575   return myNbOfBoundaryLayers;
576 }
577
578
579 /////////////////////////////////////////////////////////////////////////
580
581
582 //=======================================================================
583 //function : SetWorkingDirectory
584 //=======================================================================
585
586 void HYBRIDPlugin_Hypothesis::SetWorkingDirectory(const std::string& path)
587 {
588   if ( myWorkingDirectory != path ) {
589     myWorkingDirectory = path;
590     NotifySubMeshesHypothesisModification();
591   }
592 }
593
594 //=======================================================================
595 //function : GetWorkingDirectory
596 //=======================================================================
597
598 std::string HYBRIDPlugin_Hypothesis::GetWorkingDirectory() const
599 {
600   return myWorkingDirectory;
601 }
602
603 //=======================================================================
604 //function : SetKeepFiles
605 //=======================================================================
606
607 void HYBRIDPlugin_Hypothesis::SetKeepFiles(bool toKeep)
608 {
609   if ( myKeepFiles != toKeep ) {
610     myKeepFiles = toKeep;
611     NotifySubMeshesHypothesisModification();
612   }
613 }
614
615 //=======================================================================
616 //function : GetKeepFiles
617 //=======================================================================
618
619 bool HYBRIDPlugin_Hypothesis::GetKeepFiles() const
620 {
621   return myKeepFiles;
622 }
623
624 //=======================================================================
625 //function : SetVerboseLevel
626 //=======================================================================
627
628 void HYBRIDPlugin_Hypothesis::SetVerboseLevel(short level)
629 {
630   if ( myVerboseLevel != level ) {
631     myVerboseLevel = level;
632     NotifySubMeshesHypothesisModification();
633   }
634 }
635
636 //=======================================================================
637 //function : GetVerboseLevel
638 //=======================================================================
639
640 short HYBRIDPlugin_Hypothesis::GetVerboseLevel() const
641 {
642   return myVerboseLevel;
643 }
644
645 //=======================================================================
646 //function : SetToCreateNewNodes
647 //=======================================================================
648
649 void HYBRIDPlugin_Hypothesis::SetToCreateNewNodes(bool toCreate)
650 {
651   if ( myToCreateNewNodes != toCreate ) {
652     myToCreateNewNodes = toCreate;
653     NotifySubMeshesHypothesisModification();
654   }
655 }
656
657 //=======================================================================
658 //function : GetToCreateNewNodes
659 //=======================================================================
660
661 bool HYBRIDPlugin_Hypothesis::GetToCreateNewNodes() const
662 {
663   return myToCreateNewNodes;
664 }
665
666 //=======================================================================
667 //function : SetToUseBoundaryRecoveryVersion
668 //=======================================================================
669
670 void HYBRIDPlugin_Hypothesis::SetToUseBoundaryRecoveryVersion(bool toUse)
671 {
672   if ( myToUseBoundaryRecoveryVersion != toUse ) {
673     myToUseBoundaryRecoveryVersion = toUse;
674     NotifySubMeshesHypothesisModification();
675   }
676 }
677
678 //=======================================================================
679 //function : GetToUseBoundaryRecoveryVersion
680 //=======================================================================
681
682 bool HYBRIDPlugin_Hypothesis::GetToUseBoundaryRecoveryVersion() const
683 {
684   return myToUseBoundaryRecoveryVersion;
685 }
686
687 //=======================================================================
688 //function : SetFEMCorrection
689 //=======================================================================
690
691 void HYBRIDPlugin_Hypothesis::SetFEMCorrection(bool toUseFem)
692 {
693   if ( myToUseFemCorrection != toUseFem ) {
694     myToUseFemCorrection = toUseFem;
695     NotifySubMeshesHypothesisModification();
696   }
697 }
698
699 //=======================================================================
700 //function : GetFEMCorrection
701 //=======================================================================
702
703 bool HYBRIDPlugin_Hypothesis::GetFEMCorrection() const
704 {
705   return myToUseFemCorrection;
706 }
707
708 //=======================================================================
709 //function : SetToRemoveCentralPoint
710 //=======================================================================
711
712 void HYBRIDPlugin_Hypothesis::SetToRemoveCentralPoint(bool toRemove)
713 {
714   if ( myToRemoveCentralPoint != toRemove ) {
715     myToRemoveCentralPoint = toRemove;
716     NotifySubMeshesHypothesisModification();
717   }
718 }
719
720 //=======================================================================
721 //function : GetToRemoveCentralPoint
722 //=======================================================================
723
724 bool HYBRIDPlugin_Hypothesis::GetToRemoveCentralPoint() const
725 {
726   return myToRemoveCentralPoint;
727 }
728
729 //=======================================================================
730 //function : SetAdvancedOption
731 //=======================================================================
732
733 void HYBRIDPlugin_Hypothesis::SetAdvancedOption(const std::string& option)
734 {
735   size_t wsPos = option.find(' ');
736   if ( wsPos == std::string::npos )
737   {
738     SetOptionValue( option, "" );
739   }
740   else
741   {
742     std::string opt( option, 0, wsPos );
743     std::string val( option, wsPos + 1 );
744     SetOptionValue( opt, val );
745   }
746 }
747
748 //=======================================================================
749 //function : GetAdvancedOption
750 //=======================================================================
751
752 std::string HYBRIDPlugin_Hypothesis::GetAdvancedOption() const
753 {
754   SMESH_Comment txt;
755
756   TOptionValues::const_iterator o2v = _option2value.begin();
757   for ( ; o2v != _option2value.end(); ++o2v )
758     if ( !o2v->second.empty() )
759     {
760       if ( !txt.empty() )
761         txt << " ";
762       txt << o2v->first << " " << o2v->second;
763     }
764   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
765   {
766     if ( !txt.empty() )
767       txt << " ";
768     txt << o2v->first << " " << o2v->second;
769   }
770   return txt;
771 }
772
773 //=======================================================================
774 //function : SetGradation
775 //=======================================================================
776
777 void HYBRIDPlugin_Hypothesis::SetGradation(double gradation)
778 {
779   SetOptionValue( "gradation", SMESH_Comment( gradation ));
780   myGradation = gradation;
781 }
782
783 //=======================================================================
784 //function : GetGradation
785 //=======================================================================
786
787 double HYBRIDPlugin_Hypothesis::GetGradation() const
788 {
789   return myGradation;
790 }
791
792 //=======================================================================
793 //function : SetStandardOutputLog
794 //=======================================================================
795
796 void HYBRIDPlugin_Hypothesis::SetStandardOutputLog(bool logInStandardOutput)
797 {
798   if ( myLogInStandardOutput != logInStandardOutput ) {
799     myLogInStandardOutput = logInStandardOutput;
800     NotifySubMeshesHypothesisModification();
801   }
802 }
803
804 //=======================================================================
805 //function : GetStandardOutputLog
806 //=======================================================================
807
808 bool HYBRIDPlugin_Hypothesis::GetStandardOutputLog() const
809 {
810   return myLogInStandardOutput;
811 }
812
813 //=======================================================================
814 //function : SetRemoveLogOnSuccess
815 //=======================================================================
816
817 void HYBRIDPlugin_Hypothesis::SetRemoveLogOnSuccess(bool removeLogOnSuccess)
818 {
819   if ( myRemoveLogOnSuccess != removeLogOnSuccess ) {
820     myRemoveLogOnSuccess = removeLogOnSuccess;
821     NotifySubMeshesHypothesisModification();
822   }
823 }
824
825 //=======================================================================
826 //function : GetRemoveLogOnSuccess
827 //=======================================================================
828
829 bool HYBRIDPlugin_Hypothesis::GetRemoveLogOnSuccess() const
830 {
831   return myRemoveLogOnSuccess;
832 }
833
834 //=======================================================================
835 //function : SetEnforcedVertex
836 //=======================================================================
837
838 bool HYBRIDPlugin_Hypothesis::SetEnforcedVertex(std::string theName, std::string theEntry, std::string theGroupName,
839                                                double size, double x, double y, double z, bool isCompound)
840 {
841   bool toNotify = false;
842   bool toCreate = true;
843
844   THYBRIDEnforcedVertex *oldEnVertex;
845   THYBRIDEnforcedVertex *newEnfVertex = new THYBRIDEnforcedVertex();
846   newEnfVertex->name = theName;
847   newEnfVertex->geomEntry = theEntry;
848   newEnfVertex->coords.clear();
849   if (!isCompound) {
850     newEnfVertex->coords.push_back(x);
851     newEnfVertex->coords.push_back(y);
852     newEnfVertex->coords.push_back(z);
853   }
854   newEnfVertex->groupName = theGroupName;
855   newEnfVertex->size = size;
856   newEnfVertex->isCompound = isCompound;
857   
858   
859   // update _enfVertexList
860   THYBRIDEnforcedVertexList::iterator it = _enfVertexList.find(newEnfVertex);
861   if (it != _enfVertexList.end()) {
862     toCreate = false;
863     oldEnVertex = (*it);
864     if (oldEnVertex->name != theName) {
865       oldEnVertex->name = theName;
866       toNotify = true;
867     }
868     if (oldEnVertex->groupName != theGroupName) {
869       oldEnVertex->groupName = theGroupName;
870       toNotify = true;
871     }
872     if (oldEnVertex->size != size) {
873       oldEnVertex->size = size;
874       toNotify = true;
875     }
876     if (toNotify) {
877       // update map coords / enf vertex if needed
878       if (oldEnVertex->coords.size()) {
879         _coordsEnfVertexMap[oldEnVertex->coords] = oldEnVertex;
880         _enfVertexCoordsSizeList[oldEnVertex->coords] = size;
881       }
882
883       // update map geom entry / enf vertex if needed
884       if (oldEnVertex->geomEntry != "") {
885         _geomEntryEnfVertexMap[oldEnVertex->geomEntry] = oldEnVertex;
886         _enfVertexEntrySizeList[oldEnVertex->geomEntry] = size;
887       }
888     }
889   }
890
891 //   //////// CREATE ////////////
892   if (toCreate) {
893     toNotify = true;
894     _enfVertexList.insert(newEnfVertex);
895     if (theEntry == "") {
896       _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
897       _enfVertexCoordsSizeList[newEnfVertex->coords] = size;
898     }
899     else {
900       _geomEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
901       _enfVertexEntrySizeList[newEnfVertex->geomEntry] = size;
902     }
903   }
904
905   if (toNotify)
906     NotifySubMeshesHypothesisModification();
907
908   return toNotify;
909 }
910
911
912 //=======================================================================
913 //function : SetEnforcedMesh
914 //=======================================================================
915 bool HYBRIDPlugin_Hypothesis::SetEnforcedMesh(SMESH_Mesh& theMesh, SMESH::ElementType elementType, std::string name, std::string entry, std::string groupName)
916 {
917   TIDSortedElemSet theElemSet;
918   SMDS_ElemIteratorPtr eIt = theMesh.GetMeshDS()->elementsIterator(SMDSAbs_ElementType(elementType));
919   while ( eIt->more() )
920     theElemSet.insert( eIt->next() );
921   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
922   if (added) {
923     THYBRIDEnforcedMesh* newEnfMesh = new THYBRIDEnforcedMesh();
924     newEnfMesh->persistID   = theMesh.GetMeshDS()->GetPersistentId();
925     newEnfMesh->name        = name;
926     newEnfMesh->entry       = entry;
927     newEnfMesh->elementType = elementType;
928     newEnfMesh->groupName   = groupName;
929     
930     THYBRIDEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
931     if (it == _enfMeshList.end()) {
932       _entryEnfMeshMap[entry].insert(newEnfMesh);
933       _enfMeshList.insert(newEnfMesh);
934     }
935     else {
936       delete newEnfMesh;
937     }
938   }
939   return added;
940 }
941
942 //=======================================================================
943 //function : SetEnforcedGroup
944 //=======================================================================
945 bool HYBRIDPlugin_Hypothesis::SetEnforcedGroup(const SMESHDS_Mesh* theMeshDS, SMESH::smIdType_array_var theIDs, SMESH::ElementType elementType, std::string name, std::string entry, std::string groupName)
946 {
947   TIDSortedElemSet theElemSet;
948   if ( theIDs->length() == 0 ){MESSAGE("The source group is empty");}
949   for ( CORBA::ULong i = 0; i < theIDs->length(); i++)
950   {
951     SMESH::smIdType ind = theIDs[i];
952     if (elementType == SMESH::NODE)
953     {
954       const SMDS_MeshNode * node = theMeshDS->FindNode(ind);
955       if (node)
956         theElemSet.insert( node );
957     }
958     else
959     {
960       const SMDS_MeshElement * elem = theMeshDS->FindElement(ind);
961       if (elem)
962         theElemSet.insert( elem );
963     }
964   }
965
966   //   SMDS_ElemIteratorPtr it = theGroup->GetGroupDS()->GetElements();
967   //   while ( it->more() )
968   //     theElemSet.insert( it->next() );
969
970   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
971   if (added) {
972     THYBRIDEnforcedMesh* newEnfMesh = new THYBRIDEnforcedMesh();
973     newEnfMesh->name = name;
974     newEnfMesh->entry = entry;
975     newEnfMesh->elementType = elementType;
976     newEnfMesh->groupName = groupName;
977
978     THYBRIDEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
979     if (it == _enfMeshList.end()) {
980       _entryEnfMeshMap[entry].insert(newEnfMesh);
981       _enfMeshList.insert(newEnfMesh);
982     }
983   }
984   return added;
985 }
986
987 //=======================================================================
988 //function : SetEnforcedElements
989 //=======================================================================
990 bool HYBRIDPlugin_Hypothesis::SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, std::string groupName)
991 {
992   TIDSortedElemSet::const_iterator it = theElemSet.begin();
993   const SMDS_MeshElement* elem;
994   const SMDS_MeshNode* node;
995   bool added = true;
996   std::pair<TIDSortedNodeGroupMap::iterator,bool> nodeRet;
997   std::pair<TIDSortedElemGroupMap::iterator,bool> elemRet;
998
999   for (;it != theElemSet.end();++it)
1000   {
1001     elem = (*it);
1002     switch (elementType) {
1003       case SMESH::NODE:
1004         node = dynamic_cast<const SMDS_MeshNode*>(elem);
1005         if (node) {
1006           nodeRet = _enfNodes.insert(make_pair(node,groupName));
1007           added = added && nodeRet.second;
1008           std::string msg = added ? "yes":"no";
1009         }
1010         else {
1011           SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
1012           for (;nodeIt->more();) {
1013             node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
1014             nodeRet = _enfNodes.insert(make_pair(node,groupName));
1015             added = added && nodeRet.second;
1016           }
1017 //          added = true;s
1018         }
1019         break;
1020       case SMESH::EDGE:
1021         if (elem->GetType() == SMDSAbs_Edge) {
1022           elemRet = _enfEdges.insert(make_pair(elem,groupName));
1023           added = added && elemRet.second;
1024         }
1025         break;
1026       case SMESH::FACE:
1027         if (elem->GetType() == SMDSAbs_Face)
1028         {
1029           if (elem->NbCornerNodes() == 3) {
1030             elemRet = _enfTriangles.insert(make_pair(elem,groupName));
1031             added = added && elemRet.second;
1032           }
1033         }
1034         break;
1035       default:
1036         break;
1037     };
1038   }
1039   if (added)
1040     NotifySubMeshesHypothesisModification();
1041   return added;
1042 }
1043
1044
1045 //=======================================================================
1046 //function : GetEnforcedVertex
1047 //=======================================================================
1048
1049 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex* HYBRIDPlugin_Hypothesis::GetEnforcedVertex(double x, double y, double z)
1050 {
1051   std::vector<double> coord(3);
1052   coord[0] = x;
1053   coord[1] = y;
1054   coord[2] = z;
1055   if (_coordsEnfVertexMap.count(coord)>0)
1056     return _coordsEnfVertexMap[coord];
1057   std::ostringstream msg ;
1058   msg << "No enforced vertex at " << x << ", " << y << ", " << z;
1059   throw std::invalid_argument(msg.str());
1060 }
1061
1062 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex* HYBRIDPlugin_Hypothesis::GetEnforcedVertex(const std::string theEntry)
1063 {
1064   if (_geomEntryEnfVertexMap.count(theEntry)>0)
1065     return _geomEntryEnfVertexMap[theEntry];
1066   
1067   std::ostringstream msg ;
1068   msg << "No enforced vertex with entry " << theEntry;
1069   throw std::invalid_argument(msg.str());
1070 }
1071
1072 //=======================================================================
1073 //function : RemoveEnforcedVertex
1074 //=======================================================================
1075
1076 bool HYBRIDPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, const std::string theEntry)
1077 {
1078   bool toNotify = false;
1079   std::ostringstream msg;
1080   THYBRIDEnforcedVertex *oldEnfVertex;
1081   std::vector<double> coords(3);
1082   coords[0] = x;
1083   coords[1] = y;
1084   coords[2] = z;
1085   
1086   // check that enf vertex with given enf vertex entry exists
1087   TGeomEntryHYBRIDEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry);
1088   if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) {
1089     // Success
1090     oldEnfVertex = it_enfVertexEntry->second;
1091     _geomEntryEnfVertexMap.erase(it_enfVertexEntry);
1092   } else {
1093     // Fail
1094     // check that enf vertex with given coords exists
1095     TCoordsHYBRIDEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
1096     if (it_coords_enf != _coordsEnfVertexMap.end()) {
1097       // Success
1098       oldEnfVertex = it_coords_enf->second;
1099       _coordsEnfVertexMap.erase(it_coords_enf);
1100       _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords));
1101     } else {
1102       // Fail
1103       throw std::invalid_argument(msg.str());
1104     }
1105   }
1106
1107
1108   // update _enfVertexList
1109   THYBRIDEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1110   if (it != _enfVertexList.end()) {
1111     if ((*it)->groupName != "")
1112       _groupsToRemove.insert((*it)->groupName);
1113     _enfVertexList.erase(it);
1114     toNotify = true;
1115   }
1116
1117   if (toNotify)
1118     NotifySubMeshesHypothesisModification();
1119
1120   return toNotify;
1121 }
1122
1123 //=======================================================================
1124 //function : ClearEnforcedVertices
1125 //=======================================================================
1126 void HYBRIDPlugin_Hypothesis::ClearEnforcedVertices()
1127 {
1128   THYBRIDEnforcedVertexList::const_iterator it = _enfVertexList.begin();
1129   for(;it != _enfVertexList.end();++it) {
1130     if ((*it)->groupName != "")
1131       _groupsToRemove.insert((*it)->groupName);
1132   }
1133   _enfVertexList.clear();
1134   _coordsEnfVertexMap.clear();
1135   _geomEntryEnfVertexMap.clear();
1136   _enfVertexCoordsSizeList.clear();
1137   _enfVertexEntrySizeList.clear();
1138   NotifySubMeshesHypothesisModification();
1139 }
1140
1141 //=======================================================================
1142 //function : ClearEnforcedMeshes
1143 //=======================================================================
1144 void HYBRIDPlugin_Hypothesis::ClearEnforcedMeshes()
1145 {
1146   THYBRIDEnforcedMeshList::const_iterator it = _enfMeshList.begin();
1147   for(;it != _enfMeshList.end();++it) {
1148     if ((*it)->groupName != "")
1149       _groupsToRemove.insert((*it)->groupName);
1150   }
1151   _enfNodes.clear();
1152   _enfEdges.clear();
1153   _enfTriangles.clear();
1154   _nodeIDToSizeMap.clear();
1155   _enfMeshList.clear();
1156   _entryEnfMeshMap.clear();
1157   NotifySubMeshesHypothesisModification();
1158 }
1159
1160 //================================================================================
1161 /*!
1162  * \brief At mesh loading, restore enforced elements by just loaded enforced meshes
1163  */
1164 //================================================================================
1165
1166 void HYBRIDPlugin_Hypothesis::RestoreEnfElemsByMeshes()
1167 {
1168   THYBRIDEnforcedMeshList::const_iterator it = _enfMeshList.begin();
1169   for(;it != _enfMeshList.end();++it) {
1170     THYBRIDEnforcedMesh* enfMesh = *it;
1171     if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
1172       SetEnforcedMesh( *mesh,
1173                        enfMesh->elementType,
1174                        enfMesh->name,
1175                        enfMesh->entry,
1176                        enfMesh->groupName );
1177     enfMesh->persistID = -1; // not to restore again
1178   }
1179 }
1180
1181 //=======================================================================
1182 //function : SetGroupsToRemove
1183 //=======================================================================
1184
1185 void HYBRIDPlugin_Hypothesis::ClearGroupsToRemove()
1186 {
1187   _groupsToRemove.clear();
1188 }
1189
1190
1191 //=======================================================================
1192 //function : DefaultLayersOnAllWrap
1193 //=======================================================================
1194
1195 bool HYBRIDPlugin_Hypothesis::DefaultLayersOnAllWrap()
1196 {
1197   return true;
1198 }
1199
1200 //=======================================================================
1201 //function : DefaultMeshHoles
1202 //=======================================================================
1203
1204 bool HYBRIDPlugin_Hypothesis::DefaultMeshHoles()
1205 {
1206   return false; // PAL19680
1207 }
1208
1209 //=======================================================================
1210 //function : DefaultToMakeGroupsOfDomains
1211 //=======================================================================
1212
1213 bool HYBRIDPlugin_Hypothesis::DefaultToMakeGroupsOfDomains()
1214 {
1215   return false; // issue 0022172
1216 }
1217
1218 //=======================================================================
1219 //function : DefaultMaximumMemory
1220 //=======================================================================
1221
1222 #if defined(WIN32)
1223 #include <windows.h>
1224 #elif !defined(__APPLE__)
1225 #include <sys/sysinfo.h>
1226 #endif
1227
1228 double  HYBRIDPlugin_Hypothesis::DefaultMaximumMemory()
1229 {
1230 #if defined(WIN32)
1231   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1232   MEMORYSTATUSEX statex;
1233   statex.dwLength = sizeof (statex);
1234   int err = GlobalMemoryStatusEx (&statex);
1235   if (err != 0) {
1236     int totMB = 
1237       statex.ullTotalPhys / 1024 / 1024 +
1238       statex.ullTotalPageFile / 1024 / 1024 +
1239       statex.ullTotalVirtual / 1024 / 1024;
1240     return ( 0.7 * totMB );
1241   }
1242 #elif !defined(__APPLE__)
1243   struct sysinfo si;
1244   int err = sysinfo( &si );
1245   if ( err == 0 ) {
1246     int ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1247     return ( 0.7 * ramMB );
1248   }
1249 #endif
1250   return 1024;
1251 }
1252
1253 //=======================================================================
1254 //function : DefaultInitialMemory
1255 //=======================================================================
1256
1257 double  HYBRIDPlugin_Hypothesis::DefaultInitialMemory()
1258 {
1259   return DefaultMaximumMemory();
1260 }
1261
1262 //=======================================================================
1263 //function : DefaultCollisionMode
1264 //=======================================================================
1265 short  HYBRIDPlugin_Hypothesis::DefaultCollisionMode()
1266 {
1267   return Decrease;
1268 }
1269
1270 //=======================================================================
1271 //function : DefaultBoundaryLayersGrowth
1272 //=======================================================================
1273 short  HYBRIDPlugin_Hypothesis::DefaultBoundaryLayersGrowth()
1274 {
1275   return Layer_Growth_Inward;
1276 }
1277
1278 //=======================================================================
1279 //function : DefaultElementGeneration
1280 //=======================================================================
1281 short  HYBRIDPlugin_Hypothesis::DefaultElementGeneration()
1282 {
1283   return Generation_Tetra_Dominant;
1284 }
1285
1286 //=======================================================================
1287 //function : DefaultOptimizationLevel
1288 //=======================================================================
1289 short  HYBRIDPlugin_Hypothesis::DefaultOptimizationLevel()
1290 {
1291   return Medium;
1292 }
1293
1294 //=======================================================================
1295 //function : DefaultWorkingDirectory
1296 //=======================================================================
1297
1298 std::string HYBRIDPlugin_Hypothesis::DefaultWorkingDirectory()
1299 {
1300   std::string aTmpDir;
1301
1302   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1303   if(Tmp_dir != NULL) {
1304     aTmpDir = Tmp_dir;
1305   }
1306   else {
1307 #ifdef WIN32
1308     aTmpDir = "C:\\";
1309 #else
1310     aTmpDir = "/tmp/";
1311 #endif
1312   }
1313   return aTmpDir;
1314 }
1315
1316 //=======================================================================
1317 //function : DefaultKeepFiles
1318 //=======================================================================
1319
1320 bool   HYBRIDPlugin_Hypothesis::DefaultKeepFiles()
1321 {
1322   return false;
1323 }
1324
1325 //=======================================================================
1326 //function : DefaultRemoveLogOnSuccess
1327 //=======================================================================
1328
1329 bool   HYBRIDPlugin_Hypothesis::DefaultRemoveLogOnSuccess()
1330 {
1331   return false;
1332 }
1333
1334
1335 //=======================================================================
1336 //function : DefaultVerboseLevel
1337 //=======================================================================
1338
1339 short  HYBRIDPlugin_Hypothesis::DefaultVerboseLevel()
1340 {
1341   return 10;
1342 }
1343
1344 //=======================================================================
1345 //function : DefaultToCreateNewNodes
1346 //=======================================================================
1347
1348 bool HYBRIDPlugin_Hypothesis::DefaultToCreateNewNodes()
1349 {
1350   return true;
1351 }
1352
1353 //=======================================================================
1354 //function : DefaultToUseBoundaryRecoveryVersion
1355 //=======================================================================
1356
1357 bool HYBRIDPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion()
1358 {
1359   return false;
1360 }
1361
1362 //=======================================================================
1363 //function : DefaultToUseFEMCorrection
1364 //=======================================================================
1365
1366 bool HYBRIDPlugin_Hypothesis::DefaultToUseFEMCorrection()
1367 {
1368   return false;
1369 }
1370
1371 //=======================================================================
1372 //function : DefaultToRemoveCentralPoint
1373 //=======================================================================
1374
1375 bool HYBRIDPlugin_Hypothesis::DefaultToRemoveCentralPoint()
1376 {
1377   return false;
1378 }
1379
1380 //=======================================================================
1381 //function : DefaultGradation
1382 //=======================================================================
1383
1384 double HYBRIDPlugin_Hypothesis::DefaultGradation()
1385 {
1386   return 1.05;
1387 }
1388
1389 //=======================================================================
1390 //function : DefaultStandardOutputLog
1391 //=======================================================================
1392
1393 bool HYBRIDPlugin_Hypothesis::DefaultStandardOutputLog()
1394 {
1395   return false;
1396 }
1397
1398 // //=======================================================================
1399 // //function : DefaultID2SizeMap
1400 // //=======================================================================
1401 // 
1402 // HYBRIDPlugin_Hypothesis::TID2SizeMap HYBRIDPlugin_Hypothesis::DefaultID2SizeMap()
1403 // {
1404 //   return HYBRIDPlugin_Hypothesis::TID2SizeMap();
1405 // }
1406
1407 //=======================================================================
1408 //function : DefaultAddMultinormals
1409 //=======================================================================
1410 bool HYBRIDPlugin_Hypothesis::DefaultAddMultinormals()
1411 {
1412   return false;
1413 }
1414
1415 //=======================================================================
1416 //function : DefaultSmoothNormals
1417 //=======================================================================
1418 bool HYBRIDPlugin_Hypothesis::DefaultSmoothNormals()
1419 {
1420   return false;
1421 }
1422
1423 //=======================================================================
1424 //function : DefaultHeightFirstLayer
1425 //=======================================================================
1426 double HYBRIDPlugin_Hypothesis::DefaultHeightFirstLayer()
1427 {
1428   return 0.0; //or epsilon?
1429 }
1430
1431 //=======================================================================
1432 //function : DefaultBoundaryLayersProgression
1433 //=======================================================================
1434 double HYBRIDPlugin_Hypothesis::DefaultBoundaryLayersProgression()
1435 {
1436   return 1.0;
1437 }
1438
1439 //=======================================================================
1440 //function : DefaultCoreSize
1441 //=======================================================================
1442 double HYBRIDPlugin_Hypothesis::DefaultCoreSize()
1443 {
1444   return 0.0;
1445 }
1446
1447 //=======================================================================
1448 //function : DefaultMultinormalsAngle
1449 //=======================================================================
1450 double HYBRIDPlugin_Hypothesis::DefaultMultinormalsAngle()
1451 {
1452   return 30.0;
1453 }
1454
1455 //=======================================================================
1456 //function : DefaultNbOfBoundaryLayers
1457 //=======================================================================
1458 short HYBRIDPlugin_Hypothesis::DefaultNbOfBoundaryLayers()
1459 {
1460   return 1;
1461 }
1462
1463 //=======================================================================
1464 //function : SaveTo
1465 //=======================================================================
1466
1467 std::ostream & HYBRIDPlugin_Hypothesis::SaveTo(std::ostream & save)
1468 {
1469   save << (int) myBoundaryLayersGrowth << " ";
1470   save << (int) myElementGeneration << " ";
1471   save << (int) myAddMultinormals << " ";
1472   save << (int) mySmoothNormals << " ";
1473   save << (int) myLayersOnAllWrap << " ";
1474
1475   save << myNbOfBoundaryLayers << " ";
1476   save << myHeightFirstLayer << " ";
1477   save << myBoundaryLayersProgression << " ";
1478   save << myMultinormalsAngle << " ";
1479
1480   save << (int) myKeepFiles << " ";
1481   save << myWorkingDirectory << " ";
1482   save << myVerboseLevel << " ";
1483   save << myCoreSize << " ";
1484
1485   // if (!myTextOption.empty()) {
1486   //   save << "__OPTIONS_BEGIN__ ";
1487   //   save << myTextOption << " ";
1488   //   save << "__OPTIONS_END__ ";
1489   // }
1490
1491
1492   THYBRIDEnforcedVertexList::iterator it  = _enfVertexList.begin();
1493   if (it != _enfVertexList.end()) {
1494     save << " " << "__ENFORCED_VERTICES_BEGIN__ ";
1495     for ( ; it != _enfVertexList.end(); ++it ) {
1496       THYBRIDEnforcedVertex *enfVertex = (*it);
1497       save << " " << "__BEGIN_VERTEX__";
1498       if (!enfVertex->name.empty()) {
1499         save << " " << "__BEGIN_NAME__";
1500         save << " " << enfVertex->name;
1501         save << " " << "__END_NAME__";
1502       }
1503       if (!enfVertex->geomEntry.empty()) {
1504         save << " " << "__BEGIN_ENTRY__";
1505         save << " " << enfVertex->geomEntry;
1506         save << " " << enfVertex->isCompound;
1507         save << " " << "__END_ENTRY__";
1508       }
1509       if (!enfVertex->groupName.empty()) {
1510         save << " " << "__BEGIN_GROUP__";
1511         save << " " << enfVertex->groupName;
1512         save << " " << "__END_GROUP__";
1513       }
1514       if (enfVertex->coords.size()) {
1515         save << " " << "__BEGIN_COORDS__";
1516         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
1517           save << " " << enfVertex->coords[i];
1518         save << " " << "__END_COORDS__";
1519       }
1520       save << " " << "__BEGIN_SIZE__";
1521       save << " " << enfVertex->size;
1522       save << " " << "__END_SIZE__";
1523       save << " " << "__END_VERTEX__";
1524     }
1525     save << " " << "__ENFORCED_VERTICES_END__ ";
1526   }
1527
1528   THYBRIDEnforcedMeshList::iterator it_mesh  = _enfMeshList.begin();
1529   if (it_mesh != _enfMeshList.end()) {
1530     save << " " << "__ENFORCED_MESHES_BEGIN__ ";
1531     for ( ; it_mesh != _enfMeshList.end(); ++it_mesh ) {
1532       THYBRIDEnforcedMesh *enfMesh = (*it_mesh);
1533       save << " " << "__BEGIN_ENF_MESH__";
1534
1535       save << " " << "__BEGIN_NAME__";
1536       save << " " << enfMesh->name;
1537       save << " " << "__END_NAME__";
1538
1539       save << " " << "__BEGIN_ENTRY__";
1540       save << " " << enfMesh->entry;
1541       save << " " << "__END_ENTRY__";
1542
1543       save << " " << "__BEGIN_ELEM_TYPE__";
1544       save << " " << (int)enfMesh->elementType;
1545       save << " " << "__END_ELEM_TYPE__";
1546
1547       if (!enfMesh->groupName.empty()) {
1548         save << " " << "__BEGIN_GROUP__";
1549         save << " " << enfMesh->groupName;
1550         save << " " << "__END_GROUP__";
1551       }
1552       save << " " << "__PERSIST_ID__";
1553       save << " " << enfMesh->persistID;
1554       save << " " << "__END_ENF_MESH__";
1555       std::cout << "Saving of enforced mesh " << enfMesh->name.c_str() << " done" << std::endl;
1556     }
1557     save << " "  << "__ENFORCED_MESHES_END__ ";
1558   }
1559
1560   save << " " << myFacesWithLayers.size();
1561   for ( size_t i = 0; i < myFacesWithLayers.size(); ++i )
1562     save << " " << myFacesWithLayers[i];
1563
1564   save << " " << myFacesWithImprinting.size();
1565   for ( size_t i = 0; i < myFacesWithImprinting.size(); ++i )
1566     save << " " << myFacesWithImprinting[i];
1567
1568   save << " " << myFacesWithSnapping.size();
1569   for ( size_t i = 0; i < myFacesWithSnapping.size(); ++i )
1570     save << " " << myFacesWithSnapping[i];
1571
1572   // New options in 2.9.6 (issue #17784)
1573
1574   save << " " << myHeightIsRelative;
1575   save << " " << myBoundaryLayersMaxElemAngle;
1576   save << " " << myCollisionMode;
1577   save << " " << myGradation;
1578   save << " " << myOptimizationLevel;
1579
1580   save << " " << _option2value.size();
1581   TOptionValues::iterator o2v = _option2value.begin();
1582   for ( ; o2v != _option2value.end(); ++o2v )
1583     save << " -" << o2v->first << " -" << o2v->second;
1584
1585   save << " " << _customOption2value.size();
1586   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
1587     save << " -" << o2v->first << " -" << o2v->second;
1588
1589   return save;
1590 }
1591
1592 //=======================================================================
1593 //function : LoadFrom
1594 //=======================================================================
1595
1596 std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load)
1597 {
1598   bool isOK = true;
1599   int i;
1600   double d;
1601
1602   isOK = static_cast<bool>(load >> i);
1603   if (isOK)
1604     myBoundaryLayersGrowth = (short) i;
1605   else
1606     load.clear(ios::badbit | load.rdstate());
1607
1608   isOK = static_cast<bool>(load >> i);
1609   if (isOK)
1610     myElementGeneration = (short) i;
1611   else
1612     load.clear(ios::badbit | load.rdstate());
1613
1614   isOK = static_cast<bool>(load >> i);
1615   if (isOK)
1616     myAddMultinormals = (bool) i;
1617   else
1618     load.clear(ios::badbit | load.rdstate());
1619
1620   isOK = static_cast<bool>(load >> i);
1621   if (isOK)
1622     mySmoothNormals = (bool) i;
1623   else
1624     load.clear(ios::badbit | load.rdstate());
1625
1626   isOK = static_cast<bool>(load >> i);
1627   if (isOK)
1628     myLayersOnAllWrap = (bool) i;
1629   else
1630     load.clear(ios::badbit | load.rdstate());
1631
1632   isOK = static_cast<bool>(load >> i);
1633   if (isOK)
1634     myNbOfBoundaryLayers = (short) i;
1635   else
1636     load.clear(ios::badbit | load.rdstate());
1637
1638   isOK = static_cast<bool>(load >> d);
1639   if (isOK)
1640     myHeightFirstLayer = d;
1641   else
1642     load.clear(ios::badbit | load.rdstate());
1643
1644   isOK = static_cast<bool>(load >> d);
1645   if (isOK)
1646     myBoundaryLayersProgression = d;
1647   else
1648     load.clear(ios::badbit | load.rdstate());
1649
1650   isOK = static_cast<bool>(load >> d);
1651   if (isOK)
1652     myMultinormalsAngle = d;
1653   else
1654     load.clear(ios::badbit | load.rdstate());
1655
1656   isOK = static_cast<bool>(load >> i);
1657   if (isOK)
1658     myKeepFiles = (bool) i;
1659   else
1660     load.clear(ios::badbit | load.rdstate());
1661
1662   isOK = static_cast<bool>(load >> myWorkingDirectory);
1663   if (isOK) {
1664     if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty
1665       myKeepFiles = false;
1666       myWorkingDirectory.clear();
1667     }
1668     else if ( myWorkingDirectory == "1" ) {
1669       myKeepFiles = true;
1670       myWorkingDirectory.clear();
1671     }
1672   }
1673   else
1674     load.clear(ios::badbit | load.rdstate());
1675
1676   isOK = static_cast<bool>(load >> i);
1677   if (isOK)
1678     myVerboseLevel = (short) i;
1679   else
1680     load.clear(ios::badbit | load.rdstate());
1681
1682   isOK = static_cast<bool>(load >> d);
1683   if (isOK)
1684     myCoreSize = d;
1685   else
1686     load.clear(ios::badbit | load.rdstate());
1687
1688   std::string separator;
1689   bool hasOptions = false;
1690   bool hasEnforcedVertices = false;
1691   bool hasEnforcedMeshes = false;
1692   isOK = static_cast<bool>(load >> separator);
1693
1694   if (isOK) {
1695     if (separator == "__OPTIONS_BEGIN__")
1696       hasOptions = true;
1697     else if (separator == "__ENFORCED_VERTICES_BEGIN__")
1698       hasEnforcedVertices = true;
1699     else if (separator == "__ENFORCED_MESHES_BEGIN__")
1700       hasEnforcedMeshes = true;
1701   }
1702
1703   if (hasOptions) {
1704     std::string txt;
1705     while (isOK) {
1706       isOK = static_cast<bool>(load >> txt);
1707       if (isOK) {
1708         if (txt == "__OPTIONS_END__") {
1709           isOK = false;
1710           break;
1711         }
1712         // myTextOption += txt;
1713       }
1714     }
1715   }
1716
1717   if (hasOptions) {
1718     isOK = static_cast<bool>(load >> separator);
1719     if (isOK && separator == "__ENFORCED_VERTICES_BEGIN__")
1720       hasEnforcedVertices = true;
1721     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1722       hasEnforcedMeshes = true;
1723   }
1724
1725   if (hasEnforcedVertices) {
1726     std::string txt, name, entry, groupName;
1727     double size, coords[3];
1728     bool isCompound;
1729     bool hasCoords = false;
1730     isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1731     while (isOK) {
1732       if (txt == "__ENFORCED_VERTICES_END__")
1733         isOK = false;
1734
1735       THYBRIDEnforcedVertex *enfVertex = new THYBRIDEnforcedVertex();
1736       while (isOK) {
1737         isOK = static_cast<bool>(load >> txt);
1738         if (txt == "__END_VERTEX__") {
1739           enfVertex->name = name;
1740           enfVertex->geomEntry = entry;
1741           enfVertex->isCompound = isCompound;
1742           enfVertex->groupName = groupName;
1743           enfVertex->coords.clear();
1744           if (hasCoords)
1745             enfVertex->coords.assign(coords,coords+3);
1746
1747           _enfVertexList.insert(enfVertex);
1748
1749           if (enfVertex->coords.size())
1750             _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
1751           if (!enfVertex->geomEntry.empty())
1752             _geomEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
1753
1754           name.clear();
1755           entry.clear();
1756           groupName.clear();
1757           hasCoords = false;
1758           isOK = false;
1759         }
1760
1761         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1762           while (isOK && (txt != "__END_NAME__")) {
1763             isOK = static_cast<bool>(load >> txt);
1764             if (txt != "__END_NAME__") {
1765               if (!name.empty())
1766                 name += " ";
1767               name += txt;
1768             }
1769           }
1770         }
1771
1772         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1773           isOK = static_cast<bool>(load >> entry);
1774           isOK = static_cast<bool>(load >> isCompound);
1775           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1776           if (txt != "__END_ENTRY__")
1777             throw std::exception();
1778         }
1779
1780         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1781           while (isOK && (txt != "__END_GROUP__")) {
1782             isOK = static_cast<bool>(load >> txt);
1783             if (txt != "__END_GROUP__") {
1784               if (!groupName.empty())
1785                 groupName += " ";
1786               groupName += txt;
1787             }
1788           }
1789         }
1790
1791         if (txt == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
1792           hasCoords = true;
1793           isOK = static_cast<bool>(load >> coords[0] >> coords[1] >> coords[2]);
1794           isOK = static_cast<bool>(load >> txt); // __END_COORDS__
1795           if (txt != "__END_COORDS__")
1796             throw std::exception();
1797         }
1798
1799         if (txt == "__BEGIN_SIZE__") {  // __BEGIN_ENTRY__
1800           isOK = static_cast<bool>(load >> size);
1801           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1802           if (txt != "__END_SIZE__") {
1803             throw std::exception();
1804           }
1805         }
1806       }
1807       isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1808     }
1809   }
1810
1811   if (hasEnforcedVertices) {
1812     isOK = static_cast<bool>(load >> separator);
1813     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1814       hasEnforcedMeshes = true;
1815   }
1816
1817   if (hasEnforcedMeshes) {
1818     std::string txt, name, entry, groupName;
1819     int elementType = -1, persistID = -1;
1820     isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1821     while (isOK) {
1822       //                if (isOK) {
1823       if (txt == "__ENFORCED_MESHES_END__")
1824         isOK = false;
1825
1826       THYBRIDEnforcedMesh *enfMesh = new THYBRIDEnforcedMesh();
1827       while (isOK) {
1828         isOK = static_cast<bool>(load >> txt);
1829         if (txt == "__END_ENF_MESH__") {
1830           enfMesh->name = name;
1831           enfMesh->entry = entry;
1832           enfMesh->elementType = (SMESH::ElementType)elementType;
1833           enfMesh->groupName = groupName;
1834           enfMesh->persistID = persistID;
1835
1836           _enfMeshList.insert(enfMesh);
1837           std::cout << "Restoring of enforced mesh " <<name  << " done" << std::endl;
1838
1839           name.clear();
1840           entry.clear();
1841           elementType = -1;
1842           groupName.clear();
1843           persistID = -1;
1844           isOK = false;
1845         }
1846
1847         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1848           while (isOK && (txt != "__END_NAME__")) {
1849             isOK = static_cast<bool>(load >> txt);
1850             if (txt != "__END_NAME__") {
1851               if (!name.empty())
1852                 name += " ";
1853               name += txt;
1854             }
1855           }
1856         }
1857
1858         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1859           isOK = static_cast<bool>(load >> entry);
1860           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1861           if (txt != "__END_ENTRY__")
1862             throw std::exception();
1863         }
1864
1865         if (txt == "__BEGIN_ELEM_TYPE__") {  // __BEGIN_ELEM_TYPE__
1866           isOK = static_cast<bool>(load >> elementType);
1867           isOK = static_cast<bool>(load >> txt); // __END_ELEM_TYPE__
1868           if (txt != "__END_ELEM_TYPE__")
1869             throw std::exception();
1870         }
1871
1872         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1873           while (isOK && (txt != "__END_GROUP__")) {
1874             isOK = static_cast<bool>(load >> txt);
1875             if (txt != "__END_GROUP__") {
1876               if (!groupName.empty())
1877                 groupName += " ";
1878               groupName += txt;
1879             }
1880           } // while
1881         } // if
1882
1883         if (txt == "__PERSIST_ID__") {
1884           isOK = static_cast<bool>(load >> persistID);
1885         }
1886         std::cout << "isOK: " << isOK << std::endl;
1887       } // while
1888       //                } // if
1889       isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1890     } // while
1891   } // if
1892
1893   if ( hasEnforcedMeshes )
1894     isOK = static_cast<bool>(load >> separator);
1895
1896   if ( isOK )
1897   {
1898     i = atoi( separator.c_str() );
1899     isOK = ( i >= 0 );
1900     if ( isOK )
1901     {
1902       myFacesWithLayers.reserve( i );
1903       while (( myFacesWithLayers.size() < myFacesWithLayers.capacity() ) &&
1904              ( isOK = static_cast<bool>(load >> i)) )
1905         myFacesWithLayers.push_back( i );
1906     }
1907   }
1908
1909   isOK = static_cast<bool>(load >> separator);
1910   if ( isOK )
1911   {
1912     i = atoi( separator.c_str() );
1913     isOK = ( i >= 0 );
1914     if ( isOK )
1915     {
1916       myFacesWithImprinting.reserve( i );
1917       while (( myFacesWithImprinting.size() < myFacesWithImprinting.capacity() ) &&
1918              ( isOK = static_cast<bool>(load >> i)) )
1919         myFacesWithImprinting.push_back( i );
1920     }
1921   }
1922
1923   isOK = static_cast<bool>(load >> separator);
1924   if ( isOK )
1925   {
1926     i = atoi( separator.c_str() );
1927     isOK = ( i >= 0 );
1928     if ( isOK )
1929     {
1930       myFacesWithSnapping.reserve( i );
1931       while (( myFacesWithSnapping.size() < myFacesWithSnapping.capacity() ) &&
1932              ( isOK = static_cast<bool>(load >> i)) )
1933         myFacesWithSnapping.push_back( i );
1934     }
1935   }
1936
1937   // New options in 2.9.6 (issue #17784)
1938
1939   if ( static_cast<bool>(load >> i))
1940   {
1941     myHeightIsRelative = (bool) i;
1942     load >> myBoundaryLayersMaxElemAngle;
1943     load >> myCollisionMode;
1944     load >> myGradation;
1945     load >> myOptimizationLevel;
1946
1947     std::string option, value;
1948     if ( static_cast<bool>( load >> i ) && i >= 0 )
1949     {
1950       for ( int nbRead = 0; nbRead < i; ++nbRead )
1951       {
1952         load >> option >> value;
1953         _option2value[ std::string( option, 1 )] = std::string( value, 1 );
1954       }
1955     }
1956     if ( static_cast<bool>( load >> i ) && i >= 0 )
1957     {
1958       for ( int nbRead = 0; nbRead < i; ++nbRead )
1959       {
1960         load >> option >> value;
1961         _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
1962       }
1963     }
1964   }
1965
1966   return load;
1967 }
1968
1969 //=======================================================================
1970 //function : SetParametersByMesh
1971 //=======================================================================
1972
1973 bool HYBRIDPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&)
1974 {
1975   return false;
1976 }
1977
1978 //================================================================================
1979 /*!
1980  * \brief Sets myToMakeGroupsOfDomains depending on whether theMesh is on shape or not
1981  */
1982 //================================================================================
1983
1984 bool HYBRIDPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
1985                                                      const SMESH_Mesh* /*theMesh*/)
1986 {
1987   myToMakeGroupsOfDomains = ( !dflts._shape || dflts._shape->IsNull() );
1988   return true;
1989 }
1990
1991 //================================================================================
1992 /*!
1993  * \brief Return command to run hybrid mesher excluding file prefix (-f)
1994  */
1995 //================================================================================
1996
1997 std::string HYBRIDPlugin_Hypothesis::CommandToRun(const HYBRIDPlugin_Hypothesis* hyp)
1998 {
1999   SMESH_Comment cmd = GetExeName();
2000   // check if any option is overridden by hyp->_option2value
2001   bool p_h     = ( hyp && hyp->HasOptionDefined("-h"));
2002   bool p_v     = ( hyp && hyp->HasOptionDefined("-v"));
2003   bool p_blsd  = ( hyp && hyp->HasOptionDefined("--normal_direction"));
2004   bool p_hotfl = ( hyp && hyp->HasOptionDefined("--boundary_layer_global_initial_height"));
2005   bool p_nobl  = ( hyp && hyp->HasOptionDefined("--number_of_boundary_layers"));
2006   bool p_blgp  = ( hyp && hyp->HasOptionDefined("--boundary_layer_geometric_progression"));
2007   bool p_eg    = ( hyp && hyp->HasOptionDefined("--element_generation"));
2008   bool p_cs    = ( hyp && hyp->HasOptionDefined("--global_physical_size"));
2009
2010   bool nolayers = false;
2011   bool layersOnAllWrap = hyp ? hyp->myLayersOnAllWrap : DefaultLayersOnAllWrap();
2012
2013   //help mode
2014   if ( p_h ) {
2015     cmd << " --help ";
2016 #ifdef WIN32
2017     cmd << " < NUL";
2018 #endif
2019     std::cout << "!!!!! CommandToRun help only !!!! " << cmd << std::endl;
2020     return cmd;
2021   }
2022
2023   if ( !p_v && hyp )
2024     cmd << " --verbose " << hyp->myVerboseLevel;
2025
2026   //no layers?
2027   if ( !p_nobl && hyp ) {
2028     if ( hyp->myNbOfBoundaryLayers < 1 ) nolayers = true;
2029   }
2030   if ( !p_hotfl && hyp ) {
2031     if ( hyp->myHeightFirstLayer < 1e-50 ) nolayers = true;
2032   }
2033
2034   if ( !p_blsd && hyp ) {
2035     if ( hyp->myBoundaryLayersGrowth >= 0 && hyp->myBoundaryLayersGrowth <= 1 ) {
2036       const char* value[] = { "-1" , "1" }; // -1 == inside
2037       cmd << " --normal_direction " << value[ hyp->myBoundaryLayersGrowth ];
2038     }
2039   }
2040
2041   if ( !p_hotfl && hyp ) {
2042     cmd << " --boundary_layer_global_initial_height " << hyp->myHeightFirstLayer;
2043   }
2044   if ( hyp && hyp->GetHeightIsRelative() )
2045     cmd << " --boundary_layer_height_relative_to_local_surface_size yes";
2046
2047   if ( !p_nobl && hyp ) {
2048     cmd << " --number_of_boundary_layers " << ( nolayers ? 0 :  hyp->myNbOfBoundaryLayers );
2049   }
2050
2051   if ( !p_blgp && hyp ) {
2052     cmd << " --boundary_layer_geometric_progression " << hyp->myBoundaryLayersProgression;
2053   }
2054
2055   if ( !nolayers && hyp )
2056   {
2057     cmd << " --boundary_layer_size_mode " << ( layersOnAllWrap ? "global" : "local" );
2058
2059     if ( hyp->GetBoundaryLayersMaxElemAngle() != hyp->DefaultBoundaryLayersMaxElemAngle() )
2060       cmd << " --boundary_layer_max_element_angle "
2061           << SMESH_Comment( hyp->GetBoundaryLayersMaxElemAngle() );
2062
2063     if ( !layersOnAllWrap )
2064     {
2065       // faces with layers
2066       const std::vector<int>& faceLayersIDs = hyp->GetFacesWithLayers();
2067       if ( !faceLayersIDs.empty() )
2068         cmd << " --boundary_layer_surface_tags ";
2069       for ( size_t i = 0; i < faceLayersIDs.size(); ++i )
2070         cmd << faceLayersIDs[i] << ",";
2071       if ( !faceLayersIDs.empty() )
2072         cmd << " --boundary_layer_initial_height_on_surface_tags ";
2073       for ( size_t i = 0; i < faceLayersIDs.size(); ++i )
2074         cmd << hyp->myHeightFirstLayer << ",";
2075
2076       // faces with imprinting
2077       const std::vector<int>& faceImprintingIDs = hyp->GetFacesWithImprinting();
2078       if ( !faceImprintingIDs.empty() )
2079         cmd << " --boundary_layer_imprinting yes --boundary_layer_imprinting_tags ";
2080       for ( size_t i = 0; i < faceImprintingIDs.size(); ++i )
2081         cmd << faceImprintingIDs[i] << ",";
2082
2083       // faces with snapping
2084       const std::vector<int>& faceSnappingIDs = hyp->GetFacesWithSnapping();
2085       if ( !faceSnappingIDs.empty() )
2086         cmd << " --boundary_layer_snapping yes --boundary_layer_snapping_tags ";
2087       for ( size_t i = 0; i < faceSnappingIDs.size(); ++i )
2088         cmd << faceSnappingIDs[i] << ",";
2089     }
2090   }
2091
2092   if ( !p_eg && hyp ) {
2093     if ( hyp->myElementGeneration >= 0 && hyp->myElementGeneration <= 3 ) {
2094       const char* value[] = { "tetra_dominant" , "hexa_dominant", "cartesian_core", "extrusion_only" };
2095       cmd << " --element_generation " << value[ hyp->myElementGeneration ];
2096     }
2097   }
2098
2099   if ( !p_cs && hyp ) {
2100     if ( hyp->myCoreSize > 0 ) {
2101       cmd << " --global_physical_size " << hyp->myCoreSize;
2102     }
2103   }
2104
2105   if ( hyp )
2106   {
2107     // options as text
2108     std::string option, value;
2109     bool isDefault;
2110     const TOptionValues* options[] = { & hyp->_option2value, & hyp->_customOption2value };
2111     for ( int iOp = 0; iOp < 2; ++iOp )
2112     {
2113       TOptionValues::const_iterator o2v = options[iOp]->begin();
2114       for ( ; o2v != options[iOp]->end(); ++o2v )
2115       {
2116         option = o2v->first;
2117         value = hyp->GetOptionValue( option, &isDefault );
2118
2119         if ( isDefault )
2120           continue;
2121         if ( value.empty() )
2122         {
2123           if ( hyp->_defaultOptionValues.count( option ))
2124             continue; // non-custom option with no value
2125         }
2126         if ( option[0] != '-' )
2127           cmd << " --";
2128         else
2129           cmd << " ";
2130         cmd << option << " " << value;
2131       }
2132     }
2133   }
2134
2135 #ifdef WIN32
2136   cmd << " < NUL";
2137 #endif
2138   //std::cout << "!!!!!CommandToRun end " << cmd << std::endl;
2139
2140   return cmd;
2141 }
2142
2143 //================================================================================
2144 /*!
2145  * \brief Return a unique file name
2146  */
2147 //================================================================================
2148
2149 std::string HYBRIDPlugin_Hypothesis::GetFileName(const HYBRIDPlugin_Hypothesis* hyp)
2150 {
2151   std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory();
2152   const char lastChar = *aTmpDir.rbegin();
2153 #ifdef WIN32
2154   if(lastChar != '\\') aTmpDir+='\\';
2155 #else
2156   if(lastChar != '/') aTmpDir+='/';
2157 #endif
2158
2159   SMESH_Comment aGenericName = aTmpDir;
2160   aGenericName << "HYBRID_";
2161   aGenericName << getpid();
2162   aGenericName << "_";
2163   aGenericName << Abs((Standard_Integer)(long) aGenericName.c_str());
2164
2165   return aGenericName;
2166 }
2167
2168 //================================================================================
2169 /*
2170  * Return the name of executable
2171  */
2172 //================================================================================
2173
2174 std::string HYBRIDPlugin_Hypothesis::GetExeName()
2175 {
2176   //call mg-hybrid.bash is script which assumes new project version(s) mg-hybrid.exe in the prerequisite base and special? licence.
2177 #ifdef WIN32
2178   return "mg-hybrid.exe";
2179 #else
2180   return "mg-hybrid.bash";
2181 #endif
2182 }
2183
2184 //=============================================================================
2185 void HYBRIDPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
2186                                              const std::string& optionValue)
2187 {
2188   TOptionValues::iterator op_val = _option2value.find(optionName);
2189   if (op_val == _option2value.end())
2190   {
2191     op_val = _customOption2value.find( optionName );
2192     if ( op_val == _customOption2value.end() || op_val->second != optionValue )
2193       NotifySubMeshesHypothesisModification();
2194     _customOption2value[ optionName ] = optionValue;
2195     return;
2196   }
2197
2198   if (op_val->second != optionValue)
2199   {
2200     const char* ptr = optionValue.c_str();
2201     // strip white spaces
2202     while (ptr[0] == ' ')
2203       ptr++;
2204     int i = strlen(ptr);
2205     while (i != 0 && ptr[i - 1] == ' ')
2206       i--;
2207     // check value type
2208     bool typeOk = true;
2209     std::string typeName;
2210     if (i == 0) {
2211       // empty string
2212     } else if (_charOptions.count(optionName)) {
2213       // do not check strings
2214     } else if (_doubleOptions.count(optionName)) {
2215       // check if value is double
2216       ToDbl(ptr, &typeOk);
2217       typeName = "real";
2218     } else if (_boolOptions.count(optionName)) {
2219       // check if value is bool
2220       ToBool(ptr, &typeOk);
2221       typeName = "bool";
2222     } else {
2223       // check if value is int
2224       ToInt(ptr, &typeOk);
2225       typeName = "integer";
2226     }
2227     if ( typeOk ) // check some specific values ?
2228     {
2229     }
2230     if ( !typeOk )
2231     {
2232       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
2233       throw std::invalid_argument(msg);
2234     }
2235     std::string value( ptr, i );
2236     if ( _defaultOptionValues[ optionName ] == value )
2237       value.clear();
2238
2239     op_val->second = value;
2240
2241     NotifySubMeshesHypothesisModification();
2242   }
2243 }
2244
2245 //=============================================================================
2246 //! Return option value. If isDefault provided, it can be a default value,
2247 //  then *isDefault == true. If isDefault is not provided, the value will be
2248 //  empty if it equals a default one.
2249 std::string HYBRIDPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
2250                                                     bool*              isDefault) const
2251 {
2252   TOptionValues::const_iterator op_val = _option2value.find(optionName);
2253   if (op_val == _option2value.end())
2254   {
2255     op_val = _customOption2value.find(optionName);
2256     if (op_val == _customOption2value.end())
2257     {
2258       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
2259       throw std::invalid_argument(msg);
2260     }
2261   }
2262   std::string val = op_val->second;
2263   if ( isDefault ) *isDefault = ( val.empty() );
2264
2265   if ( val.empty() && isDefault )
2266   {
2267     op_val = _defaultOptionValues.find( optionName );
2268     if (op_val != _defaultOptionValues.end())
2269       val = op_val->second;
2270   }
2271   return val;
2272 }
2273
2274
2275 //=============================================================================
2276 bool HYBRIDPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
2277 {
2278   bool isDefault = false;
2279   try
2280   {
2281     GetOptionValue( optionName, &isDefault );
2282   }
2283   catch ( std::invalid_argument& )
2284   {
2285     return false;
2286   }
2287   return !isDefault;
2288 }
2289
2290 //=============================================================================
2291 void HYBRIDPlugin_Hypothesis::ClearOption(const std::string& optionName)
2292 {
2293   TOptionValues::iterator op_val = _customOption2value.find(optionName);
2294   if (op_val != _customOption2value.end())
2295     _customOption2value.erase(op_val);
2296   else {
2297     op_val = _option2value.find(optionName);
2298     if (op_val != _option2value.end())
2299       op_val->second.clear();
2300   }
2301 }
2302
2303 //=============================================================================
2304 HYBRIDPlugin_Hypothesis::TOptionValues HYBRIDPlugin_Hypothesis::GetOptionValues() const
2305 {
2306   TOptionValues vals;
2307   TOptionValues::const_iterator op_val = _option2value.begin();
2308   for ( ; op_val != _option2value.end(); ++op_val )
2309     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
2310
2311   return vals;
2312 }
2313
2314 //================================================================================
2315 /*!
2316  * \brief Converts a string to a bool
2317  */
2318 //================================================================================
2319
2320 bool HYBRIDPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
2321 {
2322   std::string s = str;
2323   if ( isOk ) *isOk = true;
2324
2325   for ( size_t i = 0; i <= s.size(); ++i )
2326     s[i] = tolower( s[i] );
2327
2328   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
2329     return true;
2330
2331   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
2332     return false;
2333
2334   if ( isOk )
2335     *isOk = false;
2336   else {
2337     std::string msg = "Not a Boolean value:'" + str + "'";
2338     throw std::invalid_argument(msg);
2339   }
2340   return false;
2341 }
2342
2343 //================================================================================
2344 /*!
2345  * \brief Converts a string to a real value
2346  */
2347 //================================================================================
2348
2349 double HYBRIDPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
2350 {
2351   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2352
2353   char * endPtr;
2354   double val = strtod(&str[0], &endPtr);
2355   bool ok = (&str[0] != endPtr);
2356
2357   if ( isOk ) *isOk = ok;
2358
2359   if ( !ok )
2360   {
2361     std::string msg = "Not a real value:'" + str + "'";
2362     throw std::invalid_argument(msg);
2363   }
2364   return val;
2365 }
2366
2367 //================================================================================
2368 /*!
2369  * \brief Converts a string to a integer value
2370  */
2371 //================================================================================
2372
2373 int HYBRIDPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
2374 {
2375   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2376
2377   char * endPtr;
2378   int val = (int)strtol( &str[0], &endPtr, 10);
2379   bool ok = (&str[0] != endPtr);
2380
2381   if ( isOk ) *isOk = ok;
2382
2383   if ( !ok )
2384   {
2385     std::string msg = "Not an integer value:'" + str + "'";
2386     throw std::invalid_argument(msg);
2387   }
2388   return val;
2389 }
2390
2391
2392 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexList HYBRIDPlugin_Hypothesis::GetEnforcedVertices(const HYBRIDPlugin_Hypothesis* hyp)
2393 {
2394   return hyp ? hyp->_GetEnforcedVertices():THYBRIDEnforcedVertexList();
2395 }
2396
2397 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues HYBRIDPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const HYBRIDPlugin_Hypothesis* hyp)
2398 {  
2399   return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): THYBRIDEnforcedVertexCoordsValues();
2400 }
2401
2402 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexEntryValues HYBRIDPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const HYBRIDPlugin_Hypothesis* hyp)
2403 {  
2404   return hyp ? hyp->_GetEnforcedVerticesEntrySize():THYBRIDEnforcedVertexEntryValues();
2405 }
2406
2407 HYBRIDPlugin_Hypothesis::TCoordsHYBRIDEnforcedVertexMap HYBRIDPlugin_Hypothesis::GetEnforcedVerticesByCoords (const HYBRIDPlugin_Hypothesis* hyp)
2408 {  
2409   return hyp ? hyp->_GetEnforcedVerticesByCoords():TCoordsHYBRIDEnforcedVertexMap();
2410 }
2411
2412 HYBRIDPlugin_Hypothesis::TGeomEntryHYBRIDEnforcedVertexMap HYBRIDPlugin_Hypothesis::GetEnforcedVerticesByEntry (const HYBRIDPlugin_Hypothesis* hyp)
2413 {  
2414   return hyp ? hyp->_GetEnforcedVerticesByEntry():TGeomEntryHYBRIDEnforcedVertexMap();
2415 }
2416
2417 HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap HYBRIDPlugin_Hypothesis::GetEnforcedNodes(const HYBRIDPlugin_Hypothesis* hyp)
2418 {
2419   return hyp ? hyp->_GetEnforcedNodes():TIDSortedNodeGroupMap();
2420 }
2421
2422 HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap HYBRIDPlugin_Hypothesis::GetEnforcedEdges(const HYBRIDPlugin_Hypothesis* hyp)
2423 {
2424   return hyp ? hyp->_GetEnforcedEdges():TIDSortedElemGroupMap();
2425 }
2426
2427 HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap HYBRIDPlugin_Hypothesis::GetEnforcedTriangles(const HYBRIDPlugin_Hypothesis* hyp)
2428 {
2429   return hyp ? hyp->_GetEnforcedTriangles():TIDSortedElemGroupMap();
2430 }
2431
2432 HYBRIDPlugin_Hypothesis::TID2SizeMap HYBRIDPlugin_Hypothesis::GetNodeIDToSizeMap(const HYBRIDPlugin_Hypothesis* hyp)
2433 {
2434   return hyp ? hyp->_GetNodeIDToSizeMap():TID2SizeMap();
2435 }
2436
2437 HYBRIDPlugin_Hypothesis::TSetStrings HYBRIDPlugin_Hypothesis::GetGroupsToRemove(const HYBRIDPlugin_Hypothesis* hyp)
2438 {
2439   return hyp ? hyp->_GetGroupsToRemove():TSetStrings();
2440 }