Salome HOME
Copyright update 2021
[plugins/hybridplugin.git] / src / HYBRIDPlugin / HYBRIDPlugin_Hypothesis.cxx
1 // Copyright (C) 2007-2021  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::long_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       CORBA::Long ind = theIDs[i];
951       if (elementType == SMESH::NODE)
952       {
953         const SMDS_MeshNode * node = theMeshDS->FindNode(ind);
954         if (node)
955           theElemSet.insert( node );
956       }
957       else
958       {
959         const SMDS_MeshElement * elem = theMeshDS->FindElement(ind);
960         if (elem)
961           theElemSet.insert( elem );
962       }
963     }
964
965 //   SMDS_ElemIteratorPtr it = theGroup->GetGroupDS()->GetElements();
966 //   while ( it->more() ) 
967 //     theElemSet.insert( it->next() );
968
969   bool added = SetEnforcedElements( theElemSet, elementType, groupName);
970   if (added) {
971     THYBRIDEnforcedMesh* newEnfMesh = new THYBRIDEnforcedMesh();
972     newEnfMesh->name = name;
973     newEnfMesh->entry = entry;
974     newEnfMesh->elementType = elementType;
975     newEnfMesh->groupName = groupName;
976     
977     THYBRIDEnforcedMeshList::iterator it = _enfMeshList.find(newEnfMesh);
978     if (it == _enfMeshList.end()) {
979       _entryEnfMeshMap[entry].insert(newEnfMesh);
980       _enfMeshList.insert(newEnfMesh);
981     }
982   }
983   return added;
984 }
985
986 //=======================================================================
987 //function : SetEnforcedElements
988 //=======================================================================
989 bool HYBRIDPlugin_Hypothesis::SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, std::string groupName)
990 {
991   TIDSortedElemSet::const_iterator it = theElemSet.begin();
992   const SMDS_MeshElement* elem;
993   const SMDS_MeshNode* node;
994   bool added = true;
995   std::pair<TIDSortedNodeGroupMap::iterator,bool> nodeRet;
996   std::pair<TIDSortedElemGroupMap::iterator,bool> elemRet;
997
998   for (;it != theElemSet.end();++it)
999   {
1000     elem = (*it);
1001     switch (elementType) {
1002       case SMESH::NODE:
1003         node = dynamic_cast<const SMDS_MeshNode*>(elem);
1004         if (node) {
1005           nodeRet = _enfNodes.insert(make_pair(node,groupName));
1006           added = added && nodeRet.second;
1007           std::string msg = added ? "yes":"no";
1008         }
1009         else {
1010           SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
1011           for (;nodeIt->more();) {
1012             node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
1013             nodeRet = _enfNodes.insert(make_pair(node,groupName));
1014             added = added && nodeRet.second;
1015           }
1016 //          added = true;s
1017         }
1018         break;
1019       case SMESH::EDGE:
1020         if (elem->GetType() == SMDSAbs_Edge) {
1021           elemRet = _enfEdges.insert(make_pair(elem,groupName));
1022           added = added && elemRet.second;
1023         }
1024         break;
1025       case SMESH::FACE:
1026         if (elem->GetType() == SMDSAbs_Face)
1027         {
1028           if (elem->NbCornerNodes() == 3) {
1029             elemRet = _enfTriangles.insert(make_pair(elem,groupName));
1030             added = added && elemRet.second;
1031           }
1032         }
1033         break;
1034       default:
1035         break;
1036     };
1037   }
1038   if (added)
1039     NotifySubMeshesHypothesisModification();
1040   return added;
1041 }
1042
1043
1044 //=======================================================================
1045 //function : GetEnforcedVertex
1046 //=======================================================================
1047
1048 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex* HYBRIDPlugin_Hypothesis::GetEnforcedVertex(double x, double y, double z)
1049 {
1050   std::vector<double> coord(3);
1051   coord[0] = x;
1052   coord[1] = y;
1053   coord[2] = z;
1054   if (_coordsEnfVertexMap.count(coord)>0)
1055     return _coordsEnfVertexMap[coord];
1056   std::ostringstream msg ;
1057   msg << "No enforced vertex at " << x << ", " << y << ", " << z;
1058   throw std::invalid_argument(msg.str());
1059 }
1060
1061 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertex* HYBRIDPlugin_Hypothesis::GetEnforcedVertex(const std::string theEntry)
1062 {
1063   if (_geomEntryEnfVertexMap.count(theEntry)>0)
1064     return _geomEntryEnfVertexMap[theEntry];
1065   
1066   std::ostringstream msg ;
1067   msg << "No enforced vertex with entry " << theEntry;
1068   throw std::invalid_argument(msg.str());
1069 }
1070
1071 //=======================================================================
1072 //function : RemoveEnforcedVertex
1073 //=======================================================================
1074
1075 bool HYBRIDPlugin_Hypothesis::RemoveEnforcedVertex(double x, double y, double z, const std::string theEntry)
1076 {
1077   bool toNotify = false;
1078   std::ostringstream msg;
1079   THYBRIDEnforcedVertex *oldEnfVertex;
1080   std::vector<double> coords(3);
1081   coords[0] = x;
1082   coords[1] = y;
1083   coords[2] = z;
1084   
1085   // check that enf vertex with given enf vertex entry exists
1086   TGeomEntryHYBRIDEnforcedVertexMap::iterator it_enfVertexEntry = _geomEntryEnfVertexMap.find(theEntry);
1087   if (it_enfVertexEntry != _geomEntryEnfVertexMap.end()) {
1088     // Success
1089     oldEnfVertex = it_enfVertexEntry->second;
1090     _geomEntryEnfVertexMap.erase(it_enfVertexEntry);
1091   } else {
1092     // Fail
1093     // check that enf vertex with given coords exists
1094     TCoordsHYBRIDEnforcedVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
1095     if (it_coords_enf != _coordsEnfVertexMap.end()) {
1096       // Success
1097       oldEnfVertex = it_coords_enf->second;
1098       _coordsEnfVertexMap.erase(it_coords_enf);
1099       _enfVertexCoordsSizeList.erase(_enfVertexCoordsSizeList.find(coords));
1100     } else {
1101       // Fail
1102       throw std::invalid_argument(msg.str());
1103     }
1104   }
1105
1106
1107   // update _enfVertexList
1108   THYBRIDEnforcedVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1109   if (it != _enfVertexList.end()) {
1110     if ((*it)->groupName != "")
1111       _groupsToRemove.insert((*it)->groupName);
1112     _enfVertexList.erase(it);
1113     toNotify = true;
1114   }
1115
1116   if (toNotify)
1117     NotifySubMeshesHypothesisModification();
1118
1119   return toNotify;
1120 }
1121
1122 //=======================================================================
1123 //function : ClearEnforcedVertices
1124 //=======================================================================
1125 void HYBRIDPlugin_Hypothesis::ClearEnforcedVertices()
1126 {
1127   THYBRIDEnforcedVertexList::const_iterator it = _enfVertexList.begin();
1128   for(;it != _enfVertexList.end();++it) {
1129     if ((*it)->groupName != "")
1130       _groupsToRemove.insert((*it)->groupName);
1131   }
1132   _enfVertexList.clear();
1133   _coordsEnfVertexMap.clear();
1134   _geomEntryEnfVertexMap.clear();
1135   _enfVertexCoordsSizeList.clear();
1136   _enfVertexEntrySizeList.clear();
1137   NotifySubMeshesHypothesisModification();
1138 }
1139
1140 //=======================================================================
1141 //function : ClearEnforcedMeshes
1142 //=======================================================================
1143 void HYBRIDPlugin_Hypothesis::ClearEnforcedMeshes()
1144 {
1145   THYBRIDEnforcedMeshList::const_iterator it = _enfMeshList.begin();
1146   for(;it != _enfMeshList.end();++it) {
1147     if ((*it)->groupName != "")
1148       _groupsToRemove.insert((*it)->groupName);
1149   }
1150   _enfNodes.clear();
1151   _enfEdges.clear();
1152   _enfTriangles.clear();
1153   _nodeIDToSizeMap.clear();
1154   _enfMeshList.clear();
1155   _entryEnfMeshMap.clear();
1156   NotifySubMeshesHypothesisModification();
1157 }
1158
1159 //================================================================================
1160 /*!
1161  * \brief At mesh loading, restore enforced elements by just loaded enforced meshes
1162  */
1163 //================================================================================
1164
1165 void HYBRIDPlugin_Hypothesis::RestoreEnfElemsByMeshes()
1166 {
1167   THYBRIDEnforcedMeshList::const_iterator it = _enfMeshList.begin();
1168   for(;it != _enfMeshList.end();++it) {
1169     THYBRIDEnforcedMesh* enfMesh = *it;
1170     if ( SMESH_Mesh* mesh = GetMeshByPersistentID( enfMesh->persistID ))
1171       SetEnforcedMesh( *mesh,
1172                        enfMesh->elementType,
1173                        enfMesh->name,
1174                        enfMesh->entry,
1175                        enfMesh->groupName );
1176     enfMesh->persistID = -1; // not to restore again
1177   }
1178 }
1179
1180 //=======================================================================
1181 //function : SetGroupsToRemove
1182 //=======================================================================
1183
1184 void HYBRIDPlugin_Hypothesis::ClearGroupsToRemove()
1185 {
1186   _groupsToRemove.clear();
1187 }
1188
1189
1190 //=======================================================================
1191 //function : DefaultLayersOnAllWrap
1192 //=======================================================================
1193
1194 bool HYBRIDPlugin_Hypothesis::DefaultLayersOnAllWrap()
1195 {
1196   return true;
1197 }
1198
1199 //=======================================================================
1200 //function : DefaultMeshHoles
1201 //=======================================================================
1202
1203 bool HYBRIDPlugin_Hypothesis::DefaultMeshHoles()
1204 {
1205   return false; // PAL19680
1206 }
1207
1208 //=======================================================================
1209 //function : DefaultToMakeGroupsOfDomains
1210 //=======================================================================
1211
1212 bool HYBRIDPlugin_Hypothesis::DefaultToMakeGroupsOfDomains()
1213 {
1214   return false; // issue 0022172
1215 }
1216
1217 //=======================================================================
1218 //function : DefaultMaximumMemory
1219 //=======================================================================
1220
1221 #if defined(WIN32)
1222 #include <windows.h>
1223 #elif !defined(__APPLE__)
1224 #include <sys/sysinfo.h>
1225 #endif
1226
1227 double  HYBRIDPlugin_Hypothesis::DefaultMaximumMemory()
1228 {
1229 #if defined(WIN32)
1230   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1231   MEMORYSTATUSEX statex;
1232   statex.dwLength = sizeof (statex);
1233   int err = GlobalMemoryStatusEx (&statex);
1234   if (err != 0) {
1235     int totMB = 
1236       statex.ullTotalPhys / 1024 / 1024 +
1237       statex.ullTotalPageFile / 1024 / 1024 +
1238       statex.ullTotalVirtual / 1024 / 1024;
1239     return ( 0.7 * totMB );
1240   }
1241 #elif !defined(__APPLE__)
1242   struct sysinfo si;
1243   int err = sysinfo( &si );
1244   if ( err == 0 ) {
1245     int ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1246     return ( 0.7 * ramMB );
1247   }
1248 #endif
1249   return 1024;
1250 }
1251
1252 //=======================================================================
1253 //function : DefaultInitialMemory
1254 //=======================================================================
1255
1256 double  HYBRIDPlugin_Hypothesis::DefaultInitialMemory()
1257 {
1258   return DefaultMaximumMemory();
1259 }
1260
1261 //=======================================================================
1262 //function : DefaultCollisionMode
1263 //=======================================================================
1264 short  HYBRIDPlugin_Hypothesis::DefaultCollisionMode()
1265 {
1266   return Decrease;
1267 }
1268
1269 //=======================================================================
1270 //function : DefaultBoundaryLayersGrowth
1271 //=======================================================================
1272 short  HYBRIDPlugin_Hypothesis::DefaultBoundaryLayersGrowth()
1273 {
1274   return Layer_Growth_Inward;
1275 }
1276
1277 //=======================================================================
1278 //function : DefaultElementGeneration
1279 //=======================================================================
1280 short  HYBRIDPlugin_Hypothesis::DefaultElementGeneration()
1281 {
1282   return Generation_Tetra_Dominant;
1283 }
1284
1285 //=======================================================================
1286 //function : DefaultOptimizationLevel
1287 //=======================================================================
1288 short  HYBRIDPlugin_Hypothesis::DefaultOptimizationLevel()
1289 {
1290   return Medium;
1291 }
1292
1293 //=======================================================================
1294 //function : DefaultWorkingDirectory
1295 //=======================================================================
1296
1297 std::string HYBRIDPlugin_Hypothesis::DefaultWorkingDirectory()
1298 {
1299   std::string aTmpDir;
1300
1301   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1302   if(Tmp_dir != NULL) {
1303     aTmpDir = Tmp_dir;
1304   }
1305   else {
1306 #ifdef WIN32
1307     aTmpDir = "C:\\";
1308 #else
1309     aTmpDir = "/tmp/";
1310 #endif
1311   }
1312   return aTmpDir;
1313 }
1314
1315 //=======================================================================
1316 //function : DefaultKeepFiles
1317 //=======================================================================
1318
1319 bool   HYBRIDPlugin_Hypothesis::DefaultKeepFiles()
1320 {
1321   return false;
1322 }
1323
1324 //=======================================================================
1325 //function : DefaultRemoveLogOnSuccess
1326 //=======================================================================
1327
1328 bool   HYBRIDPlugin_Hypothesis::DefaultRemoveLogOnSuccess()
1329 {
1330   return false;
1331 }
1332
1333
1334 //=======================================================================
1335 //function : DefaultVerboseLevel
1336 //=======================================================================
1337
1338 short  HYBRIDPlugin_Hypothesis::DefaultVerboseLevel()
1339 {
1340   return 10;
1341 }
1342
1343 //=======================================================================
1344 //function : DefaultToCreateNewNodes
1345 //=======================================================================
1346
1347 bool HYBRIDPlugin_Hypothesis::DefaultToCreateNewNodes()
1348 {
1349   return true;
1350 }
1351
1352 //=======================================================================
1353 //function : DefaultToUseBoundaryRecoveryVersion
1354 //=======================================================================
1355
1356 bool HYBRIDPlugin_Hypothesis::DefaultToUseBoundaryRecoveryVersion()
1357 {
1358   return false;
1359 }
1360
1361 //=======================================================================
1362 //function : DefaultToUseFEMCorrection
1363 //=======================================================================
1364
1365 bool HYBRIDPlugin_Hypothesis::DefaultToUseFEMCorrection()
1366 {
1367   return false;
1368 }
1369
1370 //=======================================================================
1371 //function : DefaultToRemoveCentralPoint
1372 //=======================================================================
1373
1374 bool HYBRIDPlugin_Hypothesis::DefaultToRemoveCentralPoint()
1375 {
1376   return false;
1377 }
1378
1379 //=======================================================================
1380 //function : DefaultGradation
1381 //=======================================================================
1382
1383 double HYBRIDPlugin_Hypothesis::DefaultGradation()
1384 {
1385   return 1.05;
1386 }
1387
1388 //=======================================================================
1389 //function : DefaultStandardOutputLog
1390 //=======================================================================
1391
1392 bool HYBRIDPlugin_Hypothesis::DefaultStandardOutputLog()
1393 {
1394   return false;
1395 }
1396
1397 // //=======================================================================
1398 // //function : DefaultID2SizeMap
1399 // //=======================================================================
1400 // 
1401 // HYBRIDPlugin_Hypothesis::TID2SizeMap HYBRIDPlugin_Hypothesis::DefaultID2SizeMap()
1402 // {
1403 //   return HYBRIDPlugin_Hypothesis::TID2SizeMap();
1404 // }
1405
1406 //=======================================================================
1407 //function : DefaultAddMultinormals
1408 //=======================================================================
1409 bool HYBRIDPlugin_Hypothesis::DefaultAddMultinormals()
1410 {
1411   return false;
1412 }
1413
1414 //=======================================================================
1415 //function : DefaultSmoothNormals
1416 //=======================================================================
1417 bool HYBRIDPlugin_Hypothesis::DefaultSmoothNormals()
1418 {
1419   return false;
1420 }
1421
1422 //=======================================================================
1423 //function : DefaultHeightFirstLayer
1424 //=======================================================================
1425 double HYBRIDPlugin_Hypothesis::DefaultHeightFirstLayer()
1426 {
1427   return 0.0; //or epsilon?
1428 }
1429
1430 //=======================================================================
1431 //function : DefaultBoundaryLayersProgression
1432 //=======================================================================
1433 double HYBRIDPlugin_Hypothesis::DefaultBoundaryLayersProgression()
1434 {
1435   return 1.0;
1436 }
1437
1438 //=======================================================================
1439 //function : DefaultCoreSize
1440 //=======================================================================
1441 double HYBRIDPlugin_Hypothesis::DefaultCoreSize()
1442 {
1443   return 0.0;
1444 }
1445
1446 //=======================================================================
1447 //function : DefaultMultinormalsAngle
1448 //=======================================================================
1449 double HYBRIDPlugin_Hypothesis::DefaultMultinormalsAngle()
1450 {
1451   return 30.0;
1452 }
1453
1454 //=======================================================================
1455 //function : DefaultNbOfBoundaryLayers
1456 //=======================================================================
1457 short HYBRIDPlugin_Hypothesis::DefaultNbOfBoundaryLayers()
1458 {
1459   return 1;
1460 }
1461
1462 //=======================================================================
1463 //function : SaveTo
1464 //=======================================================================
1465
1466 std::ostream & HYBRIDPlugin_Hypothesis::SaveTo(std::ostream & save)
1467 {
1468   save << (int) myBoundaryLayersGrowth << " ";
1469   save << (int) myElementGeneration << " ";
1470   save << (int) myAddMultinormals << " ";
1471   save << (int) mySmoothNormals << " ";
1472   save << (int) myLayersOnAllWrap << " ";
1473
1474   save << myNbOfBoundaryLayers << " ";
1475   save << myHeightFirstLayer << " ";
1476   save << myBoundaryLayersProgression << " ";
1477   save << myMultinormalsAngle << " ";
1478
1479   save << (int) myKeepFiles << " ";
1480   save << myWorkingDirectory << " ";
1481   save << myVerboseLevel << " ";
1482   save << myCoreSize << " ";
1483
1484   // if (!myTextOption.empty()) {
1485   //   save << "__OPTIONS_BEGIN__ ";
1486   //   save << myTextOption << " ";
1487   //   save << "__OPTIONS_END__ ";
1488   // }
1489
1490
1491   THYBRIDEnforcedVertexList::iterator it  = _enfVertexList.begin();
1492   if (it != _enfVertexList.end()) {
1493     save << " " << "__ENFORCED_VERTICES_BEGIN__ ";
1494     for ( ; it != _enfVertexList.end(); ++it ) {
1495       THYBRIDEnforcedVertex *enfVertex = (*it);
1496       save << " " << "__BEGIN_VERTEX__";
1497       if (!enfVertex->name.empty()) {
1498         save << " " << "__BEGIN_NAME__";
1499         save << " " << enfVertex->name;
1500         save << " " << "__END_NAME__";
1501       }
1502       if (!enfVertex->geomEntry.empty()) {
1503         save << " " << "__BEGIN_ENTRY__";
1504         save << " " << enfVertex->geomEntry;
1505         save << " " << enfVertex->isCompound;
1506         save << " " << "__END_ENTRY__";
1507       }
1508       if (!enfVertex->groupName.empty()) {
1509         save << " " << "__BEGIN_GROUP__";
1510         save << " " << enfVertex->groupName;
1511         save << " " << "__END_GROUP__";
1512       }
1513       if (enfVertex->coords.size()) {
1514         save << " " << "__BEGIN_COORDS__";
1515         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
1516           save << " " << enfVertex->coords[i];
1517         save << " " << "__END_COORDS__";
1518       }
1519       save << " " << "__BEGIN_SIZE__";
1520       save << " " << enfVertex->size;
1521       save << " " << "__END_SIZE__";
1522       save << " " << "__END_VERTEX__";
1523     }
1524     save << " " << "__ENFORCED_VERTICES_END__ ";
1525   }
1526
1527   THYBRIDEnforcedMeshList::iterator it_mesh  = _enfMeshList.begin();
1528   if (it_mesh != _enfMeshList.end()) {
1529     save << " " << "__ENFORCED_MESHES_BEGIN__ ";
1530     for ( ; it_mesh != _enfMeshList.end(); ++it_mesh ) {
1531       THYBRIDEnforcedMesh *enfMesh = (*it_mesh);
1532       save << " " << "__BEGIN_ENF_MESH__";
1533
1534       save << " " << "__BEGIN_NAME__";
1535       save << " " << enfMesh->name;
1536       save << " " << "__END_NAME__";
1537
1538       save << " " << "__BEGIN_ENTRY__";
1539       save << " " << enfMesh->entry;
1540       save << " " << "__END_ENTRY__";
1541
1542       save << " " << "__BEGIN_ELEM_TYPE__";
1543       save << " " << (int)enfMesh->elementType;
1544       save << " " << "__END_ELEM_TYPE__";
1545
1546       if (!enfMesh->groupName.empty()) {
1547         save << " " << "__BEGIN_GROUP__";
1548         save << " " << enfMesh->groupName;
1549         save << " " << "__END_GROUP__";
1550       }
1551       save << " " << "__PERSIST_ID__";
1552       save << " " << enfMesh->persistID;
1553       save << " " << "__END_ENF_MESH__";
1554       std::cout << "Saving of enforced mesh " << enfMesh->name.c_str() << " done" << std::endl;
1555     }
1556     save << " "  << "__ENFORCED_MESHES_END__ ";
1557   }
1558
1559   save << " " << myFacesWithLayers.size();
1560   for ( size_t i = 0; i < myFacesWithLayers.size(); ++i )
1561     save << " " << myFacesWithLayers[i];
1562
1563   save << " " << myFacesWithImprinting.size();
1564   for ( size_t i = 0; i < myFacesWithImprinting.size(); ++i )
1565     save << " " << myFacesWithImprinting[i];
1566
1567   save << " " << myFacesWithSnapping.size();
1568   for ( size_t i = 0; i < myFacesWithSnapping.size(); ++i )
1569     save << " " << myFacesWithSnapping[i];
1570
1571   // New options in 2.9.6 (issue #17784)
1572
1573   save << " " << myHeightIsRelative;
1574   save << " " << myBoundaryLayersMaxElemAngle;
1575   save << " " << myCollisionMode;
1576   save << " " << myGradation;
1577   save << " " << myOptimizationLevel;
1578
1579   save << " " << _option2value.size();
1580   TOptionValues::iterator o2v = _option2value.begin();
1581   for ( ; o2v != _option2value.end(); ++o2v )
1582     save << " -" << o2v->first << " -" << o2v->second;
1583
1584   save << " " << _customOption2value.size();
1585   for ( o2v = _customOption2value.begin(); o2v != _customOption2value.end(); ++o2v )
1586     save << " -" << o2v->first << " -" << o2v->second;
1587
1588   return save;
1589 }
1590
1591 //=======================================================================
1592 //function : LoadFrom
1593 //=======================================================================
1594
1595 std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load)
1596 {
1597   bool isOK = true;
1598   int i;
1599   double d;
1600
1601   isOK = static_cast<bool>(load >> i);
1602   if (isOK)
1603     myBoundaryLayersGrowth = (short) i;
1604   else
1605     load.clear(ios::badbit | load.rdstate());
1606
1607   isOK = static_cast<bool>(load >> i);
1608   if (isOK)
1609     myElementGeneration = (short) i;
1610   else
1611     load.clear(ios::badbit | load.rdstate());
1612
1613   isOK = static_cast<bool>(load >> i);
1614   if (isOK)
1615     myAddMultinormals = (bool) i;
1616   else
1617     load.clear(ios::badbit | load.rdstate());
1618
1619   isOK = static_cast<bool>(load >> i);
1620   if (isOK)
1621     mySmoothNormals = (bool) i;
1622   else
1623     load.clear(ios::badbit | load.rdstate());
1624
1625   isOK = static_cast<bool>(load >> i);
1626   if (isOK)
1627     myLayersOnAllWrap = (bool) i;
1628   else
1629     load.clear(ios::badbit | load.rdstate());
1630
1631   isOK = static_cast<bool>(load >> i);
1632   if (isOK)
1633     myNbOfBoundaryLayers = (short) i;
1634   else
1635     load.clear(ios::badbit | load.rdstate());
1636
1637   isOK = static_cast<bool>(load >> d);
1638   if (isOK)
1639     myHeightFirstLayer = d;
1640   else
1641     load.clear(ios::badbit | load.rdstate());
1642
1643   isOK = static_cast<bool>(load >> d);
1644   if (isOK)
1645     myBoundaryLayersProgression = d;
1646   else
1647     load.clear(ios::badbit | load.rdstate());
1648
1649   isOK = static_cast<bool>(load >> d);
1650   if (isOK)
1651     myMultinormalsAngle = d;
1652   else
1653     load.clear(ios::badbit | load.rdstate());
1654
1655   isOK = static_cast<bool>(load >> i);
1656   if (isOK)
1657     myKeepFiles = (bool) i;
1658   else
1659     load.clear(ios::badbit | load.rdstate());
1660
1661   isOK = static_cast<bool>(load >> myWorkingDirectory);
1662   if (isOK) {
1663     if ( myWorkingDirectory == "0") { // myWorkingDirectory was empty
1664       myKeepFiles = false;
1665       myWorkingDirectory.clear();
1666     }
1667     else if ( myWorkingDirectory == "1" ) {
1668       myKeepFiles = true;
1669       myWorkingDirectory.clear();
1670     }
1671   }
1672   else
1673     load.clear(ios::badbit | load.rdstate());
1674
1675   isOK = static_cast<bool>(load >> i);
1676   if (isOK)
1677     myVerboseLevel = (short) i;
1678   else
1679     load.clear(ios::badbit | load.rdstate());
1680
1681   isOK = static_cast<bool>(load >> d);
1682   if (isOK)
1683     myCoreSize = d;
1684   else
1685     load.clear(ios::badbit | load.rdstate());
1686
1687   std::string separator;
1688   bool hasOptions = false;
1689   bool hasEnforcedVertices = false;
1690   bool hasEnforcedMeshes = false;
1691   isOK = static_cast<bool>(load >> separator);
1692
1693   if (isOK) {
1694     if (separator == "__OPTIONS_BEGIN__")
1695       hasOptions = true;
1696     else if (separator == "__ENFORCED_VERTICES_BEGIN__")
1697       hasEnforcedVertices = true;
1698     else if (separator == "__ENFORCED_MESHES_BEGIN__")
1699       hasEnforcedMeshes = true;
1700   }
1701
1702   if (hasOptions) {
1703     std::string txt;
1704     while (isOK) {
1705       isOK = static_cast<bool>(load >> txt);
1706       if (isOK) {
1707         if (txt == "__OPTIONS_END__") {
1708           isOK = false;
1709           break;
1710         }
1711         // myTextOption += txt;
1712       }
1713     }
1714   }
1715
1716   if (hasOptions) {
1717     isOK = static_cast<bool>(load >> separator);
1718     if (isOK && separator == "__ENFORCED_VERTICES_BEGIN__")
1719       hasEnforcedVertices = true;
1720     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1721       hasEnforcedMeshes = true;
1722   }
1723
1724   if (hasEnforcedVertices) {
1725     std::string txt, name, entry, groupName;
1726     double size, coords[3];
1727     bool isCompound;
1728     bool hasCoords = false;
1729     isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1730     while (isOK) {
1731       if (txt == "__ENFORCED_VERTICES_END__")
1732         isOK = false;
1733
1734       THYBRIDEnforcedVertex *enfVertex = new THYBRIDEnforcedVertex();
1735       while (isOK) {
1736         isOK = static_cast<bool>(load >> txt);
1737         if (txt == "__END_VERTEX__") {
1738           enfVertex->name = name;
1739           enfVertex->geomEntry = entry;
1740           enfVertex->isCompound = isCompound;
1741           enfVertex->groupName = groupName;
1742           enfVertex->coords.clear();
1743           if (hasCoords)
1744             enfVertex->coords.assign(coords,coords+3);
1745
1746           _enfVertexList.insert(enfVertex);
1747
1748           if (enfVertex->coords.size())
1749             _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
1750           if (!enfVertex->geomEntry.empty())
1751             _geomEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
1752
1753           name.clear();
1754           entry.clear();
1755           groupName.clear();
1756           hasCoords = false;
1757           isOK = false;
1758         }
1759
1760         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1761           while (isOK && (txt != "__END_NAME__")) {
1762             isOK = static_cast<bool>(load >> txt);
1763             if (txt != "__END_NAME__") {
1764               if (!name.empty())
1765                 name += " ";
1766               name += txt;
1767             }
1768           }
1769         }
1770
1771         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1772           isOK = static_cast<bool>(load >> entry);
1773           isOK = static_cast<bool>(load >> isCompound);
1774           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1775           if (txt != "__END_ENTRY__")
1776             throw std::exception();
1777         }
1778
1779         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1780           while (isOK && (txt != "__END_GROUP__")) {
1781             isOK = static_cast<bool>(load >> txt);
1782             if (txt != "__END_GROUP__") {
1783               if (!groupName.empty())
1784                 groupName += " ";
1785               groupName += txt;
1786             }
1787           }
1788         }
1789
1790         if (txt == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
1791           hasCoords = true;
1792           isOK = static_cast<bool>(load >> coords[0] >> coords[1] >> coords[2]);
1793           isOK = static_cast<bool>(load >> txt); // __END_COORDS__
1794           if (txt != "__END_COORDS__")
1795             throw std::exception();
1796         }
1797
1798         if (txt == "__BEGIN_SIZE__") {  // __BEGIN_ENTRY__
1799           isOK = static_cast<bool>(load >> size);
1800           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1801           if (txt != "__END_SIZE__") {
1802             throw std::exception();
1803           }
1804         }
1805       }
1806       isOK = static_cast<bool>(load >> txt);  // __BEGIN_VERTEX__
1807     }
1808   }
1809
1810   if (hasEnforcedVertices) {
1811     isOK = static_cast<bool>(load >> separator);
1812     if (isOK && separator == "__ENFORCED_MESHES_BEGIN__")
1813       hasEnforcedMeshes = true;
1814   }
1815
1816   if (hasEnforcedMeshes) {
1817     std::string txt, name, entry, groupName;
1818     int elementType = -1, persistID = -1;
1819     isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1820     while (isOK) {
1821       //                if (isOK) {
1822       if (txt == "__ENFORCED_MESHES_END__")
1823         isOK = false;
1824
1825       THYBRIDEnforcedMesh *enfMesh = new THYBRIDEnforcedMesh();
1826       while (isOK) {
1827         isOK = static_cast<bool>(load >> txt);
1828         if (txt == "__END_ENF_MESH__") {
1829           enfMesh->name = name;
1830           enfMesh->entry = entry;
1831           enfMesh->elementType = (SMESH::ElementType)elementType;
1832           enfMesh->groupName = groupName;
1833           enfMesh->persistID = persistID;
1834
1835           _enfMeshList.insert(enfMesh);
1836           std::cout << "Restoring of enforced mesh " <<name  << " done" << std::endl;
1837
1838           name.clear();
1839           entry.clear();
1840           elementType = -1;
1841           groupName.clear();
1842           persistID = -1;
1843           isOK = false;
1844         }
1845
1846         if (txt == "__BEGIN_NAME__") {  // __BEGIN_NAME__
1847           while (isOK && (txt != "__END_NAME__")) {
1848             isOK = static_cast<bool>(load >> txt);
1849             if (txt != "__END_NAME__") {
1850               if (!name.empty())
1851                 name += " ";
1852               name += txt;
1853             }
1854           }
1855         }
1856
1857         if (txt == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
1858           isOK = static_cast<bool>(load >> entry);
1859           isOK = static_cast<bool>(load >> txt); // __END_ENTRY__
1860           if (txt != "__END_ENTRY__")
1861             throw std::exception();
1862         }
1863
1864         if (txt == "__BEGIN_ELEM_TYPE__") {  // __BEGIN_ELEM_TYPE__
1865           isOK = static_cast<bool>(load >> elementType);
1866           isOK = static_cast<bool>(load >> txt); // __END_ELEM_TYPE__
1867           if (txt != "__END_ELEM_TYPE__")
1868             throw std::exception();
1869         }
1870
1871         if (txt == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
1872           while (isOK && (txt != "__END_GROUP__")) {
1873             isOK = static_cast<bool>(load >> txt);
1874             if (txt != "__END_GROUP__") {
1875               if (!groupName.empty())
1876                 groupName += " ";
1877               groupName += txt;
1878             }
1879           } // while
1880         } // if
1881
1882         if (txt == "__PERSIST_ID__") {
1883           isOK = static_cast<bool>(load >> persistID);
1884         }
1885         std::cout << "isOK: " << isOK << std::endl;
1886       } // while
1887       //                } // if
1888       isOK = static_cast<bool>(load >> txt);  // __BEGIN_ENF_MESH__
1889     } // while
1890   } // if
1891
1892   if ( hasEnforcedMeshes )
1893     isOK = static_cast<bool>(load >> separator);
1894
1895   if ( isOK )
1896   {
1897     i = atoi( separator.c_str() );
1898     isOK = ( i >= 0 );
1899     if ( isOK )
1900     {
1901       myFacesWithLayers.reserve( i );
1902       while (( myFacesWithLayers.size() < myFacesWithLayers.capacity() ) &&
1903              ( isOK = static_cast<bool>(load >> i)) )
1904         myFacesWithLayers.push_back( i );
1905     }
1906   }
1907
1908   isOK = static_cast<bool>(load >> separator);
1909   if ( isOK )
1910   {
1911     i = atoi( separator.c_str() );
1912     isOK = ( i >= 0 );
1913     if ( isOK )
1914     {
1915       myFacesWithImprinting.reserve( i );
1916       while (( myFacesWithImprinting.size() < myFacesWithImprinting.capacity() ) &&
1917              ( isOK = static_cast<bool>(load >> i)) )
1918         myFacesWithImprinting.push_back( i );
1919     }
1920   }
1921
1922   isOK = static_cast<bool>(load >> separator);
1923   if ( isOK )
1924   {
1925     i = atoi( separator.c_str() );
1926     isOK = ( i >= 0 );
1927     if ( isOK )
1928     {
1929       myFacesWithSnapping.reserve( i );
1930       while (( myFacesWithSnapping.size() < myFacesWithSnapping.capacity() ) &&
1931              ( isOK = static_cast<bool>(load >> i)) )
1932         myFacesWithSnapping.push_back( i );
1933     }
1934   }
1935
1936   // New options in 2.9.6 (issue #17784)
1937
1938   if ( static_cast<bool>(load >> i))
1939   {
1940     myHeightIsRelative = (bool) i;
1941     load >> myBoundaryLayersMaxElemAngle;
1942     load >> myCollisionMode;
1943     load >> myGradation;
1944     load >> myOptimizationLevel;
1945
1946     std::string option, value;
1947     if ( static_cast<bool>( load >> i ) && i >= 0 )
1948     {
1949       for ( int nbRead = 0; nbRead < i; ++nbRead )
1950       {
1951         load >> option >> value;
1952         _option2value[ std::string( option, 1 )] = std::string( value, 1 );
1953       }
1954     }
1955     if ( static_cast<bool>( load >> i ) && i >= 0 )
1956     {
1957       for ( int nbRead = 0; nbRead < i; ++nbRead )
1958       {
1959         load >> option >> value;
1960         _customOption2value[ std::string( option, 1 )] = std::string( value, 1 );
1961       }
1962     }
1963   }
1964
1965   return load;
1966 }
1967
1968 //=======================================================================
1969 //function : SetParametersByMesh
1970 //=======================================================================
1971
1972 bool HYBRIDPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* ,const TopoDS_Shape&)
1973 {
1974   return false;
1975 }
1976
1977 //================================================================================
1978 /*!
1979  * \brief Sets myToMakeGroupsOfDomains depending on whether theMesh is on shape or not
1980  */
1981 //================================================================================
1982
1983 bool HYBRIDPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
1984                                                      const SMESH_Mesh* /*theMesh*/)
1985 {
1986   myToMakeGroupsOfDomains = ( !dflts._shape || dflts._shape->IsNull() );
1987   return true;
1988 }
1989
1990 //================================================================================
1991 /*!
1992  * \brief Return command to run hybrid mesher excluding file prefix (-f)
1993  */
1994 //================================================================================
1995
1996 std::string HYBRIDPlugin_Hypothesis::CommandToRun(const HYBRIDPlugin_Hypothesis* hyp)
1997 {
1998   SMESH_Comment cmd = GetExeName();
1999   // check if any option is overridden by hyp->_option2value
2000   bool p_h     = ( hyp && hyp->HasOptionDefined("-h"));
2001   bool p_v     = ( hyp && hyp->HasOptionDefined("-v"));
2002   bool p_blsd  = ( hyp && hyp->HasOptionDefined("--normal_direction"));
2003   bool p_hotfl = ( hyp && hyp->HasOptionDefined("--boundary_layer_global_initial_height"));
2004   bool p_nobl  = ( hyp && hyp->HasOptionDefined("--number_of_boundary_layers"));
2005   bool p_blgp  = ( hyp && hyp->HasOptionDefined("--boundary_layer_geometric_progression"));
2006   bool p_eg    = ( hyp && hyp->HasOptionDefined("--element_generation"));
2007   bool p_cs    = ( hyp && hyp->HasOptionDefined("--global_physical_size"));
2008
2009   bool nolayers = false;
2010   bool layersOnAllWrap = hyp ? hyp->myLayersOnAllWrap : DefaultLayersOnAllWrap();
2011
2012   //help mode
2013   if ( p_h ) {
2014     cmd << " --help ";
2015 #ifdef WIN32
2016     cmd << " < NUL";
2017 #endif
2018     std::cout << "!!!!! CommandToRun help only !!!! " << cmd << std::endl;
2019     return cmd;
2020   }
2021
2022   if ( !p_v && hyp )
2023     cmd << " --verbose " << hyp->myVerboseLevel;
2024
2025   //no layers?
2026   if ( !p_nobl && hyp ) {
2027     if ( hyp->myNbOfBoundaryLayers < 1 ) nolayers = true;
2028   }
2029   if ( !p_hotfl && hyp ) {
2030     if ( hyp->myHeightFirstLayer < 1e-50 ) nolayers = true;
2031   }
2032
2033   if ( !p_blsd && hyp ) {
2034     if ( hyp->myBoundaryLayersGrowth >= 0 && hyp->myBoundaryLayersGrowth <= 1 ) {
2035       const char* value[] = { "-1" , "1" }; // -1 == inside
2036       cmd << " --normal_direction " << value[ hyp->myBoundaryLayersGrowth ];
2037     }
2038   }
2039
2040   if ( !p_hotfl && hyp ) {
2041     cmd << " --boundary_layer_global_initial_height " << hyp->myHeightFirstLayer;
2042   }
2043   if ( hyp && hyp->GetHeightIsRelative() )
2044     cmd << " --boundary_layer_height_relative_to_local_surface_size yes";
2045
2046   if ( !p_nobl && hyp ) {
2047     cmd << " --number_of_boundary_layers " << ( nolayers ? 0 :  hyp->myNbOfBoundaryLayers );
2048   }
2049
2050   if ( !p_blgp && hyp ) {
2051     cmd << " --boundary_layer_geometric_progression " << hyp->myBoundaryLayersProgression;
2052   }
2053
2054   if ( !nolayers && hyp )
2055   {
2056     cmd << " --boundary_layer_size_mode " << ( layersOnAllWrap ? "global" : "local" );
2057
2058     if ( hyp->GetBoundaryLayersMaxElemAngle() != hyp->DefaultBoundaryLayersMaxElemAngle() )
2059       cmd << " --boundary_layer_max_element_angle "
2060           << SMESH_Comment( hyp->GetBoundaryLayersMaxElemAngle() );
2061
2062     if ( !layersOnAllWrap )
2063     {
2064       // faces with layers
2065       const std::vector<int>& faceLayersIDs = hyp->GetFacesWithLayers();
2066       if ( !faceLayersIDs.empty() )
2067         cmd << " --boundary_layer_surface_tags ";
2068       for ( size_t i = 0; i < faceLayersIDs.size(); ++i )
2069         cmd << faceLayersIDs[i] << ",";
2070       if ( !faceLayersIDs.empty() )
2071         cmd << " --boundary_layer_initial_height_on_surface_tags ";
2072       for ( size_t i = 0; i < faceLayersIDs.size(); ++i )
2073         cmd << hyp->myHeightFirstLayer << ",";
2074
2075       // faces with imprinting
2076       const std::vector<int>& faceImprintingIDs = hyp->GetFacesWithImprinting();
2077       if ( !faceImprintingIDs.empty() )
2078         cmd << " --boundary_layer_imprinting yes --boundary_layer_imprinting_tags ";
2079       for ( size_t i = 0; i < faceImprintingIDs.size(); ++i )
2080         cmd << faceImprintingIDs[i] << ",";
2081
2082       // faces with snapping
2083       const std::vector<int>& faceSnappingIDs = hyp->GetFacesWithSnapping();
2084       if ( !faceSnappingIDs.empty() )
2085         cmd << " --boundary_layer_snapping yes --boundary_layer_snapping_tags ";
2086       for ( size_t i = 0; i < faceSnappingIDs.size(); ++i )
2087         cmd << faceSnappingIDs[i] << ",";
2088     }
2089   }
2090
2091   if ( !p_eg && hyp ) {
2092     if ( hyp->myElementGeneration >= 0 && hyp->myElementGeneration <= 3 ) {
2093       const char* value[] = { "tetra_dominant" , "hexa_dominant", "cartesian_core", "extrusion_only" };
2094       cmd << " --element_generation " << value[ hyp->myElementGeneration ];
2095     }
2096   }
2097
2098   if ( !p_cs && hyp ) {
2099     if ( hyp->myCoreSize > 0 ) {
2100       cmd << " --global_physical_size " << hyp->myCoreSize;
2101     }
2102   }
2103
2104   if ( hyp )
2105   {
2106     // options as text
2107     std::string option, value;
2108     bool isDefault;
2109     const TOptionValues* options[] = { & hyp->_option2value, & hyp->_customOption2value };
2110     for ( int iOp = 0; iOp < 2; ++iOp )
2111     {
2112       TOptionValues::const_iterator o2v = options[iOp]->begin();
2113       for ( ; o2v != options[iOp]->end(); ++o2v )
2114       {
2115         option = o2v->first;
2116         value = hyp->GetOptionValue( option, &isDefault );
2117
2118         if ( isDefault )
2119           continue;
2120         if ( value.empty() )
2121         {
2122           if ( hyp->_defaultOptionValues.count( option ))
2123             continue; // non-custom option with no value
2124         }
2125         if ( option[0] != '-' )
2126           cmd << " --";
2127         else
2128           cmd << " ";
2129         cmd << option << " " << value;
2130       }
2131     }
2132   }
2133
2134 #ifdef WIN32
2135   cmd << " < NUL";
2136 #endif
2137   //std::cout << "!!!!!CommandToRun end " << cmd << std::endl;
2138
2139   return cmd;
2140 }
2141
2142 //================================================================================
2143 /*!
2144  * \brief Return a unique file name
2145  */
2146 //================================================================================
2147
2148 std::string HYBRIDPlugin_Hypothesis::GetFileName(const HYBRIDPlugin_Hypothesis* hyp)
2149 {
2150   std::string aTmpDir = hyp ? hyp->GetWorkingDirectory() : DefaultWorkingDirectory();
2151   const char lastChar = *aTmpDir.rbegin();
2152 #ifdef WIN32
2153   if(lastChar != '\\') aTmpDir+='\\';
2154 #else
2155   if(lastChar != '/') aTmpDir+='/';
2156 #endif
2157
2158   SMESH_Comment aGenericName = aTmpDir;
2159   aGenericName << "HYBRID_";
2160   aGenericName << getpid();
2161   aGenericName << "_";
2162   aGenericName << Abs((Standard_Integer)(long) aGenericName.c_str());
2163
2164   return aGenericName;
2165 }
2166
2167 //================================================================================
2168 /*
2169  * Return the name of executable
2170  */
2171 //================================================================================
2172
2173 std::string HYBRIDPlugin_Hypothesis::GetExeName()
2174 {
2175   //call mg-hybrid.bash is script which assumes new project version(s) mg-hybrid.exe in the prerequisite base and special? licence.
2176 #ifdef WIN32
2177   return "mg-hybrid.exe";
2178 #else
2179   return "mg-hybrid.bash";
2180 #endif
2181 }
2182
2183 //=============================================================================
2184 void HYBRIDPlugin_Hypothesis::SetOptionValue(const std::string& optionName,
2185                                              const std::string& optionValue)
2186 {
2187   TOptionValues::iterator op_val = _option2value.find(optionName);
2188   if (op_val == _option2value.end())
2189   {
2190     op_val = _customOption2value.find( optionName );
2191     if ( op_val == _customOption2value.end() || op_val->second != optionValue )
2192       NotifySubMeshesHypothesisModification();
2193     _customOption2value[ optionName ] = optionValue;
2194     return;
2195   }
2196
2197   if (op_val->second != optionValue)
2198   {
2199     const char* ptr = optionValue.c_str();
2200     // strip white spaces
2201     while (ptr[0] == ' ')
2202       ptr++;
2203     int i = strlen(ptr);
2204     while (i != 0 && ptr[i - 1] == ' ')
2205       i--;
2206     // check value type
2207     bool typeOk = true;
2208     std::string typeName;
2209     if (i == 0) {
2210       // empty string
2211     } else if (_charOptions.count(optionName)) {
2212       // do not check strings
2213     } else if (_doubleOptions.count(optionName)) {
2214       // check if value is double
2215       ToDbl(ptr, &typeOk);
2216       typeName = "real";
2217     } else if (_boolOptions.count(optionName)) {
2218       // check if value is bool
2219       ToBool(ptr, &typeOk);
2220       typeName = "bool";
2221     } else {
2222       // check if value is int
2223       ToInt(ptr, &typeOk);
2224       typeName = "integer";
2225     }
2226     if ( typeOk ) // check some specific values ?
2227     {
2228     }
2229     if ( !typeOk )
2230     {
2231       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
2232       throw std::invalid_argument(msg);
2233     }
2234     std::string value( ptr, i );
2235     if ( _defaultOptionValues[ optionName ] == value )
2236       value.clear();
2237
2238     op_val->second = value;
2239
2240     NotifySubMeshesHypothesisModification();
2241   }
2242 }
2243
2244 //=============================================================================
2245 //! Return option value. If isDefault provided, it can be a default value,
2246 //  then *isDefault == true. If isDefault is not provided, the value will be
2247 //  empty if it equals a default one.
2248 std::string HYBRIDPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
2249                                                     bool*              isDefault) const
2250 {
2251   TOptionValues::const_iterator op_val = _option2value.find(optionName);
2252   if (op_val == _option2value.end())
2253   {
2254     op_val = _customOption2value.find(optionName);
2255     if (op_val == _customOption2value.end())
2256     {
2257       std::string msg = "Unknown MG-Tetra option: <" + optionName + ">";
2258       throw std::invalid_argument(msg);
2259     }
2260   }
2261   std::string val = op_val->second;
2262   if ( isDefault ) *isDefault = ( val.empty() );
2263
2264   if ( val.empty() && isDefault )
2265   {
2266     op_val = _defaultOptionValues.find( optionName );
2267     if (op_val != _defaultOptionValues.end())
2268       val = op_val->second;
2269   }
2270   return val;
2271 }
2272
2273
2274 //=============================================================================
2275 bool HYBRIDPlugin_Hypothesis::HasOptionDefined( const std::string& optionName ) const
2276 {
2277   bool isDefault = false;
2278   try
2279   {
2280     GetOptionValue( optionName, &isDefault );
2281   }
2282   catch ( std::invalid_argument& )
2283   {
2284     return false;
2285   }
2286   return !isDefault;
2287 }
2288
2289 //=============================================================================
2290 void HYBRIDPlugin_Hypothesis::ClearOption(const std::string& optionName)
2291 {
2292   TOptionValues::iterator op_val = _customOption2value.find(optionName);
2293   if (op_val != _customOption2value.end())
2294     _customOption2value.erase(op_val);
2295   else {
2296     op_val = _option2value.find(optionName);
2297     if (op_val != _option2value.end())
2298       op_val->second.clear();
2299   }
2300 }
2301
2302 //=============================================================================
2303 HYBRIDPlugin_Hypothesis::TOptionValues HYBRIDPlugin_Hypothesis::GetOptionValues() const
2304 {
2305   TOptionValues vals;
2306   TOptionValues::const_iterator op_val = _option2value.begin();
2307   for ( ; op_val != _option2value.end(); ++op_val )
2308     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
2309
2310   return vals;
2311 }
2312
2313 //================================================================================
2314 /*!
2315  * \brief Converts a string to a bool
2316  */
2317 //================================================================================
2318
2319 bool HYBRIDPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
2320 {
2321   std::string s = str;
2322   if ( isOk ) *isOk = true;
2323
2324   for ( size_t i = 0; i <= s.size(); ++i )
2325     s[i] = tolower( s[i] );
2326
2327   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
2328     return true;
2329
2330   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
2331     return false;
2332
2333   if ( isOk )
2334     *isOk = false;
2335   else {
2336     std::string msg = "Not a Boolean value:'" + str + "'";
2337     throw std::invalid_argument(msg);
2338   }
2339   return false;
2340 }
2341
2342 //================================================================================
2343 /*!
2344  * \brief Converts a string to a real value
2345  */
2346 //================================================================================
2347
2348 double HYBRIDPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
2349 {
2350   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2351
2352   char * endPtr;
2353   double val = strtod(&str[0], &endPtr);
2354   bool ok = (&str[0] != endPtr);
2355
2356   if ( isOk ) *isOk = ok;
2357
2358   if ( !ok )
2359   {
2360     std::string msg = "Not a real value:'" + str + "'";
2361     throw std::invalid_argument(msg);
2362   }
2363   return val;
2364 }
2365
2366 //================================================================================
2367 /*!
2368  * \brief Converts a string to a integer value
2369  */
2370 //================================================================================
2371
2372 int HYBRIDPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
2373 {
2374   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
2375
2376   char * endPtr;
2377   int val = (int)strtol( &str[0], &endPtr, 10);
2378   bool ok = (&str[0] != endPtr);
2379
2380   if ( isOk ) *isOk = ok;
2381
2382   if ( !ok )
2383   {
2384     std::string msg = "Not an integer value:'" + str + "'";
2385     throw std::invalid_argument(msg);
2386   }
2387   return val;
2388 }
2389
2390
2391 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexList HYBRIDPlugin_Hypothesis::GetEnforcedVertices(const HYBRIDPlugin_Hypothesis* hyp)
2392 {
2393   return hyp ? hyp->_GetEnforcedVertices():THYBRIDEnforcedVertexList();
2394 }
2395
2396 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexCoordsValues HYBRIDPlugin_Hypothesis::GetEnforcedVerticesCoordsSize (const HYBRIDPlugin_Hypothesis* hyp)
2397 {  
2398   return hyp ? hyp->_GetEnforcedVerticesCoordsSize(): THYBRIDEnforcedVertexCoordsValues();
2399 }
2400
2401 HYBRIDPlugin_Hypothesis::THYBRIDEnforcedVertexEntryValues HYBRIDPlugin_Hypothesis::GetEnforcedVerticesEntrySize (const HYBRIDPlugin_Hypothesis* hyp)
2402 {  
2403   return hyp ? hyp->_GetEnforcedVerticesEntrySize():THYBRIDEnforcedVertexEntryValues();
2404 }
2405
2406 HYBRIDPlugin_Hypothesis::TCoordsHYBRIDEnforcedVertexMap HYBRIDPlugin_Hypothesis::GetEnforcedVerticesByCoords (const HYBRIDPlugin_Hypothesis* hyp)
2407 {  
2408   return hyp ? hyp->_GetEnforcedVerticesByCoords():TCoordsHYBRIDEnforcedVertexMap();
2409 }
2410
2411 HYBRIDPlugin_Hypothesis::TGeomEntryHYBRIDEnforcedVertexMap HYBRIDPlugin_Hypothesis::GetEnforcedVerticesByEntry (const HYBRIDPlugin_Hypothesis* hyp)
2412 {  
2413   return hyp ? hyp->_GetEnforcedVerticesByEntry():TGeomEntryHYBRIDEnforcedVertexMap();
2414 }
2415
2416 HYBRIDPlugin_Hypothesis::TIDSortedNodeGroupMap HYBRIDPlugin_Hypothesis::GetEnforcedNodes(const HYBRIDPlugin_Hypothesis* hyp)
2417 {
2418   return hyp ? hyp->_GetEnforcedNodes():TIDSortedNodeGroupMap();
2419 }
2420
2421 HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap HYBRIDPlugin_Hypothesis::GetEnforcedEdges(const HYBRIDPlugin_Hypothesis* hyp)
2422 {
2423   return hyp ? hyp->_GetEnforcedEdges():TIDSortedElemGroupMap();
2424 }
2425
2426 HYBRIDPlugin_Hypothesis::TIDSortedElemGroupMap HYBRIDPlugin_Hypothesis::GetEnforcedTriangles(const HYBRIDPlugin_Hypothesis* hyp)
2427 {
2428   return hyp ? hyp->_GetEnforcedTriangles():TIDSortedElemGroupMap();
2429 }
2430
2431 HYBRIDPlugin_Hypothesis::TID2SizeMap HYBRIDPlugin_Hypothesis::GetNodeIDToSizeMap(const HYBRIDPlugin_Hypothesis* hyp)
2432 {
2433   return hyp ? hyp->_GetNodeIDToSizeMap():TID2SizeMap();
2434 }
2435
2436 HYBRIDPlugin_Hypothesis::TSetStrings HYBRIDPlugin_Hypothesis::GetGroupsToRemove(const HYBRIDPlugin_Hypothesis* hyp)
2437 {
2438   return hyp ? hyp->_GetGroupsToRemove():TSetStrings();
2439 }