Salome HOME
updated copyright message
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_Hypothesis.cxx
1 // Copyright (C) 2007-2023  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    : BLSURFPlugin_Hypothesis.cxx
22 // Authors : Francis KLOSS (OCC) & Patrick LAUG (INRIA) & Lioka RAZAFINDRAZAKA (CEA)
23 //           & Aurelien ALLEAUME (DISTENE)
24 //           Size maps development: Nicolas GEIMER (OCC) & Gilles DAVID (EURIWARE)
25 // ---
26 //
27 #include "BLSURFPlugin_Hypothesis.hxx"
28 #include "BLSURFPlugin_Attractor.hxx"
29
30 #include <SMESHDS_Group.hxx>
31 #include <SMESHDS_Mesh.hxx>
32 #include <SMESH_BoostTxtArchive.hxx>
33 #include <SMESH_Gen_i.hxx>
34 #include <SMESH_Group.hxx>
35 #include <SMESH_TryCatch.hxx>
36
37 #include <Basics_Utils.hxx>
38 #include <utilities.h>
39
40 // cascade include
41 #include <ShapeAnalysis.hxx>
42
43 // CORBA includes
44 #include CORBA_CLIENT_HEADER(SALOMEDS)
45 #include CORBA_CLIENT_HEADER(GEOM_Gen)
46
47 #include <meshgems/meshgems.h>
48 #define MESHGEMS_VERSION_HEX (MESHGEMS_VERSION_MAJOR << 16 | MESHGEMS_VERSION_MINOR << 8 | MESHGEMS_VERSION_PATCH)
49
50 #include <boost/archive/text_oarchive.hpp>
51 #include <boost/serialization/set.hpp>
52 #include <boost/serialization/vector.hpp>
53 #include <boost/serialization/string.hpp>
54
55 namespace
56 {
57   struct GET_DEFAULT // struct used to get default value from GetOptionValue()
58   {
59     bool isDefault;
60     operator bool* () { return &isDefault; }
61   };
62 }
63
64 //=============================================================================
65 BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, SMESH_Gen * gen, bool hasgeom) :
66   SMESH_Hypothesis(hypId, gen),
67   _physicalMesh(GetDefaultPhysicalMesh()),
68   _geometricMesh(GetDefaultGeometricMesh()),
69   _phySize(GetDefaultPhySize()),
70   _phySizeRel(GetDefaultPhySizeRel()),
71   _minSize(GetDefaultMinSize()),
72   _maxSize(GetDefaultMaxSize()),
73   _minSizeRel(GetDefaultMinSizeRel()),
74   _maxSizeRel(GetDefaultMaxSizeRel()),
75   _useGradation(GetDefaultUseGradation()),
76   _gradation(GetDefaultGradation()),
77   _useVolumeGradation(GetDefaultUseVolumeGradation()),
78   _volumeGradation(GetDefaultVolumeGradation()),
79   _elementType(GetDefaultElementType()),
80   _angleMesh(GetDefaultAngleMesh()),
81   _chordalError(GetDefaultChordalError()),
82   _anisotropic(GetDefaultAnisotropic()),
83   _anisotropicRatio(GetDefaultAnisotropicRatio()),
84   _removeTinyEdges(GetDefaultRemoveTinyEdges()),
85   _tinyEdgeLength(GetDefaultTinyEdgeLength()),
86   _optimiseTinyEdges(GetDefaultOptimiseTinyEdges()),
87   _tinyEdgeOptimisationLength(GetDefaultTinyEdgeOptimisationLength()),
88   _correctSurfaceIntersec(GetDefaultCorrectSurfaceIntersection()),
89   _corrSurfaceIntersCost(GetDefaultCorrectSurfaceIntersectionMaxCost()),
90   _badElementRemoval(GetDefaultBadElementRemoval()),
91   _badElementAspectRatio(GetDefaultBadElementAspectRatio()),
92   _optimizeMesh(GetDefaultOptimizeMesh()),
93   _quadraticMesh(GetDefaultQuadraticMesh()),
94   _verb(GetDefaultVerbosity()),
95   _topology(GetDefaultTopology()),
96   _useSurfaceProximity(GetDefaultUseSurfaceProximity()),
97   _nbSurfaceProximityLayers(GetDefaultNbSurfaceProximityLayers()),
98   _surfaceProximityRatio(GetDefaultSurfaceProximityRatio()),
99   _useVolumeProximity(GetDefaultUseVolumeProximity()),
100   _nbVolumeProximityLayers(GetDefaultNbVolumeProximityLayers()),
101   _volumeProximityRatio(GetDefaultVolumeProximityRatio()),
102   _preCADMergeEdges(GetDefaultPreCADMergeEdges()),
103   _preCADRemoveDuplicateCADFaces(GetDefaultPreCADRemoveDuplicateCADFaces()),
104   _preCADProcess3DTopology(GetDefaultPreCADProcess3DTopology()),
105   _preCADDiscardInput(GetDefaultPreCADDiscardInput()),
106   _sizeMap(GetDefaultSizeMap()),
107   _attractors(GetDefaultSizeMap()),
108   _classAttractors(GetDefaultAttractorMap()),
109   _faceEntryEnfVertexListMap(GetDefaultFaceEntryEnfVertexListMap()),
110   _enfVertexList(GetDefaultEnfVertexList()),
111   _faceEntryCoordsListMap(GetDefaultFaceEntryCoordsListMap()),
112   _coordsEnfVertexMap(GetDefaultCoordsEnfVertexMap()),
113   _faceEntryEnfVertexEntryListMap(GetDefaultFaceEntryEnfVertexEntryListMap()),
114   _enfVertexEntryEnfVertexMap(GetDefaultEnfVertexEntryEnfVertexMap()),
115   _groupNameNodeIDMap(GetDefaultGroupNameNodeIDMap()),
116   _enforcedInternalVerticesAllFaces(GetDefaultInternalEnforcedVertex()),
117   _preCadFacesPeriodicityVector(GetDefaultPreCadFacesPeriodicityVector()),
118   _preCadEdgesPeriodicityVector(GetDefaultPreCadEdgesPeriodicityVector()),
119   _GMFFileName(GetDefaultGMFFile())
120 {
121   _name = GetHypType(hasgeom);
122   _param_algo_dim = 2;
123
124   // Advanced options with their defaults according to MG User Manual
125
126   const char* boolOptionNames[] = {
127 #if MESHGEMS_VERSION_HEX < 0x020A00
128     "enforce_cad_edge_sizes",                   // default = 0 // Deprecated since MeshGems 2.10
129 #endif
130     "jacobian_rectification_respect_geometry",  // default = 1
131     "rectify_jacobian",                         // default = 1
132     "respect_geometry",                         // default = 1
133     "tiny_edge_avoid_surface_intersections",    // default = 1
134     "debug",                                    // default = 0
135     "allow_patch_independent",                   // false
136     "" // mark of end
137   };
138
139   const char* intOptionNames[] = {
140 #if MESHGEMS_VERSION_HEX < 0x020A00
141     "max_number_of_points_per_patch",           // default = 100000 // Deprecated since MeshGems 2.10
142 #endif
143     "max_number_of_threads",                    // default = 4
144     "" // mark of end
145   };
146   const char* doubleOptionNames[] = {       // "surface_intersections_processing_max_cost",// default = 15
147                                             // "periodic_tolerance",                       // default = diag/100
148                                             // "volume_gradation",
149                                             // "tiny_edge_optimisation_length",            // default = diag * 1e-6
150     "" // mark of end
151   };
152   const char* charOptionNames[] = {         // "required_entities",                        // default = "respect"
153                                             // "tags",                                     // default = "respect"
154     "" // mark of end
155   };
156
157   // PreCAD advanced options
158   const char* preCADboolOptionNames[] = {   "closed_geometry",                          // default = 0
159                                             "discard_input_topology",                   // default = 0
160                                             "merge_edges",                              // default =  = 1
161                                             "remove_duplicate_cad_faces",               // default = 1
162                                             // "create_tag_on_collision",                  // default = 1
163                                             "process_3d_topology",                      // default = 1
164                                             // "remove_tiny_edges",                        // default = 0
165                                             // remove_tiny_uv_edges option is not documented
166                                             // but it is useful that the user can change it to disable all preprocessing options
167                                             "remove_tiny_uv_edges",                        // default = 1
168                                             "compute_ridges",                             // true
169                                             "" // mark of end
170       };
171   const char* preCADintOptionNames[] = {    // "manifold_geometry",                        // default = 0
172                                             "" // mark of end
173       };
174   const char* preCADdoubleOptionNames[] = { "periodic_tolerance",                       // default = diag * 1e-5
175                                             "sewing_tolerance",                         // default = diag * 5e-4
176                                             // "tiny_edge_length",                         // default = diag * 1e-5
177                                             "" // mark of end
178       };
179   const char* preCADcharOptionNames[] = {   "required_entities",                        // default = "respect"
180                                             "tags",                                     // default = "respect"
181                                             "" // mark of end
182       };
183   
184   int i = 0;
185   while (boolOptionNames[i][0])
186   {
187     _boolOptions.insert( boolOptionNames[i] );
188     _option2value[boolOptionNames[i++]].clear();
189   }
190   i = 0;
191   while (preCADboolOptionNames[i][0] && hasgeom)
192   {
193     _boolOptions.insert( preCADboolOptionNames[i] );
194     _preCADoption2value[preCADboolOptionNames[i++]].clear();
195   }
196   i = 0;
197   while (intOptionNames[i][0])
198     _option2value[intOptionNames[i++]].clear();
199   
200   i = 0;
201   while (preCADintOptionNames[i][0] && hasgeom)
202     _preCADoption2value[preCADintOptionNames[i++]].clear();
203
204   i = 0;
205   while (doubleOptionNames[i][0]) {
206     _doubleOptions.insert(doubleOptionNames[i]);
207     _option2value[doubleOptionNames[i++]].clear();
208   }
209   i = 0;
210   while (preCADdoubleOptionNames[i][0] && hasgeom) {
211     _preCADdoubleOptions.insert(preCADdoubleOptionNames[i]);
212     _preCADoption2value[preCADdoubleOptionNames[i++]].clear();
213   }
214   i = 0;
215   while (charOptionNames[i][0]) {
216     _charOptions.insert(charOptionNames[i]);
217     _option2value[charOptionNames[i++]].clear();
218   }
219   i = 0;
220   while (preCADcharOptionNames[i][0] && hasgeom) {
221     _preCADcharOptions.insert(preCADcharOptionNames[i]);
222     _preCADoption2value[preCADcharOptionNames[i++]].clear();
223   }
224
225   // default values to be used while MG meshing
226
227 #if MESHGEMS_VERSION_HEX < 0x020A00
228   _defaultOptionValues["enforce_cad_edge_sizes"                 ] = "no";  // Deprecated since MeshGems 2.10
229 #endif
230   _defaultOptionValues["jacobian_rectification_respect_geometry"] = "yes";
231 #if MESHGEMS_VERSION_HEX < 0x020A00
232   _defaultOptionValues["max_number_of_points_per_patch"         ] = "0";   // Deprecated since MeshGems 2.10
233 #endif
234   _defaultOptionValues["max_number_of_threads"                  ] = "4";
235   _defaultOptionValues["rectify_jacobian"                       ] = "yes";
236   _defaultOptionValues["respect_geometry"                       ] = "yes";
237   _defaultOptionValues["tiny_edge_avoid_surface_intersections"  ] = "yes";
238   //_defaultOptionValues["use_deprecated_patch_mesher"          ] = "no";
239   _defaultOptionValues["debug"                                  ] = "no";
240   _defaultOptionValues["allow_patch_independent"                ] = "no";
241   if ( hasgeom )
242   {
243     _defaultOptionValues["closed_geometry"                        ] = "no";
244     _defaultOptionValues["discard_input_topology"                 ] = "no";
245     _defaultOptionValues["merge_edges"                            ] = "no";
246     _defaultOptionValues["periodic_tolerance"                     ] = "1e-5*D";
247     _defaultOptionValues["process_3d_topology"                    ] = "no";
248     _defaultOptionValues["remove_duplicate_cad_faces"             ] = "no";
249     _defaultOptionValues["remove_tiny_uv_edges"                   ] = "no";
250     _defaultOptionValues["required_entities"                      ] = "respect";
251     _defaultOptionValues["sewing_tolerance"                       ] = "5e-4*D";
252     _defaultOptionValues["tags"                                   ] = "respect";
253     _defaultOptionValues["compute_ridges"                         ] = "yes";
254   }
255
256   if ( MESHGEMS_VERSION_HEX < 0x020906 )
257   {
258     std::string missingOption = "allow_patch_independent";
259     _defaultOptionValues.erase( missingOption );
260     _boolOptions.erase( missingOption );
261     _option2value.erase( missingOption );
262   }
263
264 #ifdef _DEBUG_
265   // check validity of option names of _defaultOptionValues
266   TOptionValues::iterator n2v = _defaultOptionValues.begin();
267   for ( ; n2v != _defaultOptionValues.end(); ++n2v )
268     ASSERT( _option2value.count( n2v->first ) || _preCADoption2value.count( n2v->first ));
269   ASSERT( _option2value.size() + _preCADoption2value.size() == _defaultOptionValues.size() );
270 #endif
271
272 }
273
274 TopoDS_Shape BLSURFPlugin_Hypothesis::entryToShape(std::string entry)
275 {
276   GEOM::GEOM_Object_var aGeomObj;
277   
278   TopoDS_Shape S = TopoDS_Shape();
279   SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->FindObjectID( entry.c_str() );
280   if (!aSObj->_is_nil() ) {
281     CORBA::Object_var obj = aSObj->GetObject();
282     aGeomObj = GEOM::GEOM_Object::_narrow(obj);
283     aSObj->UnRegister();
284   }
285   if ( !aGeomObj->_is_nil() )
286     S = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( aGeomObj.in() );
287   return S;
288 }
289
290 //=============================================================================
291 std::string BLSURFPlugin_Hypothesis::GetMeshGemsVersion()
292 {
293   return MESHGEMS_VERSION_LONG;
294 }
295
296 //=============================================================================
297 void BLSURFPlugin_Hypothesis::SetPhysicalMesh(PhysicalMesh thePhysicalMesh)
298 {
299   if (thePhysicalMesh != _physicalMesh) {
300     _physicalMesh = thePhysicalMesh;
301     NotifySubMeshesHypothesisModification();
302   }
303 }
304
305 //=============================================================================
306 void BLSURFPlugin_Hypothesis::SetGeometricMesh(GeometricMesh theGeometricMesh)
307 {
308   if (theGeometricMesh != _geometricMesh) {
309     _geometricMesh = theGeometricMesh;
310 //     switch (_geometricMesh) {
311 //       case DefaultGeom:
312 //       default:
313 //         _angleMesh = GetDefaultAngleMesh();
314 //         _gradation = GetDefaultGradation();
315 //         break;
316 //     }
317     NotifySubMeshesHypothesisModification();
318   }
319 }
320
321 //=============================================================================
322 void BLSURFPlugin_Hypothesis::SetPhySize(double theVal, bool isRelative)
323 {
324   if ((theVal != _phySize) || (isRelative != _phySizeRel)) {
325     _phySizeRel = isRelative;
326     if (theVal == 0) {
327       _phySize = GetMaxSize();
328     }
329     else
330       _phySize = theVal;
331     NotifySubMeshesHypothesisModification();
332   }
333 }
334
335 //=============================================================================
336 void BLSURFPlugin_Hypothesis::SetMinSize(double theMinSize, bool isRelative)
337 {
338   if ((theMinSize != _minSize) || (isRelative != _minSizeRel)) {
339     _minSizeRel = isRelative;
340     _minSize = theMinSize;
341     NotifySubMeshesHypothesisModification();
342   }
343 }
344
345 //=============================================================================
346 void BLSURFPlugin_Hypothesis::SetMaxSize(double theMaxSize, bool isRelative)
347 {
348   if ((theMaxSize != _maxSize) || (isRelative != _maxSizeRel)) {
349     _maxSizeRel = isRelative;
350     _maxSize = theMaxSize;
351     NotifySubMeshesHypothesisModification();
352   }
353 }
354
355 //=============================================================================
356 void BLSURFPlugin_Hypothesis::SetUseGradation(bool theVal)
357 {
358   if (theVal != _useGradation) {
359     _useGradation = theVal;
360     NotifySubMeshesHypothesisModification();
361   }
362 }
363
364 //=============================================================================
365 void BLSURFPlugin_Hypothesis::SetGradation(double theVal)
366 {
367   _useGradation = ( theVal > 0 );
368   if (theVal != _gradation) {
369     _gradation = theVal;
370     NotifySubMeshesHypothesisModification();
371   }
372 }
373
374 //=============================================================================
375 void BLSURFPlugin_Hypothesis::SetUseVolumeGradation(bool theVal)
376 {
377   if (theVal != _useVolumeGradation) {
378     _useVolumeGradation = theVal;
379     NotifySubMeshesHypothesisModification();
380   }
381 }
382
383 //=============================================================================
384 void BLSURFPlugin_Hypothesis::SetVolumeGradation(double theVal)
385 {
386   _useVolumeGradation = ( theVal > 0 );
387   if (theVal != _volumeGradation) {
388     _volumeGradation = theVal;
389     NotifySubMeshesHypothesisModification();
390   }
391 }
392
393 //=============================================================================
394 void BLSURFPlugin_Hypothesis::SetElementType(ElementType theElementType)
395 {
396   if (theElementType != _elementType) {
397     _elementType = theElementType;
398     NotifySubMeshesHypothesisModification();
399   }
400 }
401
402 //=============================================================================
403 void BLSURFPlugin_Hypothesis::SetAngleMesh(double theVal)
404 {
405   if (theVal != _angleMesh) {
406     _angleMesh = theVal;
407     NotifySubMeshesHypothesisModification();
408   }
409 }
410
411 //=============================================================================
412 void BLSURFPlugin_Hypothesis::SetChordalError(double theDistance)
413 {
414   if (theDistance != _chordalError) {
415     _chordalError = theDistance;
416     NotifySubMeshesHypothesisModification();
417   }
418 }
419
420 //=============================================================================
421 void BLSURFPlugin_Hypothesis::SetAnisotropic(bool theVal)
422 {
423   if (theVal != _anisotropic) {
424     _anisotropic = theVal;
425     NotifySubMeshesHypothesisModification();
426   }
427 }
428
429 //=============================================================================
430 void BLSURFPlugin_Hypothesis::SetAnisotropicRatio(double theVal)
431 {
432   if (theVal != _anisotropicRatio) {
433     _anisotropicRatio = theVal;
434     NotifySubMeshesHypothesisModification();
435   }
436 }
437
438 //=============================================================================
439 void BLSURFPlugin_Hypothesis::SetRemoveTinyEdges(bool theVal)
440 {
441   if (theVal != _removeTinyEdges) {
442     _removeTinyEdges = theVal;
443     NotifySubMeshesHypothesisModification();
444   }
445 }
446
447 //=============================================================================
448 void BLSURFPlugin_Hypothesis::SetTinyEdgeLength(double theVal)
449 {
450   if (theVal != _tinyEdgeLength) {
451     _tinyEdgeLength = theVal;
452     NotifySubMeshesHypothesisModification();
453   }
454 }
455
456 //=============================================================================
457 void BLSURFPlugin_Hypothesis::SetOptimiseTinyEdges(bool theVal)
458 {
459   if (theVal != _optimiseTinyEdges) {
460     _optimiseTinyEdges = theVal;
461     NotifySubMeshesHypothesisModification();
462   }
463 }
464
465 //=============================================================================
466 void BLSURFPlugin_Hypothesis::SetTinyEdgeOptimisationLength(double theVal)
467 {
468   if (theVal != _tinyEdgeOptimisationLength) {
469     _tinyEdgeOptimisationLength = theVal;
470     NotifySubMeshesHypothesisModification();
471   }
472 }
473
474 //=============================================================================
475 void BLSURFPlugin_Hypothesis::SetCorrectSurfaceIntersection(bool theVal)
476 {
477   if (theVal != _correctSurfaceIntersec) {
478     _correctSurfaceIntersec = theVal;
479     NotifySubMeshesHypothesisModification();
480   }
481 }
482
483 //=============================================================================
484 void BLSURFPlugin_Hypothesis::SetCorrectSurfaceIntersectionMaxCost(double theVal)
485 {
486   if (theVal != _corrSurfaceIntersCost) {
487     _corrSurfaceIntersCost = theVal;
488     NotifySubMeshesHypothesisModification();
489   }
490 }
491
492 //=============================================================================
493 void BLSURFPlugin_Hypothesis::SetBadElementRemoval(bool theVal)
494 {
495   if (theVal != _badElementRemoval) {
496     _badElementRemoval = theVal;
497     NotifySubMeshesHypothesisModification();
498   }
499 }
500
501 //=============================================================================
502 void BLSURFPlugin_Hypothesis::SetBadElementAspectRatio(double theVal)
503 {
504   if (theVal != _badElementAspectRatio) {
505     _badElementAspectRatio = theVal;
506     NotifySubMeshesHypothesisModification();
507   }
508 }
509
510 //=============================================================================
511 void BLSURFPlugin_Hypothesis::SetOptimizeMesh(bool theVal)
512 {
513   if (theVal != _optimizeMesh) {
514     _optimizeMesh = theVal;
515     NotifySubMeshesHypothesisModification();
516   }
517 }
518
519 //=============================================================================
520 void BLSURFPlugin_Hypothesis::SetQuadraticMesh(bool theVal)
521 {
522   if (theVal != _quadraticMesh) {
523     _quadraticMesh = theVal;
524     NotifySubMeshesHypothesisModification();
525   }
526 }
527
528 //=============================================================================
529 void BLSURFPlugin_Hypothesis::SetTopology(Topology theTopology)
530 {
531   if (theTopology != _topology) {
532     _topology = theTopology;
533     NotifySubMeshesHypothesisModification();
534   }
535 }
536
537 //=============================================================================
538 void BLSURFPlugin_Hypothesis::SetUseSurfaceProximity( bool toUse )
539 {
540   if ( _useSurfaceProximity != toUse )
541   {
542     _useSurfaceProximity = toUse;
543     NotifySubMeshesHypothesisModification();
544   }
545 }
546
547 //=============================================================================
548 void BLSURFPlugin_Hypothesis::SetNbSurfaceProximityLayers( int nbLayers )
549 {
550   if ( _nbSurfaceProximityLayers != nbLayers )
551   {
552     _nbSurfaceProximityLayers = nbLayers;
553     NotifySubMeshesHypothesisModification();
554   }
555 }
556
557 //=============================================================================
558 void BLSURFPlugin_Hypothesis::SetSurfaceProximityRatio( double ratio )
559 {
560   if ( _surfaceProximityRatio != ratio )
561   {
562     _surfaceProximityRatio = ratio;
563     NotifySubMeshesHypothesisModification();
564   }
565 }
566
567 //=============================================================================
568 void BLSURFPlugin_Hypothesis::SetUseVolumeProximity( bool toUse )
569 {
570   if ( _useVolumeProximity != toUse )
571   {
572     _useVolumeProximity = toUse;
573     NotifySubMeshesHypothesisModification();
574   }
575 }
576
577 //=============================================================================
578 void BLSURFPlugin_Hypothesis::SetNbVolumeProximityLayers( int nbLayers )
579 {
580   if ( _nbVolumeProximityLayers != nbLayers )
581   {
582     _nbVolumeProximityLayers = nbLayers;
583     NotifySubMeshesHypothesisModification();
584   }
585 }
586
587 //=============================================================================
588 void BLSURFPlugin_Hypothesis::SetVolumeProximityRatio( double ratio )
589 {
590   if ( _volumeProximityRatio != ratio )
591   {
592     _volumeProximityRatio = ratio;
593     NotifySubMeshesHypothesisModification();
594   }
595 }
596
597 //=============================================================================
598 void BLSURFPlugin_Hypothesis::SetVerbosity(int theVal) {
599   if (theVal != _verb) {
600     _verb = theVal;
601     NotifySubMeshesHypothesisModification();
602   }
603 }
604
605 //=============================================================================
606 void BLSURFPlugin_Hypothesis::SetEnforceCadEdgesSize( bool toEnforce )
607 {
608 #if MESHGEMS_VERSION_HEX < 0x020A00
609   // Deprecated since MeshGems 2.10
610   if ( GetEnforceCadEdgesSize() != toEnforce )
611   {
612     SetOptionValue( "enforce_cad_edge_sizes", toEnforce ? "yes" : "no" );
613     NotifySubMeshesHypothesisModification();
614   }
615 #else
616   (void)toEnforce; // maybe unused
617 #endif
618 }
619 //=============================================================================
620 bool BLSURFPlugin_Hypothesis::GetEnforceCadEdgesSize()
621 {
622 #if MESHGEMS_VERSION_HEX < 0x020A00
623   // Deprecated since MeshGems 2.10
624   return ToBool( GetOptionValue( "enforce_cad_edge_sizes" ), GET_DEFAULT() );
625 #else
626   return false;
627 #endif
628 }
629 //=============================================================================
630
631 void BLSURFPlugin_Hypothesis::SetJacobianRectificationRespectGeometry( bool allowRectification )
632 {
633   if ( GetJacobianRectificationRespectGeometry() != allowRectification )
634   {
635     SetOptionValue("jacobian_rectification_respect_geometry", allowRectification ? "yes" : "no" );
636     NotifySubMeshesHypothesisModification();
637   }
638 }
639 //=============================================================================
640 bool BLSURFPlugin_Hypothesis::GetJacobianRectificationRespectGeometry()
641 {
642   return ToBool( GetOptionValue("jacobian_rectification_respect_geometry", GET_DEFAULT()));
643 }
644 //=============================================================================
645
646 void BLSURFPlugin_Hypothesis::SetJacobianRectification( bool allowRectification )
647 {
648   if ( GetJacobianRectification() != allowRectification )
649   {
650     SetOptionValue( "rectify_jacobian", allowRectification ? "yes" : "no" );
651     NotifySubMeshesHypothesisModification();
652   }
653 }
654 //=============================================================================
655 bool BLSURFPlugin_Hypothesis::GetJacobianRectification()
656 {
657   return ToBool( GetOptionValue("rectify_jacobian", GET_DEFAULT()));
658 }
659 //=============================================================================
660
661 void BLSURFPlugin_Hypothesis::SetUseDeprecatedPatchMesher( bool /*useDeprecatedPatchMesher*/ )
662 {
663   // if ( GetUseDeprecatedPatchMesher() != useDeprecatedPatchMesher )
664   // {
665   //   SetOptionValue( "use_deprecated_patch_mesher", useDeprecatedPatchMesher ? "yes" : "no" );
666   //   NotifySubMeshesHypothesisModification();
667   // }
668 }
669 //=============================================================================
670 bool BLSURFPlugin_Hypothesis::GetUseDeprecatedPatchMesher()
671 {
672   return false;//ToBool( GetOptionValue("use_deprecated_patch_mesher", GET_DEFAULT()));
673 }
674 //=============================================================================
675
676 void BLSURFPlugin_Hypothesis::SetMaxNumberOfPointsPerPatch( int nb )
677 {
678 #if MESHGEMS_VERSION_HEX < 0x020A00
679   // Deprecated since MeshGems 2.10
680   if ( nb < 0 )
681     throw std::invalid_argument( SMESH_Comment("Invalid number of points: ") << nb );
682
683   if ( GetMaxNumberOfPointsPerPatch() != nb )
684   {
685     SetOptionValue("max_number_of_points_per_patch", SMESH_Comment( nb ));
686     NotifySubMeshesHypothesisModification();
687   }
688 #else
689   (void)nb; // maybe unused
690 #endif
691 }
692 //=============================================================================
693 int BLSURFPlugin_Hypothesis::GetMaxNumberOfPointsPerPatch()
694 {
695 #if MESHGEMS_VERSION_HEX < 0x020A00
696   // Deprecated since MeshGems 2.10
697   return ToInt( GetOptionValue("max_number_of_points_per_patch", GET_DEFAULT()));
698 #else
699   return 0;
700 #endif
701 }
702 //=============================================================================
703
704 void BLSURFPlugin_Hypothesis::SetMaxNumberOfThreads( int nb )
705 {
706   if ( nb < 0 )
707     throw std::invalid_argument( SMESH_Comment("Invalid number of threads: ") << nb );
708
709   if ( GetMaxNumberOfThreads() != nb )
710   {
711     SetOptionValue("max_number_of_threads", SMESH_Comment( nb ));
712     NotifySubMeshesHypothesisModification();
713   }
714 }
715 //=============================================================================
716 int BLSURFPlugin_Hypothesis::GetMaxNumberOfThreads()
717 {
718   return ToInt( GetOptionValue("max_number_of_threads", GET_DEFAULT()));
719 }
720 //=============================================================================
721
722 void BLSURFPlugin_Hypothesis::SetRespectGeometry( bool toRespect )
723 {
724   if ( GetRespectGeometry() != toRespect )
725   {
726     SetOptionValue("respect_geometry", toRespect ? "yes" : "no" );
727     NotifySubMeshesHypothesisModification();
728   }
729 }
730 //=============================================================================
731 bool BLSURFPlugin_Hypothesis::GetRespectGeometry()
732 {
733   return ToBool( GetOptionValue( "respect_geometry", GET_DEFAULT()));
734 }
735 //=============================================================================
736
737 void BLSURFPlugin_Hypothesis::SetTinyEdgesAvoidSurfaceIntersections( bool toAvoidIntersection )
738 {
739   if ( GetTinyEdgesAvoidSurfaceIntersections() != toAvoidIntersection )
740   {
741     SetOptionValue("tiny_edge_avoid_surface_intersections", toAvoidIntersection ? "yes" : "no" );
742     NotifySubMeshesHypothesisModification();
743   }
744 }
745 //=============================================================================
746 bool BLSURFPlugin_Hypothesis::GetTinyEdgesAvoidSurfaceIntersections()
747 {
748   return ToBool( GetOptionValue("tiny_edge_avoid_surface_intersections", GET_DEFAULT()));
749 }
750 //=============================================================================
751
752 void BLSURFPlugin_Hypothesis::SetClosedGeometry( bool isClosed )
753 {
754   if ( GetClosedGeometry() != isClosed )
755   {
756     SetPreCADOptionValue("closed_geometry", isClosed ? "yes" : "no" );
757     NotifySubMeshesHypothesisModification();
758   }
759 }
760 //=============================================================================
761 bool BLSURFPlugin_Hypothesis::GetClosedGeometry()
762 {
763   return ToBool( GetPreCADOptionValue( "closed_geometry", GET_DEFAULT()));
764 }
765 //=============================================================================
766
767 void BLSURFPlugin_Hypothesis::SetDebug( bool isDebug )
768 {
769   if ( GetDebug() != isDebug )
770   {
771     SetPreCADOptionValue("debug", isDebug ? "yes" : "no" );
772     NotifySubMeshesHypothesisModification();
773   }
774 }
775 //=============================================================================
776 bool BLSURFPlugin_Hypothesis::GetDebug()
777 {
778   return ToBool( GetPreCADOptionValue("debug", GET_DEFAULT()));
779 }
780 //=============================================================================
781
782 void BLSURFPlugin_Hypothesis::SetPeriodicTolerance( CORBA::Double tol )
783 {
784   if ( tol <= 0 )
785     throw std::invalid_argument( SMESH_Comment("Invalid tolerance: ") << tol );
786   if ( GetPeriodicTolerance() != tol )
787   {
788     SetPreCADOptionValue("periodic_tolerance", SMESH_Comment( tol ) );
789     NotifySubMeshesHypothesisModification();
790   }
791 }
792 //=============================================================================
793 double BLSURFPlugin_Hypothesis::GetPeriodicTolerance()
794 {
795   return ToDbl( GetPreCADOptionValue( "periodic_tolerance", GET_DEFAULT()));
796 }
797 //=============================================================================
798
799 void BLSURFPlugin_Hypothesis::SetRequiredEntities( const std::string& howToTreat )
800 {
801   if ( howToTreat != "respect" && howToTreat != "ignore" && howToTreat != "clear"  )
802     throw std::invalid_argument
803       ( SMESH_Comment("required_entities must be in ['respect','ignore','clear'] "));
804
805   if ( GetRequiredEntities() != howToTreat )
806   {
807     SetPreCADOptionValue("required_entities", howToTreat );
808     NotifySubMeshesHypothesisModification();
809   }
810 }
811 //=============================================================================
812 std::string BLSURFPlugin_Hypothesis::GetRequiredEntities()
813 {
814   return GetPreCADOptionValue("required_entities", GET_DEFAULT());
815 }
816 //=============================================================================
817
818 void BLSURFPlugin_Hypothesis::SetSewingTolerance( CORBA::Double tol )
819 {
820   if ( tol <= 0 )
821     throw std::invalid_argument( SMESH_Comment("Invalid tolerance: ") << tol );
822   if ( GetSewingTolerance() != tol )
823   {
824     SetPreCADOptionValue("sewing_tolerance", SMESH_Comment( tol ) );
825     NotifySubMeshesHypothesisModification();
826   }
827 }
828 //=============================================================================
829 CORBA::Double BLSURFPlugin_Hypothesis::GetSewingTolerance()
830 {
831   return ToDbl( GetPreCADOptionValue("sewing_tolerance", GET_DEFAULT()));
832 }
833 //=============================================================================
834
835 void BLSURFPlugin_Hypothesis::SetTags( const std::string& howToTreat )
836 {
837   if ( howToTreat != "respect" && howToTreat != "ignore" && howToTreat != "clear"  )
838     throw std::invalid_argument
839       ( SMESH_Comment("'tags' must be in ['respect','ignore','clear'] "));
840
841   if ( GetTags() != howToTreat )
842   {
843     SetPreCADOptionValue("tags", howToTreat );
844     NotifySubMeshesHypothesisModification();
845   }
846 }
847 //=============================================================================
848 std::string BLSURFPlugin_Hypothesis::GetTags()
849 {
850   return GetPreCADOptionValue("tags", GET_DEFAULT());
851 }
852
853 //=============================================================================
854 void BLSURFPlugin_Hypothesis::SetHyperPatches(const THyperPatchList& hpl, bool notifyMesh)
855 {
856   if ( hpl != _hyperPatchList )
857   {
858     // join patches sharing tags
859     _hyperPatchList.clear();
860     for ( size_t i = 0; i < hpl.size(); ++i )
861     {
862       const THyperPatchTags& tags = hpl[i];
863       if ( tags.size() < 2 ) continue;
864
865       std::set<int> iPatches;
866       if ( !_hyperPatchList.empty() )
867       {
868         THyperPatchTags::iterator t = tags.begin();
869         for ( ; t != tags.end(); ++t )
870         {
871           int iPatch = -1;
872           GetHyperPatchTag( *t, this, &iPatch );
873           if ( iPatch >= 0 )
874             iPatches.insert( iPatch );
875         }
876       }
877
878       if ( iPatches.empty() )
879       {
880         _hyperPatchList.push_back( tags );
881       }
882       else
883       {
884         std::set<int>::iterator iPatch = iPatches.begin();
885         THyperPatchTags&     mainPatch = _hyperPatchList[ *iPatch ];
886         mainPatch.insert( tags.begin(), tags.end() );
887
888         for ( ++iPatch; iPatch != iPatches.end(); ++iPatch )
889         {
890           mainPatch.insert( _hyperPatchList[ *iPatch ].begin(), _hyperPatchList[ *iPatch ].end() );
891           _hyperPatchList[ *iPatch ].clear();
892         }
893         if ( iPatches.size() > 1 )
894           for ( int j = (int) _hyperPatchList.size()-1; j > 0; --j )
895             if ( _hyperPatchList[j].empty() )
896               _hyperPatchList.erase( _hyperPatchList.begin() + j );
897       }
898     }
899     if ( notifyMesh )
900       NotifySubMeshesHypothesisModification();
901   }
902 }
903 //=============================================================================
904 void BLSURFPlugin_Hypothesis::SetHyperPatches(const THyperPatchEntriesList& hpel)
905 {
906   if ( hpel != _hyperPatchEntriesList )
907   {
908     _hyperPatchEntriesList = hpel;
909     _hyperPatchList.clear();
910
911     NotifySubMeshesHypothesisModification();
912   }
913 }
914 //================================================================================
915 /*!
916  * \brief Set _hyperPatchList by _hyperPatchEntriesList
917  */
918 //================================================================================
919
920 void BLSURFPlugin_Hypothesis::
921 SetHyperPatchIDsByEntry( const TopoDS_Shape&                          mainShape,
922                          const std::map< std::string, TopoDS_Shape >& entryToShape)
923 {
924   _hyperPatchList.clear();
925   if ( _hyperPatchEntriesList.empty() || mainShape.IsNull() )
926     return;
927
928   _hyperPatchList.resize( _hyperPatchEntriesList.size() );
929
930   TopTools_IndexedMapOfShape shapeMap;
931   TopExp::MapShapes( mainShape, shapeMap );
932
933   for ( size_t i = 0; i < _hyperPatchEntriesList.size(); ++i )
934   {
935     THyperPatchTags &            idsList = _hyperPatchList       [ i ];
936     const THyperPatchEntries & entryList = _hyperPatchEntriesList[ i ];
937     for ( const std::string & entry : entryList )
938     {
939       auto e2sIt = entryToShape.find( entry );
940       if ( e2sIt != entryToShape.end() )
941       {
942         for ( TopExp_Explorer fExp( e2sIt->second, TopAbs_FACE ); fExp.More(); fExp.Next() )
943         {
944           int id = shapeMap.FindIndex( fExp.Current() );
945           if ( id > 0 )
946             idsList.insert( id );
947         }
948       }
949     }
950   }
951   THyperPatchList hpl;
952   hpl.swap( _hyperPatchList );
953   SetHyperPatches( hpl, /*notifyMesh=*/false );
954 }
955
956 //=============================================================================
957 /*!
958  * \brief Return a tag of a face taking into account the hyper-patches. Optionally
959  *        return an index of a patch including the face
960  */
961 //================================================================================
962
963 int BLSURFPlugin_Hypothesis::GetHyperPatchTag( const int                      faceTag,
964                                                const BLSURFPlugin_Hypothesis* hyp,
965                                                int*                           iPatch)
966 {
967   if ( hyp )
968   {
969     const THyperPatchList& hpl = hyp->_hyperPatchList;
970     for ( size_t i = 0; i < hpl.size(); ++i )
971       if ( hpl[i].count( faceTag ))
972       {
973         if ( iPatch ) *iPatch = (int) i;
974         return *( hpl[i].begin() );
975       }
976   }
977   return faceTag;
978 }
979
980 //=============================================================================
981 void BLSURFPlugin_Hypothesis::SetEnforcedMeshes( std::vector< EnforcedMesh > & enforcedMeshes )
982 {
983   if ( _enforcedMeshes != enforcedMeshes )
984   {
985     _enforcedMeshes.swap( enforcedMeshes );
986     NotifySubMeshesHypothesisModification();
987   }
988 }
989
990 //================================================================================
991 /*!
992  * \brief Return elements of 1D enforced mesh. Result can be NULL
993  */
994 //================================================================================
995
996 SMDS_ElemIteratorPtr
997 BLSURFPlugin_Hypothesis::GetEnforcedSegments( const EnforcedMesh& enfMesh,
998                                               SMESH_Mesh* &       mesh ) const
999 {
1000   SMDS_ElemIteratorPtr it;
1001   if (( mesh = SMESH_Hypothesis::GetMeshByPersistentID( enfMesh._meshID )))
1002   {
1003     mesh->Load();
1004     if ( mesh->NbEdges() == 0 )
1005       GetGen()->Compute( *mesh, mesh->GetShapeToMesh(), /*flags=*/0 );
1006
1007     switch( enfMesh._type )
1008     {
1009     case ENFORCED_MESH:
1010       it = mesh->GetMeshDS()->elementsIterator( SMDSAbs_Edge );
1011       break;
1012
1013     case ENFORCED_GROUP:
1014       if ( SMESH_Group* grp = mesh->GetGroup( enfMesh._subID ))
1015       {
1016         if ( grp->GetGroupDS()->GetType() == SMDSAbs_Edge )
1017           it = grp->GetGroupDS()->GetElements();
1018       }
1019       break;
1020
1021     case ENFORCED_SUBMESH:
1022       if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining( enfMesh._subID ))
1023         if ( SMESHDS_SubMesh * smDS = sm->GetSubMeshDS() )
1024         {
1025           it = smDS->GetElements();
1026           if ( it->more() && it->next()->GetType() != SMDSAbs_Edge )
1027             it = SMDS_ElemIteratorPtr();
1028           else
1029             it = smDS->GetElements();
1030         }
1031       break;
1032     }
1033   }
1034   return it;
1035 }
1036
1037
1038 //=============================================================================
1039 void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal)
1040 {
1041   if (theVal != ToBool( GetPreCADOptionValue("merge_edges", GET_DEFAULT()))) {
1042     _preCADMergeEdges = theVal;
1043     SetPreCADOptionValue("merge_edges", theVal ? "yes" : "no" );
1044     NotifySubMeshesHypothesisModification();
1045   }
1046 }
1047
1048 //=============================================================================
1049 void BLSURFPlugin_Hypothesis::SetPreCADRemoveDuplicateCADFaces(bool theVal)
1050 {
1051   if (theVal != ToBool( GetPreCADOptionValue("remove_duplicate_cad_faces", GET_DEFAULT()))) {
1052     _preCADRemoveDuplicateCADFaces = theVal;
1053     SetPreCADOptionValue("remove_duplicate_cad_faces", theVal ? "yes" : "no" );
1054     NotifySubMeshesHypothesisModification();
1055   }
1056 }
1057
1058 //=============================================================================
1059 void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal)
1060 {
1061   if (theVal != ToBool( GetPreCADOptionValue("process_3d_topology", GET_DEFAULT()))) {
1062     _preCADProcess3DTopology = theVal;
1063     SetPreCADOptionValue("process_3d_topology", theVal ? "yes" : "no" );
1064     NotifySubMeshesHypothesisModification();
1065   }
1066 }
1067
1068 //=============================================================================
1069 void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal)
1070 {
1071   if (theVal != ToBool( GetPreCADOptionValue("discard_input_topology", GET_DEFAULT()))) {
1072     _preCADDiscardInput = theVal;
1073     SetPreCADOptionValue("discard_input_topology", theVal ? "yes" : "no" );
1074     NotifySubMeshesHypothesisModification();
1075   }
1076 }
1077
1078 //=============================================================================
1079 // Return true if any PreCAD option is activated
1080 bool BLSURFPlugin_Hypothesis::HasPreCADOptions(const BLSURFPlugin_Hypothesis* hyp)
1081 {
1082   if ( !hyp || hyp->_name == GetHypType(/*hasgeom=*/false))
1083   {
1084     return false;
1085   }
1086   bool orDefault, isOk;
1087   return ( ToBool( hyp->GetPreCADOptionValue("closed_geometry"           , &orDefault )) ||
1088            ToBool( hyp->GetPreCADOptionValue("discard_input_topology"    , &orDefault )) ||
1089            ToBool( hyp->GetPreCADOptionValue("merge_edges"               , &orDefault )) ||
1090            ToBool( hyp->GetPreCADOptionValue("remove_duplicate_cad_faces", &orDefault )) ||
1091            ToBool( hyp->GetPreCADOptionValue("process_3d_topology"       , &orDefault )) ||
1092            ToBool( hyp->GetPreCADOption     ("manifold_geometry")        , &isOk       ) ||
1093            hyp->GetPreCADOptionValue("sewing_tolerance", &orDefault ) != "5e-4*D"        ||
1094            !hyp->_preCadFacesPeriodicityVector.empty()                                   ||
1095            !hyp->_preCadEdgesPeriodicityVector.empty()                                   ||
1096            !hyp->_facesPeriodicityVector.empty()                                         ||
1097            !hyp->_edgesPeriodicityVector.empty()                                         ||
1098            !hyp->_verticesPeriodicityVector.empty()                                      ||
1099            !hyp->GetHyperPatches().empty()                                               ||
1100            hyp->GetTopology() != FromCAD );
1101 }
1102
1103 //=============================================================================
1104 // void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName, bool isBinary)
1105 void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName)
1106 {
1107   _GMFFileName = theFileName;
1108   //   _GMFFileMode = isBinary;
1109   NotifySubMeshesHypothesisModification();
1110 }
1111
1112 //=============================================================================
1113 void BLSURFPlugin_Hypothesis::SetOptionValue(const std::string& optionName, const std::string& optionValue)
1114 {
1115   TOptionValues::iterator op_val = _option2value.find(optionName);
1116   if (op_val == _option2value.end())
1117   {
1118     op_val = _preCADoption2value.find(optionName);
1119     if (op_val == _preCADoption2value.end())
1120     {
1121       std::string msg = "Unknown MG-CADSurf option: '" + optionName + "'. Try SetAdvancedOption()";
1122       throw std::invalid_argument(msg);
1123     }
1124   }
1125   if (op_val->second != optionValue)
1126   {
1127     const char* ptr = optionValue.c_str();
1128     // strip white spaces
1129     while (ptr[0] == ' ')
1130       ptr++;
1131     size_t i = strlen(ptr);
1132     while (i != 0 && ptr[i - 1] == ' ')
1133       i--;
1134     // check value type
1135     bool typeOk = true;
1136     std::string typeName;
1137     if (i == 0) {
1138       // empty string
1139     } else if (_charOptions.count(optionName)) {
1140       // do not check strings
1141     } else if (_doubleOptions.count(optionName)) {
1142       // check if value is double
1143       ToDbl(ptr, &typeOk);
1144       typeName = "real";
1145     } else if (_boolOptions.count(optionName)) {
1146       // check if value is bool
1147       ToBool(ptr, &typeOk);
1148       typeName = "bool";
1149     } else {
1150       // check if value is int
1151       ToInt(ptr, &typeOk);
1152       typeName = "integer";
1153     }
1154     if (!typeOk) {
1155       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
1156       throw std::invalid_argument(msg);
1157     }
1158     std::string value( ptr, i );
1159     if ( _defaultOptionValues[ optionName ] == value )
1160       value.clear();
1161
1162     op_val->second = value;
1163
1164     NotifySubMeshesHypothesisModification();
1165   }
1166 }
1167
1168 //=============================================================================
1169 void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName, const std::string& optionValue)
1170 {
1171   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
1172   if (op_val == _preCADoption2value.end()) {
1173     op_val = _option2value.find(optionName);
1174     if (op_val == _option2value.end()) {
1175       std::string msg = "Unknown MG-PreCAD option: '" + optionName + "'. Try SetAdvancedOption()";
1176       throw std::invalid_argument(msg);
1177     }
1178   }
1179   if (op_val->second != optionValue)
1180   {
1181     const char* ptr = optionValue.c_str();
1182     // strip white spaces
1183     while (ptr[0] == ' ')
1184       ptr++;
1185     size_t i = strlen(ptr);
1186     while (i != 0 && ptr[i - 1] == ' ')
1187       i--;
1188     // check value type
1189     bool typeOk = true;
1190     std::string typeName;
1191     if (i == 0) {
1192       // empty string
1193     } else if (_preCADcharOptions.find(optionName) != _preCADcharOptions.end()) {
1194       // do not check strings
1195     } else if (_preCADdoubleOptions.find(optionName) != _preCADdoubleOptions.end()) {
1196       // check if value is double
1197       char * endPtr;
1198       strtod(ptr, &endPtr);
1199       typeOk = (ptr != endPtr);
1200       typeName = "real";
1201     } else if (_boolOptions.count(optionName)) {
1202       // check if value is bool
1203       ToBool(ptr, &typeOk);
1204       typeName = "bool";
1205     } else {
1206       // check if value is int
1207       char * endPtr;
1208       strtol(ptr, &endPtr, 10);
1209       typeOk = (ptr != endPtr);
1210       typeName = "integer";
1211     }
1212     if (!typeOk) {
1213       std::string msg = "PreCAD advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
1214       throw std::invalid_argument(msg);
1215     }
1216     std::string value( ptr, i );
1217     if ( _defaultOptionValues[ optionName ] == value )
1218       value.clear();
1219
1220     op_val->second = value;
1221
1222     NotifySubMeshesHypothesisModification();
1223   }
1224 }
1225
1226 //=============================================================================
1227 std::string BLSURFPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
1228                                                     bool*              isDefault) const
1229 {
1230   TOptionValues::const_iterator op_val = _option2value.find(optionName);
1231   if (op_val == _option2value.end())
1232   {
1233     op_val = _preCADoption2value.find(optionName);
1234     if (op_val == _preCADoption2value.end())
1235     {
1236       op_val = _customOption2value.find(optionName);
1237       if (op_val == _customOption2value.end())
1238       {
1239         std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
1240         throw std::invalid_argument(msg);
1241       }
1242     }
1243   }
1244   std::string val = op_val->second;
1245   if ( isDefault ) *isDefault = ( val.empty() );
1246
1247   if ( val.empty() && isDefault )
1248   {
1249     op_val = _defaultOptionValues.find( optionName );
1250     if (op_val != _defaultOptionValues.end())
1251       val = op_val->second;
1252   }
1253   return val;
1254 }
1255
1256 //=============================================================================
1257 std::string BLSURFPlugin_Hypothesis::GetPreCADOptionValue(const std::string& optionName,
1258                                                           bool*              isDefault) const
1259 {
1260   TOptionValues::const_iterator op_val = _preCADoption2value.find(optionName);
1261   if (op_val == _preCADoption2value.end())
1262   {
1263     op_val = _option2value.find(optionName);
1264     if (op_val == _option2value.end())
1265     {
1266       op_val = _customOption2value.find(optionName);
1267       if (op_val == _customOption2value.end())
1268       {
1269         std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
1270         throw std::invalid_argument(msg);
1271       }
1272     }
1273   }
1274   std::string val = op_val->second;
1275   if ( isDefault ) *isDefault = ( val.empty() );
1276
1277   if ( val.empty() && isDefault )
1278   {
1279     op_val = _defaultOptionValues.find( optionName );
1280     if (op_val != _defaultOptionValues.end())
1281       val = op_val->second;
1282   }
1283   return val;
1284 }
1285
1286 //=============================================================================
1287 void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName)
1288 {
1289   TOptionValues::iterator op_val = _customOption2value.find(optionName);
1290   if (op_val != _customOption2value.end())
1291    _customOption2value.erase(op_val);
1292   else {
1293     op_val = _option2value.find(optionName);
1294     if (op_val != _option2value.end())
1295       op_val->second.clear();
1296     else {
1297       op_val = _preCADoption2value.find(optionName);
1298       if (op_val != _preCADoption2value.end())
1299         op_val->second.clear();
1300     }
1301   }
1302 }
1303
1304 //=============================================================================
1305 void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName)
1306 {
1307   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
1308   if (op_val != _preCADoption2value.end())
1309     op_val->second.clear();
1310 }
1311
1312 //=============================================================================
1313 void BLSURFPlugin_Hypothesis::AddOption(const std::string& optionName, const std::string& optionValue)
1314 {
1315   bool modif = true;
1316   TOptionValues::iterator op_val = _option2value.find(optionName);
1317   if (op_val != _option2value.end())
1318   {
1319     if (op_val->second != optionValue)
1320       op_val->second = optionValue;
1321     else
1322       modif = false;
1323   }
1324   else
1325   {
1326     op_val = _preCADoption2value.find(optionName);
1327     if (op_val != _preCADoption2value.end())
1328     {
1329       if (op_val->second != optionValue)
1330         op_val->second = optionValue;
1331       else
1332         modif = false;
1333     }
1334     else if ( optionValue.empty() )
1335     {
1336       _customOption2value.erase( optionName );
1337     }
1338     else
1339     {
1340       op_val = _customOption2value.find(optionName);
1341       if (op_val == _customOption2value.end())
1342         _customOption2value[optionName] = optionValue;
1343       else if (op_val->second != optionValue)
1344         op_val->second = optionValue;
1345       else
1346         modif = false;
1347     }
1348   }
1349   if ( modif )
1350     NotifySubMeshesHypothesisModification();
1351 }
1352
1353 //=============================================================================
1354 void BLSURFPlugin_Hypothesis::AddPreCADOption(const std::string& optionName, const std::string& optionValue)
1355 {
1356   AddOption( optionName, optionValue );
1357 }
1358
1359 //=============================================================================
1360 std::string BLSURFPlugin_Hypothesis::GetOption(const std::string& optionName) const
1361 {
1362   TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
1363   if (op_val != _customOption2value.end())
1364     return op_val->second;
1365   else
1366     return "";
1367 }
1368
1369 //=============================================================================
1370 std::string BLSURFPlugin_Hypothesis::GetPreCADOption(const std::string& optionName) const
1371 {
1372   TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
1373   if (op_val != _customOption2value.end())
1374     return op_val->second;
1375   else
1376     return "";
1377 }
1378
1379 //=============================================================================
1380 BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetOptionValues() const
1381 {
1382   TOptionValues vals;
1383   TOptionValues::const_iterator op_val = _option2value.begin();
1384   for ( ; op_val != _option2value.end(); ++op_val )
1385     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
1386
1387   return vals;
1388 }
1389
1390 //=============================================================================
1391 BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetPreCADOptionValues() const
1392 {
1393   TOptionValues vals;
1394   TOptionValues::const_iterator op_val = _preCADoption2value.begin();
1395   for ( ; op_val != _preCADoption2value.end(); ++op_val )
1396     vals.insert( make_pair( op_val->first, GetPreCADOptionValue( op_val->first, GET_DEFAULT() )));
1397
1398   return vals;
1399 }
1400
1401 //=======================================================================
1402 //function : SetSizeMapEntry
1403 //=======================================================================
1404 void BLSURFPlugin_Hypothesis::SetSizeMapEntry(const std::string& entry, const std::string& sizeMap) {
1405   if (_sizeMap[entry].compare(sizeMap) != 0) {
1406     SetPhysicalMesh(PhysicalLocalSize);
1407     _sizeMap[entry] = sizeMap;
1408     NotifySubMeshesHypothesisModification();
1409   }
1410 }
1411
1412 //=======================================================================
1413 //function : GetSizeMapEntry
1414 //=======================================================================
1415 std::string BLSURFPlugin_Hypothesis::GetSizeMapEntry(const std::string& entry) {
1416   TSizeMap::iterator it = _sizeMap.find(entry);
1417   if (it != _sizeMap.end())
1418     return it->second;
1419   else
1420     return "No_Such_Entry";
1421 }
1422
1423 /*!
1424  * \brief Return the size maps
1425  */
1426 BLSURFPlugin_Hypothesis::TSizeMap BLSURFPlugin_Hypothesis::GetSizeMapEntries(const BLSURFPlugin_Hypothesis* hyp) {
1427   return hyp ? hyp->_GetSizeMapEntries() : GetDefaultSizeMap();
1428 }
1429
1430 //=======================================================================
1431 //function : SetAttractorEntry
1432 //=======================================================================
1433 void BLSURFPlugin_Hypothesis::SetAttractorEntry(const std::string& entry, const std::string& attractor) {
1434   if (_attractors[entry].compare(attractor) != 0) {
1435     SetPhysicalMesh(PhysicalLocalSize);
1436     _attractors[entry] = attractor;
1437     NotifySubMeshesHypothesisModification();
1438   }
1439 }
1440
1441 //=======================================================================
1442 //function : GetAttractorEntry
1443 //=======================================================================
1444 std::string BLSURFPlugin_Hypothesis::GetAttractorEntry(const std::string& entry) {
1445   TSizeMap::iterator it = _attractors.find(entry);
1446   if (it != _attractors.end())
1447     return it->second;
1448   else
1449     return "No_Such_Entry";
1450 }
1451
1452 /*!
1453  * \brief Return the attractors
1454  */
1455 BLSURFPlugin_Hypothesis::TSizeMap BLSURFPlugin_Hypothesis::GetAttractorEntries(const BLSURFPlugin_Hypothesis* hyp) {
1456   return hyp ? hyp->_GetAttractorEntries() : GetDefaultSizeMap();
1457 }
1458
1459 //=======================================================================
1460 //function : SetClassAttractorEntry
1461 //=======================================================================
1462 void BLSURFPlugin_Hypothesis::SetClassAttractorEntry(const std::string& entry, const std::string& attEntry, double StartSize, double EndSize, double ActionRadius, double ConstantRadius)
1463 {
1464   SetPhysicalMesh(PhysicalLocalSize);
1465
1466   // The new attractor can't be defined on the same face as another sizemap
1467   TSizeMap::iterator it  = _sizeMap.find( entry );
1468   if ( it != _sizeMap.end() ) {
1469     _sizeMap.erase(it);
1470     NotifySubMeshesHypothesisModification();
1471   }
1472   else {
1473     TSizeMap::iterator itAt  = _attractors.find( entry );
1474     if ( itAt != _attractors.end() ) {
1475       _attractors.erase(itAt);
1476       NotifySubMeshesHypothesisModification();
1477     }
1478   }
1479   
1480   const TopoDS_Shape AttractorShape = BLSURFPlugin_Hypothesis::entryToShape(attEntry);
1481   const TopoDS_Face FaceShape = TopoDS::Face(BLSURFPlugin_Hypothesis::entryToShape(entry));
1482   TAttractorMap::iterator attIt = _classAttractors.find(entry);
1483   for ( ; attIt != _classAttractors.end(); ++attIt )
1484     if ( attIt->first == entry && 
1485          attIt->second->GetAttractorEntry() == attEntry )
1486       break;
1487   bool attExists = (attIt != _classAttractors.end());
1488
1489   BLSURFPlugin_Attractor* myAttractor;
1490   if ( !attExists ) {
1491     myAttractor = new BLSURFPlugin_Attractor(FaceShape, AttractorShape, attEntry);//, 0.1 );
1492     _classAttractors.insert( make_pair( entry, myAttractor ));
1493   }
1494   else {
1495     myAttractor = attIt->second;
1496   }
1497   // if (!myAttractor->IsMapBuilt())
1498   //   myAttractor->BuildMap();
1499   myAttractor->SetParameters(StartSize, EndSize, ActionRadius, ConstantRadius);
1500
1501   NotifySubMeshesHypothesisModification();
1502 }
1503
1504 //=======================================================================
1505 //function : SetConstantSizeOnAdjacentFaces
1506 //=======================================================================
1507 // TODO uncomment and test (include the needed .hxx)
1508 // SetConstantSizeOnAdjacentFaces(myShape, att_entry, startSize, endSize = user_size, const_dist  ) {
1509 //   TopTools_IndexedMapOfShapListOdShape anEdge2FaceMap;
1510 //   TopExp::MapShapesAnAncestors(myShape,TopAbs_EDGE, TopAbs_FACE, anEdge2FaceMap);
1511 //   TopTools_IndexedMapOfShapListOdShape::iterator it;
1512 //   for (it = anEdge2FaceMap.begin();it != anEdge2FaceMap.end();it++){
1513 //       SetClassAttractorEntry((*it).first, att_entry, startSize, endSize, 0, const_dist)
1514 //   }
1515
1516
1517
1518
1519
1520
1521 //=======================================================================
1522 //function : GetClassAttractorEntry
1523 //=======================================================================
1524 // BLSURFPlugin_Attractor&  BLSURFPlugin_Hypothesis::GetClassAttractorEntry(const std::string& entry)
1525 // {
1526 //  TAttractorMap::iterator it  = _classAttractors.find( entry );
1527 //  if ( it != _classAttractors.end() )
1528 //    return it->second;
1529 //  else
1530 //    return "No_Such_Entry";
1531 // }
1532 // 
1533   /*!
1534    * \brief Return the map of attractor instances
1535    */
1536 BLSURFPlugin_Hypothesis::TAttractorMap BLSURFPlugin_Hypothesis::GetClassAttractorEntries(const BLSURFPlugin_Hypothesis* hyp)
1537 {
1538     return hyp ? hyp->_GetClassAttractorEntries():GetDefaultAttractorMap();
1539 }
1540
1541 //=======================================================================
1542 //function : ClearEntry
1543 //=======================================================================
1544 void BLSURFPlugin_Hypothesis::ClearEntry(const std::string& entry,
1545                                          const char * attEntry/*=0*/)
1546 {
1547  TSizeMap::iterator it  = _sizeMap.find( entry );
1548  
1549  if ( it != _sizeMap.end() ) {
1550    _sizeMap.erase(it);
1551    NotifySubMeshesHypothesisModification();
1552  }
1553  else {
1554    TSizeMap::iterator itAt  = _attractors.find( entry );
1555    if ( itAt != _attractors.end() ) {
1556      _attractors.erase(itAt);
1557      NotifySubMeshesHypothesisModification();
1558    }
1559    else {
1560      TAttractorMap::iterator it_clAt = _classAttractors.find( entry );
1561      if ( it_clAt != _classAttractors.end() ) {
1562        do {
1563          if ( !attEntry || it_clAt->second->GetAttractorEntry() == attEntry )
1564            _classAttractors.erase( it_clAt++ );
1565          else
1566            ++it_clAt;
1567        }
1568        while ( it_clAt != _classAttractors.end() );
1569        NotifySubMeshesHypothesisModification();
1570      }
1571      else
1572        std::cout<<"No_Such_Entry"<<std::endl;
1573    }
1574  }
1575 }
1576
1577 //=======================================================================
1578 //function : ClearSizeMaps
1579 //=======================================================================
1580 void BLSURFPlugin_Hypothesis::ClearSizeMaps() {
1581   _sizeMap.clear();
1582   _attractors.clear();
1583   _classAttractors.clear();
1584 }
1585
1586 // Enable internal enforced vertices on specific face if requested by user
1587
1588 ////=======================================================================
1589 ////function : SetInternalEnforcedVertex
1590 ////=======================================================================
1591 //void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertex(TEntry theFaceEntry,
1592 //                                                        bool toEnforceInternalVertices,
1593 //                                                        TEnfGroupName theGroupName) {
1594
1595 //      << toEnforceInternalVertices << ", " << theGroupName << ")");
1596   
1597 //  TFaceEntryInternalVerticesList::iterator it = _faceEntryInternalVerticesList.find(theFaceEntry);
1598 //  if (it != _faceEntryInternalVerticesList.end()) {
1599 //    if (!toEnforceInternalVertices) {
1600 //      _faceEntryInternalVerticesList.erase(it);
1601 //    }
1602 //  }
1603 //  else {
1604 //    if (toEnforceInternalVertices) {
1605 //      _faceEntryInternalVerticesList.insert(theFaceEntry);
1606 //    }
1607 //  }
1608   
1609 //  // TODO
1610 //  // Take care of groups
1611 //}
1612
1613
1614 //=======================================================================
1615 //function : SetEnforcedVertex
1616 //=======================================================================
1617 bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry        theFaceEntry,
1618                                                 TEnfName      theVertexName,
1619                                                 TEntry        theVertexEntry,
1620                                                 TEnfGroupName theGroupName,
1621                                                 double x, double y, double z)
1622 {
1623   SetPhysicalMesh(PhysicalLocalSize);
1624
1625   bool toNotify = false;
1626   bool toCreate = true;
1627
1628   TEnfVertex *oldEnVertex;
1629   TEnfVertex *newEnfVertex = new TEnfVertex();
1630   newEnfVertex->name = theVertexName;
1631   newEnfVertex->geomEntry = theVertexEntry;
1632   newEnfVertex->coords.clear();
1633   if (theVertexEntry == "") {
1634     newEnfVertex->coords.push_back(x);
1635     newEnfVertex->coords.push_back(y);
1636     newEnfVertex->coords.push_back(z);
1637   }
1638   newEnfVertex->grpName = theGroupName;
1639   newEnfVertex->faceEntries.clear();
1640   newEnfVertex->faceEntries.insert(theFaceEntry);
1641
1642
1643   // update _enfVertexList
1644   TEnfVertexList::iterator it = _enfVertexList.find(newEnfVertex);
1645   if (it != _enfVertexList.end()) {
1646     toCreate = false;
1647     oldEnVertex = (*it);
1648     if (oldEnVertex->name != theVertexName) {
1649       oldEnVertex->name = theVertexName;
1650       toNotify = true;
1651     }
1652     if (oldEnVertex->grpName != theGroupName) {
1653       oldEnVertex->grpName = theGroupName;
1654       toNotify = true;
1655     }
1656     TEntryList::iterator it_faceEntries = oldEnVertex->faceEntries.find(theFaceEntry);
1657     if (it_faceEntries == oldEnVertex->faceEntries.end()) {
1658       oldEnVertex->faceEntries.insert(theFaceEntry);
1659       _faceEntryEnfVertexListMap[theFaceEntry].insert(oldEnVertex);
1660       toNotify = true;
1661     }
1662     if (toNotify) {
1663       // update map coords / enf vertex if needed
1664       if (oldEnVertex->coords.size()) {
1665         _coordsEnfVertexMap[oldEnVertex->coords] = oldEnVertex;
1666         _faceEntryCoordsListMap[theFaceEntry].insert(oldEnVertex->coords);
1667       }
1668
1669       // update map geom entry / enf vertex if needed
1670       if (oldEnVertex->geomEntry != "") {
1671         _enfVertexEntryEnfVertexMap[oldEnVertex->geomEntry] = oldEnVertex;
1672         _faceEntryEnfVertexEntryListMap[theFaceEntry].insert(oldEnVertex->geomEntry);
1673       }
1674     }
1675   }
1676
1677 //   //////// CREATE ////////////
1678   if (toCreate) {
1679     toNotify = true;
1680     AddEnforcedVertex( theFaceEntry, newEnfVertex );
1681   }
1682   else {
1683     delete newEnfVertex;
1684   }
1685
1686   if (toNotify)
1687     NotifySubMeshesHypothesisModification();
1688
1689   return toNotify;
1690 }
1691
1692 //=======================================================================
1693 //function : AddEnforcedVertex
1694 //=======================================================================
1695
1696 void BLSURFPlugin_Hypothesis::AddEnforcedVertex( const TEntry& faceEntry,
1697                                                  TEnfVertex *  newEnfVertex )
1698 {
1699   if ( newEnfVertex )
1700   {
1701     _faceEntryEnfVertexListMap[faceEntry].insert(newEnfVertex);
1702     _enfVertexList.insert(newEnfVertex);
1703     if ( newEnfVertex->geomEntry.empty() ) {
1704       _faceEntryCoordsListMap[faceEntry].insert(newEnfVertex->coords);
1705       _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
1706     }
1707     else {
1708       _faceEntryEnfVertexEntryListMap[faceEntry].insert(newEnfVertex->geomEntry);
1709       _enfVertexEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
1710     }
1711   }
1712 }
1713
1714 //=======================================================================
1715 //function : GetEnforcedVertices
1716 //=======================================================================
1717
1718 BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetEnfVertexList(const TEntry& theFaceEntry)
1719 {
1720   if (_faceEntryEnfVertexListMap.count(theFaceEntry) > 0)
1721     return _faceEntryEnfVertexListMap[theFaceEntry];
1722   else
1723     return GetDefaultEnfVertexList();
1724
1725   std::ostringstream msg;
1726   msg << "No enforced vertex for face entry " << theFaceEntry;
1727   throw std::invalid_argument(msg.str());
1728 }
1729
1730 //=======================================================================
1731 //function : GetEnfVertexCoordsList
1732 //=======================================================================
1733
1734 BLSURFPlugin_Hypothesis::TEnfVertexCoordsList BLSURFPlugin_Hypothesis::GetEnfVertexCoordsList(const TEntry& theFaceEntry)
1735 {
1736   if (_faceEntryCoordsListMap.count(theFaceEntry) > 0)
1737     return _faceEntryCoordsListMap[theFaceEntry];
1738
1739   std::ostringstream msg;
1740   msg << "No enforced vertex coords for face entry " << theFaceEntry;
1741   throw std::invalid_argument(msg.str());
1742 }
1743
1744 //=======================================================================
1745 //function : GetEnfVertexEntryList
1746 //=======================================================================
1747
1748 BLSURFPlugin_Hypothesis::TEntryList BLSURFPlugin_Hypothesis::GetEnfVertexEntryList(const TEntry& theFaceEntry)
1749 {
1750   if (_faceEntryEnfVertexEntryListMap.count(theFaceEntry) > 0)
1751     return _faceEntryEnfVertexEntryListMap[theFaceEntry];
1752
1753   std::ostringstream msg;
1754   msg << "No enforced vertex entry for face entry " << theFaceEntry;
1755   throw std::invalid_argument(msg.str());
1756 }
1757
1758 //=======================================================================
1759 //function : GetEnfVertex(TEnfVertexCoords coords)
1760 //=======================================================================
1761
1762 BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(TEnfVertexCoords coords)
1763 {
1764   if (_coordsEnfVertexMap.count(coords) > 0)
1765     return _coordsEnfVertexMap[coords];
1766
1767   std::ostringstream msg;
1768   msg << "No enforced vertex with coords (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")";
1769   throw std::invalid_argument(msg.str());
1770 }
1771
1772 //=======================================================================
1773 //function : GetEnfVertex(const TEntry& theEnfVertexEntry)
1774 //=======================================================================
1775
1776 BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(const TEntry& theEnfVertexEntry)
1777 {
1778   if (_enfVertexEntryEnfVertexMap.count(theEnfVertexEntry) > 0)
1779     return _enfVertexEntryEnfVertexMap[theEnfVertexEntry];
1780
1781   std::ostringstream msg;
1782   msg << "No enforced vertex with entry " << theEnfVertexEntry;
1783   throw std::invalid_argument(msg.str());
1784 }
1785
1786 //Enable internal enforced vertices on specific face if requested by user
1787 ////=======================================================================
1788 ////function : GetInternalEnforcedVertex
1789 ////=======================================================================
1790
1791 //bool BLSURFPlugin_Hypothesis::GetInternalEnforcedVertex(const TEntry& theFaceEntry)
1792 //{
1793 //  if (_faceEntryInternalVerticesList.count(theFaceEntry) > 0)
1794 //    return true;
1795 //  return false;
1796 //}
1797
1798 //=======================================================================
1799 //function : ClearEnforcedVertex
1800 //=======================================================================
1801
1802 bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry,
1803                                                   double x, double y, double z,
1804                                                   const TEntry& theVertexEntry)
1805 {
1806   bool toNotify = false;
1807   std::ostringstream msg;
1808   TEnfVertex *oldEnfVertex;
1809   TEnfVertexCoords coords;
1810   coords.clear();
1811   coords.push_back(x);
1812   coords.push_back(y);
1813   coords.push_back(z);
1814
1815   // check that enf vertex with given enf vertex entry exists
1816   TEnfVertexEntryEnfVertexMap::iterator it_enfVertexEntry = _enfVertexEntryEnfVertexMap.find(theVertexEntry);
1817   if (it_enfVertexEntry != _enfVertexEntryEnfVertexMap.end()) {
1818     // Success
1819     oldEnfVertex = it_enfVertexEntry->second;
1820
1821     _enfVertexEntryEnfVertexMap.erase(it_enfVertexEntry);
1822
1823     TEntryList& enfVertexEntryList = _faceEntryEnfVertexEntryListMap[theFaceEntry];
1824     enfVertexEntryList.erase(theVertexEntry);
1825     if (enfVertexEntryList.size() == 0)
1826       _faceEntryEnfVertexEntryListMap.erase(theFaceEntry);
1827     //    TFaceEntryEnfVertexEntryListMap::iterator it_entry_entry = _faceEntryEnfVertexEntryListMap.find(theFaceEntry);
1828     //    TEntryList::iterator it_entryList = it_entry_entry->second.find(theVertexEntry);
1829     //    it_entry_entry->second.erase(it_entryList);
1830     //    if (it_entry_entry->second.size() == 0)
1831     //      _faceEntryEnfVertexEntryListMap.erase(it_entry_entry);
1832   } else {
1833     // Fail
1834     MESSAGE("Enforced vertex with geom entry " << theVertexEntry << " not found");
1835     msg << "No enforced vertex with geom entry " << theVertexEntry;
1836     // check that enf vertex with given coords exists
1837     TCoordsEnfVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
1838     if (it_coords_enf != _coordsEnfVertexMap.end()) {
1839       // Success
1840       oldEnfVertex = it_coords_enf->second;
1841
1842       _coordsEnfVertexMap.erase(it_coords_enf);
1843
1844       TEnfVertexCoordsList& enfVertexCoordsList = _faceEntryCoordsListMap[theFaceEntry];
1845       enfVertexCoordsList.erase(coords);
1846       if (enfVertexCoordsList.size() == 0)
1847         _faceEntryCoordsListMap.erase(theFaceEntry);
1848       //      TFaceEntryCoordsListMap::iterator it_entry_coords = _faceEntryCoordsListMap.find(theFaceEntry);
1849       //      TEnfVertexCoordsList::iterator it_coordsList = it_entry_coords->second.find(coords);
1850       //      it_entry_coords->second.erase(it_coordsList);
1851       //      if (it_entry_coords->second.size() == 0)
1852       //        _faceEntryCoordsListMap.erase(it_entry_coords);
1853     } else {
1854       // Fail
1855       MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found");
1856       msg << std::endl;
1857       msg << "No enforced vertex at " << x << ", " << y << ", " << z;
1858       throw std::invalid_argument(msg.str());
1859     }
1860   }
1861
1862   // update _enfVertexList
1863   TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1864   if (it != _enfVertexList.end()) {
1865     (*it)->faceEntries.erase(theFaceEntry);
1866     if ((*it)->faceEntries.size() == 0){
1867       _enfVertexList.erase(it);
1868       toNotify = true;
1869     }
1870   }
1871
1872   // update _faceEntryEnfVertexListMap
1873   TEnfVertexList& currentEnfVertexList = _faceEntryEnfVertexListMap[theFaceEntry];
1874   currentEnfVertexList.erase(oldEnfVertex);
1875
1876   if (currentEnfVertexList.size() == 0) {
1877     _faceEntryEnfVertexListMap.erase(theFaceEntry);
1878   }
1879
1880   if (toNotify)
1881     NotifySubMeshesHypothesisModification();
1882
1883   return toNotify;
1884 }
1885
1886 //=======================================================================
1887 //function : ClearEnforcedVertices
1888 //=======================================================================
1889
1890 bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry)
1891 {
1892   bool toNotify = false;
1893   TEnfVertex *oldEnfVertex;
1894
1895   TFaceEntryCoordsListMap::iterator it_entry_coords = _faceEntryCoordsListMap.find(theFaceEntry);
1896   if (it_entry_coords != _faceEntryCoordsListMap.end()) {
1897     toNotify = true;
1898     TEnfVertexCoordsList coordsList = it_entry_coords->second;
1899     TEnfVertexCoordsList::iterator it_coordsList = coordsList.begin();
1900     for (; it_coordsList != coordsList.end(); ++it_coordsList) {
1901       TEnfVertexCoords coords = (*it_coordsList);
1902       oldEnfVertex = _coordsEnfVertexMap[coords];
1903       _coordsEnfVertexMap.erase(coords);
1904       // update _enfVertexList
1905       TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1906       if (it != _enfVertexList.end()) {
1907         (*it)->faceEntries.erase(theFaceEntry);
1908         if ((*it)->faceEntries.size() == 0){
1909           _enfVertexList.erase(it);
1910           toNotify = true;
1911         }
1912       }
1913     }
1914     _faceEntryCoordsListMap.erase(it_entry_coords);
1915     _faceEntryEnfVertexListMap.erase(theFaceEntry);
1916   }
1917
1918   TFaceEntryEnfVertexEntryListMap::iterator it_entry_entry = _faceEntryEnfVertexEntryListMap.find(theFaceEntry);
1919   if (it_entry_entry != _faceEntryEnfVertexEntryListMap.end()) {
1920     toNotify = true;
1921     TEntryList enfVertexEntryList = it_entry_entry->second;
1922     TEntryList::iterator it_enfVertexEntryList = enfVertexEntryList.begin();
1923     for (; it_enfVertexEntryList != enfVertexEntryList.end(); ++it_enfVertexEntryList) {
1924       TEntry enfVertexEntry = (*it_enfVertexEntryList);
1925       oldEnfVertex = _enfVertexEntryEnfVertexMap[enfVertexEntry];
1926       _enfVertexEntryEnfVertexMap.erase(enfVertexEntry);
1927       // update _enfVertexList
1928       TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1929       if (it != _enfVertexList.end()) {
1930         (*it)->faceEntries.erase(theFaceEntry);
1931         if ((*it)->faceEntries.size() == 0){
1932           _enfVertexList.erase(it);
1933           toNotify = true;
1934         }
1935       }
1936     }
1937     _faceEntryEnfVertexEntryListMap.erase(it_entry_entry);
1938     _faceEntryEnfVertexListMap.erase(theFaceEntry);
1939   }
1940
1941   if (toNotify)
1942     NotifySubMeshesHypothesisModification();
1943
1944   return toNotify;
1945   //  std::ostringstream msg;
1946   //  msg << "No enforced vertex for " << theFaceEntry;
1947   //  throw std::invalid_argument(msg.str());
1948 }
1949
1950 //=======================================================================
1951 //function : ClearAllEnforcedVertices
1952 //=======================================================================
1953 void BLSURFPlugin_Hypothesis::ClearAllEnforcedVertices()
1954 {
1955   _faceEntryEnfVertexListMap.clear();
1956   _faceEntryCoordsListMap.clear();
1957   _coordsEnfVertexMap.clear();
1958   _faceEntryEnfVertexEntryListMap.clear();
1959   _enfVertexEntryEnfVertexMap.clear();
1960   
1961   TEnfVertexList::iterator it_enfVertex = _enfVertexList.begin();
1962   for ( ; it_enfVertex != _enfVertexList.end(); ++it_enfVertex )
1963     delete *it_enfVertex;
1964   _enfVertexList.clear();
1965
1966 //  Enable internal enforced vertices on specific face if requested by user
1967 //  _faceEntryInternalVerticesList.clear();
1968   NotifySubMeshesHypothesisModification();
1969 }
1970
1971
1972 //================================================================================
1973 /*!
1974  * \brief Return the enforced vertices
1975  */
1976 //================================================================================
1977
1978
1979 BLSURFPlugin_Hypothesis::TFaceEntryEnfVertexListMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByFace(
1980     const BLSURFPlugin_Hypothesis* hyp)
1981 {
1982   return hyp ? hyp->_GetAllEnforcedVerticesByFace() : GetDefaultFaceEntryEnfVertexListMap();
1983 }
1984
1985 //Enable internal enforced vertices on specific face if requested by user
1986 //BLSURFPlugin_Hypothesis::TFaceEntryInternalVerticesList BLSURFPlugin_Hypothesis::GetAllInternalEnforcedVerticesByFace(
1987 //    const BLSURFPlugin_Hypothesis* hyp) {
1988 //  return hyp ? hyp->_GetAllInternalEnforcedVerticesByFace() : GetDefaultFaceEntryInternalVerticesMap();
1989 //}
1990
1991 bool BLSURFPlugin_Hypothesis::GetInternalEnforcedVertexAllFaces(const BLSURFPlugin_Hypothesis* hyp)
1992 {
1993   return hyp ? hyp->_GetInternalEnforcedVertexAllFaces() : GetDefaultInternalEnforcedVertex();
1994 }
1995
1996 BLSURFPlugin_Hypothesis::TEnfGroupName BLSURFPlugin_Hypothesis::GetInternalEnforcedVertexAllFacesGroup(const BLSURFPlugin_Hypothesis* hyp)
1997 {
1998   return hyp ? hyp->_GetInternalEnforcedVertexAllFacesGroup() : BLSURFPlugin_Hypothesis::TEnfGroupName();
1999 }
2000
2001 BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetAllEnforcedVertices(
2002     const BLSURFPlugin_Hypothesis* hyp)
2003 {
2004   return hyp ? hyp->_GetAllEnforcedVertices() : GetDefaultEnfVertexList();
2005 }
2006
2007 BLSURFPlugin_Hypothesis::TFaceEntryCoordsListMap BLSURFPlugin_Hypothesis::GetAllCoordsByFace(
2008     const BLSURFPlugin_Hypothesis* hyp)
2009 {
2010   return hyp ? hyp->_GetAllCoordsByFace() : GetDefaultFaceEntryCoordsListMap();
2011 }
2012
2013 BLSURFPlugin_Hypothesis::TCoordsEnfVertexMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByCoords(
2014     const BLSURFPlugin_Hypothesis* hyp)
2015 {
2016   return hyp ? hyp->_GetAllEnforcedVerticesByCoords() : GetDefaultCoordsEnfVertexMap();
2017 }
2018
2019 BLSURFPlugin_Hypothesis::TFaceEntryEnfVertexEntryListMap BLSURFPlugin_Hypothesis::GetAllEnfVertexEntriesByFace(
2020     const BLSURFPlugin_Hypothesis* hyp)
2021 {
2022   return hyp ? hyp->_GetAllEnfVertexEntriesByFace() : GetDefaultFaceEntryEnfVertexEntryListMap();
2023 }
2024
2025 BLSURFPlugin_Hypothesis::TEnfVertexEntryEnfVertexMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByEnfVertexEntry(
2026     const BLSURFPlugin_Hypothesis* hyp)
2027 {
2028   return hyp ? hyp->_GetAllEnforcedVerticesByEnfVertexEntry() : GetDefaultEnfVertexEntryEnfVertexMap();
2029 }
2030
2031 std::set<smIdType> BLSURFPlugin_Hypothesis::GetEnfVertexNodeIDs(TEnfGroupName theGroupName)
2032 {
2033   TGroupNameNodeIDMap::const_iterator it = _groupNameNodeIDMap.find(theGroupName);
2034   if (it != _groupNameNodeIDMap.end()) {
2035     return it->second;
2036   }
2037   std::ostringstream msg;
2038   msg << "No group " << theGroupName;
2039   throw std::invalid_argument(msg.str());
2040 }
2041
2042 void BLSURFPlugin_Hypothesis::AddEnfVertexNodeID(TEnfGroupName theGroupName,smIdType theNodeID)
2043 {
2044   _groupNameNodeIDMap[theGroupName].insert(theNodeID);
2045 }
2046
2047 void BLSURFPlugin_Hypothesis::RemoveEnfVertexNodeID(TEnfGroupName theGroupName,smIdType theNodeID)
2048 {
2049   TGroupNameNodeIDMap::iterator it = _groupNameNodeIDMap.find(theGroupName);
2050   if (it != _groupNameNodeIDMap.end()) {
2051     std::set<smIdType>::iterator IDit = it->second.find(theNodeID);
2052     if (IDit != it->second.end())
2053       it->second.erase(IDit);
2054     std::ostringstream msg;
2055     msg << "No node IDs " << theNodeID << " for group " << theGroupName;
2056     throw std::invalid_argument(msg.str());
2057   }
2058   std::ostringstream msg;
2059   msg << "No group " << theGroupName;
2060   throw std::invalid_argument(msg.str());
2061 }
2062
2063
2064 //=============================================================================
2065 void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceInternalVertices)
2066 {
2067   if (toEnforceInternalVertices != _enforcedInternalVerticesAllFaces) {
2068     _enforcedInternalVerticesAllFaces = toEnforceInternalVertices;
2069     if (toEnforceInternalVertices)
2070       SetPhysicalMesh(PhysicalLocalSize);
2071     NotifySubMeshesHypothesisModification();
2072   }
2073 }
2074
2075
2076 //=============================================================================
2077 void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugin_Hypothesis::TEnfGroupName theGroupName)
2078 {
2079   if (std::string(theGroupName) != std::string(_enforcedInternalVerticesAllFacesGroup)) {
2080     _enforcedInternalVerticesAllFacesGroup = theGroupName;
2081     NotifySubMeshesHypothesisModification();
2082   }
2083 }
2084
2085 //=============================================================================
2086 BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector BLSURFPlugin_Hypothesis::GetPreCadFacesPeriodicityVector(
2087     const BLSURFPlugin_Hypothesis* hyp)
2088 {
2089   return hyp ? hyp->_GetPreCadFacesPeriodicityVector() : GetDefaultPreCadFacesPeriodicityVector();
2090 }
2091
2092 //=============================================================================
2093 BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector BLSURFPlugin_Hypothesis::GetPreCadEdgesPeriodicityVector(
2094     const BLSURFPlugin_Hypothesis* hyp)
2095 {
2096   return hyp ? hyp->_GetPreCadEdgesPeriodicityVector() : GetDefaultPreCadEdgesPeriodicityVector();
2097 }
2098
2099 //=============================================================================
2100 BLSURFPlugin_Hypothesis::TFacesPeriodicityVector BLSURFPlugin_Hypothesis::GetFacesPeriodicityVector(
2101     const BLSURFPlugin_Hypothesis* hyp)
2102 {
2103   return hyp ? hyp->_GetFacesPeriodicityVector() : GetDefaultFacesPeriodicityVector();
2104 }
2105
2106 //=============================================================================
2107 BLSURFPlugin_Hypothesis::TEdgesPeriodicityVector BLSURFPlugin_Hypothesis::GetEdgesPeriodicityVector(
2108     const BLSURFPlugin_Hypothesis* hyp)
2109 {
2110   return hyp ? hyp->_GetEdgesPeriodicityVector() : GetDefaultEdgesPeriodicityVector();
2111 }
2112
2113 //=============================================================================
2114 BLSURFPlugin_Hypothesis::TVerticesPeriodicityVector BLSURFPlugin_Hypothesis::GetVerticesPeriodicityVector(
2115     const BLSURFPlugin_Hypothesis* hyp)
2116 {
2117   return hyp ? hyp->_GetVerticesPeriodicityVector() : GetDefaultVerticesPeriodicityVector();
2118 }
2119
2120 //=======================================================================
2121 //function : ClearAllEnforcedVertices
2122 //=======================================================================
2123 void BLSURFPlugin_Hypothesis::ClearPreCadPeriodicityVectors()
2124 {
2125   _preCadFacesPeriodicityVector.clear();
2126   _preCadEdgesPeriodicityVector.clear();
2127   NotifySubMeshesHypothesisModification();
2128 }
2129
2130 //=======================================================================
2131 //function : AddPreCadFacesPeriodicity
2132 //=======================================================================
2133 void BLSURFPlugin_Hypothesis::AddPreCadFacesPeriodicity(TEntry theFace1Entry, TEntry theFace2Entry,
2134                                                         std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries)
2135 {
2136
2137   TPreCadPeriodicity preCadFacesPeriodicity;
2138   preCadFacesPeriodicity.shape1Entry = theFace1Entry;
2139   preCadFacesPeriodicity.shape2Entry = theFace2Entry;
2140   preCadFacesPeriodicity.theSourceVerticesEntries = theSourceVerticesEntries;
2141   preCadFacesPeriodicity.theTargetVerticesEntries = theTargetVerticesEntries;
2142
2143   _preCadFacesPeriodicityVector.push_back(preCadFacesPeriodicity);
2144
2145   NotifySubMeshesHypothesisModification();
2146 }
2147
2148 //=======================================================================
2149 //function : AddPreCadEdgesPeriodicity
2150 //=======================================================================
2151 void BLSURFPlugin_Hypothesis::AddPreCadEdgesPeriodicity(TEntry theEdge1Entry, TEntry theEdge2Entry,
2152     std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries)
2153 {
2154   TPreCadPeriodicity preCadEdgesPeriodicity;
2155   preCadEdgesPeriodicity.shape1Entry = theEdge1Entry;
2156   preCadEdgesPeriodicity.shape2Entry = theEdge2Entry;
2157   preCadEdgesPeriodicity.theSourceVerticesEntries = theSourceVerticesEntries;
2158   preCadEdgesPeriodicity.theTargetVerticesEntries = theTargetVerticesEntries;
2159
2160   _preCadEdgesPeriodicityVector.push_back(preCadEdgesPeriodicity);
2161
2162   NotifySubMeshesHypothesisModification();
2163 }
2164
2165 //=============================================================================
2166 std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save)
2167 {
2168   // We must keep at least the same number of arguments when increasing the SALOME version
2169   // When MG-CADSurf becomes CADMESH, some parameters were fused into a single one. Thus the same
2170   // parameter can be written several times to keep the old global number of parameters.
2171
2172   // Treat old options which are now in the advanced options
2173   TOptionValues::iterator op_val;
2174   int _decimesh = -1;
2175   int _preCADRemoveNanoEdges = -1;
2176   double _preCADEpsNano = -1.0;
2177   op_val = _option2value.find("respect_geometry");
2178   if (op_val != _option2value.end()) {
2179     std::string value = op_val->second;
2180     if (!value.empty())
2181       _decimesh = value.compare("1") == 0 ? 1 : 0;
2182   }
2183   op_val = _preCADoption2value.find("remove_tiny_edges");
2184   if (op_val != _preCADoption2value.end()) {
2185     std::string value = op_val->second;
2186     if (!value.empty())
2187       _preCADRemoveNanoEdges = value.compare("1") == 0 ? 1 : 0;
2188   }
2189   op_val = _preCADoption2value.find("tiny_edge_length");
2190   if (op_val != _preCADoption2value.end()) {
2191     std::string value = op_val->second;
2192     if (!value.empty())
2193       _preCADEpsNano = strtod(value.c_str(), NULL);
2194   }
2195
2196   save << " " << (int) _topology << " " << (int) _physicalMesh << " " << (int) _geometricMesh << " " << _phySize << " "
2197        << _angleMesh << " " << _gradation << " " << (int) _elementType << " " << _decimesh;
2198   save << " " << _minSize << " " << _maxSize << " " << _angleMesh << " " << _minSize << " " << _maxSize << " " << _verb;
2199   save << " " << (int) _preCADMergeEdges << " " << _preCADRemoveNanoEdges << " " << (int) _preCADDiscardInput << " " << _preCADEpsNano ;
2200   save << " " << (int) _enforcedInternalVerticesAllFaces;
2201   save << " " << (int) _phySizeRel << " " << (int) _minSizeRel << " " << (int) _maxSizeRel << " " << _chordalError ;
2202   save << " " << (int) _anisotropic << " " << _anisotropicRatio << " " << (int) _removeTinyEdges << " " << _tinyEdgeLength ;
2203   save << " " << (int) _badElementRemoval << " " << _badElementAspectRatio << " " << (int) _optimizeMesh << " " << (int) _quadraticMesh ;
2204   save << " " << (int) _preCADProcess3DTopology << " " << (int) _preCADRemoveDuplicateCADFaces;
2205   save << " " << (int)_optimiseTinyEdges << " " << _tinyEdgeOptimisationLength;
2206   save << " " << (int)_correctSurfaceIntersec << " " << _corrSurfaceIntersCost;
2207   save << " " << (int)_useGradation << " " << (int)_useVolumeGradation << " " << _volumeGradation;
2208
2209   op_val = _option2value.begin();
2210   if (op_val != _option2value.end()) {
2211     save << " " << "__OPTIONS_BEGIN__";
2212     for (; op_val != _option2value.end(); ++op_val) {
2213       if (!op_val->second.empty())
2214         save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
2215     }
2216     save << " " << "__OPTIONS_END__";
2217   }
2218   
2219   op_val = _customOption2value.begin();
2220   if (op_val != _customOption2value.end()) {
2221     save << " " << "__CUSTOM_OPTIONS_BEGIN__";
2222     for (; op_val != _customOption2value.end(); ++op_val) {
2223       if (!op_val->second.empty())
2224         save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
2225     }
2226     save << " " << "__CUSTOM_OPTIONS_END__";
2227   }
2228
2229   op_val = _preCADoption2value.begin();
2230   if (op_val != _preCADoption2value.end()) {
2231     save << " " << "__PRECAD_OPTIONS_BEGIN__";
2232     for (; op_val != _preCADoption2value.end(); ++op_val) {
2233       if (!op_val->second.empty())
2234         save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
2235     }
2236     save << " " << "__PRECAD_OPTIONS_END__";
2237   }
2238
2239   TSizeMap::iterator it_sm = _sizeMap.begin();
2240   if (it_sm != _sizeMap.end()) {
2241     save << " " << "__SIZEMAP_BEGIN__";
2242     for (; it_sm != _sizeMap.end(); ++it_sm) {
2243       save << " " << it_sm->first << " " << it_sm->second << "%#"; // "%#" is a mark of value end
2244     }
2245     save << " " << "__SIZEMAP_END__";
2246   }
2247
2248   TSizeMap::iterator it_at = _attractors.begin();
2249   if (it_at != _attractors.end()) {
2250     save << " " << "__ATTRACTORS_BEGIN__";
2251     for (; it_at != _attractors.end(); ++it_at) {
2252       save << " " << it_at->first << " " << it_at->second << "%#"; // "%#" is a mark of value end
2253     }
2254     save << " " << "__ATTRACTORS_END__";
2255   }
2256   
2257   TAttractorMap::iterator it_At = _classAttractors.begin();
2258   if (it_At != _classAttractors.end()) {
2259     std::ostringstream test;
2260     save << " " << "__NEW_ATTRACTORS_BEGIN__";
2261     test << " " << "__NEW_ATTRACTORS_BEGIN__";
2262     for (; it_At != _classAttractors.end(); ++it_At) {
2263       std::vector<double> attParams;
2264       attParams   = it_At->second->GetParameters();
2265 //       double step = it_At->second->GetStep();
2266       save << " " << it_At->first;
2267       save << " " << it_At->second->GetAttractorEntry();
2268       save << " " << attParams[0]  << " " <<  attParams[1] << " " <<  attParams[2] << " " <<  attParams[3];
2269 //       save << " " << step;
2270       test << " " << it_At->first;
2271       test << " " << it_At->second->GetAttractorEntry();
2272       test << " " << attParams[0]  << " " <<  attParams[1] << " " <<  attParams[2] << " " <<  attParams[3];
2273 //       test << " " << step;
2274     }
2275     save << " " << "__NEW_ATTRACTORS_END__";
2276     test << " " << "__NEW_ATTRACTORS_END__";
2277   }
2278
2279   TEnfVertexList::const_iterator it_enf = _enfVertexList.begin();
2280   if (it_enf != _enfVertexList.end()) {
2281     save << " " << "__ENFORCED_VERTICES_BEGIN__";
2282     for (; it_enf != _enfVertexList.end(); ++it_enf) {
2283       TEnfVertex *enfVertex = (*it_enf);
2284       save << " " << "__BEGIN_VERTEX__";
2285       if (!enfVertex->name.empty()) {
2286         save << " " << "__BEGIN_NAME__";
2287         save << " " << enfVertex->name;
2288         save << " " << "__END_NAME__";
2289       }
2290       if (!enfVertex->geomEntry.empty()) {
2291         save << " " << "__BEGIN_ENTRY__";
2292         save << " " << enfVertex->geomEntry;
2293         save << " " << "__END_ENTRY__";
2294       }
2295       if (!enfVertex->grpName.empty()) {
2296         save << " " << "__BEGIN_GROUP__";
2297         save << " " << enfVertex->grpName;
2298         save << " " << "__END_GROUP__";
2299       }
2300       if (enfVertex->coords.size()) {
2301         save << " " << "__BEGIN_COORDS__";
2302         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
2303           save << " " << enfVertex->coords[i];
2304         save << " " << "__END_COORDS__";
2305       }
2306       TEntryList::const_iterator faceEntriesIt = enfVertex->faceEntries.begin();
2307       bool hasFaces = false;
2308       if (faceEntriesIt != enfVertex->faceEntries.end()) {
2309         hasFaces = true;
2310         save << " " << "__BEGIN_FACELIST__";
2311       }
2312       for (; faceEntriesIt != enfVertex->faceEntries.end(); ++faceEntriesIt)
2313         if ( faceEntriesIt->empty() )
2314           save << " _no_face_";
2315         else
2316           save << " " << (*faceEntriesIt);
2317       if (hasFaces)
2318         save << " " << "__END_FACELIST__";
2319       save << " " << "__END_VERTEX__";
2320     }
2321     save << " " << "__ENFORCED_VERTICES_END__";
2322   }
2323
2324   //PERIODICITY
2325
2326   SavePreCADPeriodicity(save, "FACES");
2327   SavePreCADPeriodicity(save, "EDGES");
2328
2329   SaveFacesPeriodicity(save);
2330   SaveEdgesPeriodicity(save);
2331   SaveVerticesPeriodicity(save);
2332
2333   // HYPER-PATCHES
2334   save << " " << _hyperPatchList.size() << " ";
2335   for ( size_t i = 0; i < _hyperPatchList.size(); ++i )
2336   {
2337     THyperPatchTags& patch = _hyperPatchList[i];
2338     save << patch.size() << " ";
2339     THyperPatchTags::iterator tag = patch.begin();
2340     for ( ; tag != patch.end(); ++tag )
2341       save << *tag << " ";
2342   }
2343
2344   // New options in 2.9.6 (issue #17784)
2345   save << " " << _useSurfaceProximity;
2346   save << " " << _nbSurfaceProximityLayers;
2347   save << " " << _surfaceProximityRatio;
2348   save << " " << _useVolumeProximity;
2349   save << " " << _nbVolumeProximityLayers;
2350   save << " " << _volumeProximityRatio;
2351
2352   // hyper-patches as entries
2353   std::ostringstream hpStream;
2354   boost::archive::text_oarchive( hpStream ) << _hyperPatchEntriesList;
2355   std::string hpString = hpStream.str();
2356   SMESHDS_Hypothesis::SaveStringToStream( save, hpString );
2357
2358   // Enforced meshes
2359   std::ostringstream enfMStream;
2360   boost::archive::text_oarchive( enfMStream ) << _enforcedMeshes;
2361   std::string enfMString = enfMStream.str();
2362   SMESHDS_Hypothesis::SaveStringToStream( save, enfMString );
2363
2364   return save;
2365 }
2366
2367 void BLSURFPlugin_Hypothesis::SaveFacesPeriodicity(std::ostream & save)
2368 {
2369   TFacesPeriodicityVector::const_iterator it_faces_periodicity = _facesPeriodicityVector.begin();
2370   if (it_faces_periodicity != _facesPeriodicityVector.end()) {
2371     save << " " << "__FACES_PERIODICITY_BEGIN__";
2372     for (; it_faces_periodicity != _facesPeriodicityVector.end(); ++it_faces_periodicity) {
2373       TFacesPeriodicity periodicity_i = (*it_faces_periodicity);
2374       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2375       save << " " << "__BEGIN_ENTRY1__";
2376       save << " " << periodicity_i.first;
2377       save << " " << "__END_ENTRY1__";
2378       save << " " << "__BEGIN_ENTRY2__";
2379       save << " " << periodicity_i.second;
2380       save << " " << "__END_ENTRY2__";
2381       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2382     }
2383     save << " " << "__FACES_PERIODICITY_END__";
2384   }
2385 }
2386
2387 void BLSURFPlugin_Hypothesis::SaveEdgesPeriodicity(std::ostream & save)
2388 {
2389   TEdgesPeriodicityVector::const_iterator it_edges_periodicity = _edgesPeriodicityVector.begin();
2390   if (it_edges_periodicity != _edgesPeriodicityVector.end()) {
2391     save << " " << "__EDGES_PERIODICITY_BEGIN__";
2392     for (; it_edges_periodicity != _edgesPeriodicityVector.end(); ++it_edges_periodicity) {
2393       TEdgePeriodicity periodicity_i = (*it_edges_periodicity);
2394       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2395       if (! periodicity_i.theFace1Entry.empty()){
2396         save << " " << "__BEGIN_FACE1__";
2397         save << " " << periodicity_i.theFace1Entry;
2398         save << " " << "__END_FACE1__";
2399       }
2400       save << " " << "__BEGIN_EDGE1__";
2401       save << " " << periodicity_i.theEdge1Entry;
2402       save << " " << "__END_EDGE1__";
2403       if (! periodicity_i.theFace2Entry.empty()){
2404         save << " " << "__BEGIN_FACE2__";
2405         save << " " << periodicity_i.theFace2Entry;
2406         save << " " << "__END_FACE2__";
2407       }
2408       save << " " << "__BEGIN_EDGE2__";
2409       save << " " << periodicity_i.theEdge2Entry;
2410       save << " " << "__END_EDGE2__";
2411       save << " " << "__BEGIN_EDGE_ORIENTATION__";
2412       save << " " << periodicity_i.edge_orientation;
2413       save << " " << "__END_EDGE_ORIENTATION__";
2414       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2415     }
2416     save << " " << "__EDGES_PERIODICITY_END__";
2417   }
2418 }
2419
2420 void BLSURFPlugin_Hypothesis::SaveVerticesPeriodicity(std::ostream & save)
2421 {
2422   TVerticesPeriodicityVector::const_iterator it_vertices_periodicity = _verticesPeriodicityVector.begin();
2423   if (it_vertices_periodicity != _verticesPeriodicityVector.end()) {
2424     save << " " << "__VERTICES_PERIODICITY_BEGIN__";
2425     for (; it_vertices_periodicity != _verticesPeriodicityVector.end(); ++it_vertices_periodicity) {
2426       TVertexPeriodicity periodicity_i = (*it_vertices_periodicity);
2427       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2428       save << " " << "__BEGIN_EDGE1__";
2429       save << " " << periodicity_i.theEdge1Entry;
2430       save << " " << "__END_EDGE1__";
2431       save << " " << "__BEGIN_VERTEX1__";
2432       save << " " << periodicity_i.theVertex1Entry;
2433       save << " " << "__END_VERTEX1__";
2434       save << " " << "__BEGIN_EDGE2__";
2435       save << " " << periodicity_i.theEdge2Entry;
2436       save << " " << "__END_EDGE2__";
2437       save << " " << "__BEGIN_VERTEX2__";
2438       save << " " << periodicity_i.theVertex2Entry;
2439       save << " " << "__END_VERTEX2__";
2440       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2441     }
2442     save << " " << "__VERTICES_PERIODICITY_END__";
2443   }
2444 }
2445
2446 void BLSURFPlugin_Hypothesis::SavePreCADPeriodicity(std::ostream & save, const char* shapeType)
2447 {
2448   TPreCadPeriodicityVector precad_periodicity;
2449   if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
2450     precad_periodicity = _preCadFacesPeriodicityVector;
2451   else
2452     precad_periodicity = _preCadEdgesPeriodicityVector;
2453   TPreCadPeriodicityVector::const_iterator it_precad_periodicity = precad_periodicity.begin();
2454   if (it_precad_periodicity != precad_periodicity.end()) {
2455     save << " " << "__PRECAD_" << shapeType << "_PERIODICITY_BEGIN__";
2456     for (; it_precad_periodicity != precad_periodicity.end(); ++it_precad_periodicity) {
2457       TPreCadPeriodicity periodicity_i = (*it_precad_periodicity);
2458       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2459       if (!periodicity_i.shape1Entry.empty()) {
2460         save << " " << "__BEGIN_ENTRY1__";
2461         save << " " << periodicity_i.shape1Entry;
2462         save << " " << "__END_ENTRY1__";
2463       }
2464       if (!periodicity_i.shape2Entry.empty()) {
2465         save << " " << "__BEGIN_ENTRY2__";
2466         save << " " << periodicity_i.shape2Entry;
2467         save << " " << "__END_ENTRY2__";
2468       }
2469
2470       std::vector<std::string>::const_iterator sourceVerticesEntriesIt = periodicity_i.theSourceVerticesEntries.begin();
2471       bool hasSourceVertices = false;
2472       if (sourceVerticesEntriesIt != periodicity_i.theSourceVerticesEntries.end()) {
2473         hasSourceVertices = true;
2474         save << " " << "__BEGIN_SOURCE_VERTICES_LIST__";
2475       }
2476       for (; sourceVerticesEntriesIt != periodicity_i.theSourceVerticesEntries.end(); ++sourceVerticesEntriesIt)
2477         save << " " << (*sourceVerticesEntriesIt);
2478       if (hasSourceVertices)
2479         save << " " << "__END_SOURCE_VERTICES_LIST__";
2480
2481       std::vector<std::string>::const_iterator targetVerticesEntriesIt = periodicity_i.theTargetVerticesEntries.begin();
2482       bool hasTargetVertices = false;
2483       if (targetVerticesEntriesIt != periodicity_i.theTargetVerticesEntries.end()) {
2484         hasTargetVertices = true;
2485         save << " " << "__BEGIN_TARGET_VERTICES_LIST__";
2486       }
2487       for (; targetVerticesEntriesIt != periodicity_i.theTargetVerticesEntries.end(); ++targetVerticesEntriesIt)
2488         save << " " << (*targetVerticesEntriesIt);
2489       if (hasTargetVertices)
2490         save << " " << "__END_TARGET_VERTICES_LIST__";
2491
2492       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2493     }
2494     save << " " << "__PRECAD_" << shapeType << "_PERIODICITY_END__";
2495   }
2496
2497 }
2498
2499 //=============================================================================
2500 std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load)
2501 {
2502   bool isOK = true;
2503   int i;
2504   double val;
2505   std::string option_or_sm;
2506
2507   isOK = static_cast<bool>(load >> i);
2508   if (isOK)
2509     _topology = (Topology) i;
2510   else
2511     load.clear(std::ios::badbit | load.rdstate());
2512
2513   isOK = static_cast<bool>(load >> i);
2514   if (isOK)
2515     _physicalMesh = (PhysicalMesh) i;
2516   else
2517     load.clear(std::ios::badbit | load.rdstate());
2518
2519   isOK = static_cast<bool>(load >> i);
2520   if (isOK)
2521     _geometricMesh = (GeometricMesh) i;
2522   else
2523     load.clear(std::ios::badbit | load.rdstate());
2524
2525   isOK = static_cast<bool>(load >> val);
2526   if (isOK)
2527     _phySize = val;
2528   else
2529     load.clear(std::ios::badbit | load.rdstate());
2530
2531   isOK = static_cast<bool>(load >> val);
2532   if (isOK)
2533     _angleMesh = val;
2534   else
2535     load.clear(std::ios::badbit | load.rdstate());
2536
2537   isOK = static_cast<bool>(load >> val);
2538   if (isOK)
2539     _gradation = val;
2540   else
2541     load.clear(std::ios::badbit | load.rdstate());
2542
2543   isOK = static_cast<bool>(load >> i);
2544   if (isOK)
2545     _elementType = (ElementType) i;
2546   else
2547     load.clear(std::ios::badbit | load.rdstate());
2548
2549   isOK = static_cast<bool>(load >> i);
2550   if (isOK) {
2551     if ( i != -1) { // if value is -1, then this is no longer a standard option
2552       std::string & value = _option2value["respect_geometry"];
2553       bool _decimesh = (bool) i;
2554       value = _decimesh ? "1" : "0";
2555     }
2556   }
2557   else
2558     load.clear(std::ios::badbit | load.rdstate());
2559
2560   isOK = static_cast<bool>(load >> val);
2561   if (isOK)
2562     _minSize = val;
2563   else
2564     load.clear(std::ios::badbit | load.rdstate());
2565
2566   isOK = static_cast<bool>(load >> val);
2567   if (isOK)
2568     _maxSize = val;
2569   else
2570     load.clear(std::ios::badbit | load.rdstate());
2571
2572   isOK = static_cast<bool>(load >> val);
2573   if (isOK)
2574     // former parameter: get min value
2575     _angleMesh = std::min(val,_angleMesh);
2576   else
2577     load.clear(std::ios::badbit | load.rdstate());
2578
2579   isOK = static_cast<bool>(load >> val);
2580   if (isOK)
2581     // former parameter: get min value
2582     _minSize = std::min(val,_minSize);
2583   else
2584     load.clear(std::ios::badbit | load.rdstate());
2585
2586   isOK = static_cast<bool>(load >> val);
2587   if (isOK)
2588     // former parameter: get max value
2589     _maxSize = std::max(val,_maxSize);
2590   else
2591     load.clear(std::ios::badbit | load.rdstate());
2592
2593   isOK = static_cast<bool>(load >> i);
2594   if (isOK)
2595     _verb = i;
2596   else
2597     load.clear(std::ios::badbit | load.rdstate());
2598
2599   isOK = static_cast<bool>(load >> i);
2600   if (isOK)
2601     _preCADMergeEdges = (bool) i;
2602   else
2603     load.clear(std::ios::badbit | load.rdstate());
2604
2605   isOK = static_cast<bool>(load >> i);
2606   if (isOK) {
2607     if ( i != -1) { // if value is -1, then this is no longer a standard option
2608       std::string & value = _preCADoption2value["remove_tiny_edges"];
2609       bool _preCADRemoveNanoEdges = (bool) i;
2610       value = _preCADRemoveNanoEdges ? "1" : "0";
2611     }
2612   }
2613   else
2614     load.clear(std::ios::badbit | load.rdstate());
2615
2616   isOK = static_cast<bool>(load >> i);
2617   if (isOK)
2618     _preCADDiscardInput = (bool) i;
2619   else
2620     load.clear(std::ios::badbit | load.rdstate());
2621
2622   isOK = static_cast<bool>(load >> val);
2623   if (isOK) { // _preCADEpsNano
2624     if ( (i + 1.0) < 1e-6 ) { // if value is -1, then this is no longer a standard option: get optional value "tiny_edge_length" instead
2625       std::string & value = _preCADoption2value["tiny_edge_length"];
2626       std::ostringstream oss;
2627       oss << i;
2628       value = oss.str();
2629     }
2630   }
2631   else
2632     load.clear(std::ios::badbit | load.rdstate());
2633
2634   isOK = static_cast<bool>(load >> i);
2635   if (isOK)
2636     _enforcedInternalVerticesAllFaces = (bool) i;
2637   else
2638     load.clear(std::ios::badbit | load.rdstate());
2639
2640   // New options with MeshGems-CADSurf
2641
2642   bool hasCADSurfOptions = false;
2643   bool hasOptions = false;
2644   bool hasCustomOptions = false;
2645   bool hasPreCADOptions = false;
2646   bool hasSizeMap = false;
2647   bool hasAttractor = false;
2648   bool hasNewAttractor = false;
2649   bool hasEnforcedVertex = false;
2650   bool hasPreCADFacesPeriodicity = false;
2651   bool hasPreCADEdgesPeriodicity = false;
2652   bool hasFacesPeriodicity = false;
2653   bool hasEdgesPeriodicity = false;
2654   bool hasVerticesPeriodicity = false;
2655
2656   isOK = static_cast<bool>(load >> option_or_sm);
2657   if (isOK) {
2658     if (( option_or_sm == "1" ) || ( option_or_sm == "0" )) {
2659       i = atoi(option_or_sm.c_str());
2660       hasCADSurfOptions = true;
2661       _phySizeRel = (bool) i;
2662     }
2663     else if (option_or_sm == "__OPTIONS_BEGIN__")
2664       hasOptions = true;
2665     else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
2666       hasCustomOptions = true;
2667     else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2668       hasPreCADOptions = true;
2669     else if (option_or_sm == "__SIZEMAP_BEGIN__")
2670       hasSizeMap = true;
2671     else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2672       hasAttractor = true;
2673     else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2674       hasNewAttractor = true;
2675     else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2676       hasEnforcedVertex = true;
2677     else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2678       hasPreCADFacesPeriodicity = true;
2679     else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2680       hasPreCADEdgesPeriodicity = true;
2681     else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2682       hasFacesPeriodicity = true;
2683     else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2684       hasEdgesPeriodicity = true;
2685     else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2686       hasVerticesPeriodicity = true;
2687   }
2688
2689   if (isOK && hasCADSurfOptions) {
2690     isOK = static_cast<bool>(load >> i);
2691     if (isOK)
2692       _minSizeRel = (bool) i;
2693     else
2694       load.clear(std::ios::badbit | load.rdstate());
2695
2696     isOK = static_cast<bool>(load >> i);
2697     if (isOK)
2698       _maxSizeRel = (bool) i;
2699     else
2700       load.clear(std::ios::badbit | load.rdstate());
2701
2702     isOK = static_cast<bool>(load >> val);
2703     if (isOK)
2704       _chordalError = val;
2705     else
2706       load.clear(std::ios::badbit | load.rdstate());
2707
2708     isOK = static_cast<bool>(load >> i);
2709     if (isOK)
2710       _anisotropic = (bool) i;
2711     else
2712       load.clear(std::ios::badbit | load.rdstate());
2713
2714     isOK = static_cast<bool>(load >> val);
2715     if (isOK)
2716       _anisotropicRatio = val;
2717     else
2718       load.clear(std::ios::badbit | load.rdstate());
2719
2720     isOK = static_cast<bool>(load >> i);
2721     if (isOK)
2722       _removeTinyEdges = (bool) i;
2723     else
2724       load.clear(std::ios::badbit | load.rdstate());
2725
2726     isOK = static_cast<bool>(load >> val);
2727     if (isOK)
2728       _tinyEdgeLength = val;
2729     else
2730       load.clear(std::ios::badbit | load.rdstate());
2731
2732     isOK = static_cast<bool>(load >> i);
2733     if (isOK)
2734       _badElementRemoval = (bool) i;
2735     else
2736       load.clear(std::ios::badbit | load.rdstate());
2737
2738     isOK = static_cast<bool>(load >> val);
2739     if (isOK)
2740       _badElementAspectRatio = val;
2741     else
2742       load.clear(std::ios::badbit | load.rdstate());
2743
2744     isOK = static_cast<bool>(load >> i);
2745     if (isOK)
2746       _optimizeMesh = (bool) i;
2747     else
2748       load.clear(std::ios::badbit | load.rdstate());
2749
2750     isOK = static_cast<bool>(load >> i);
2751     if (isOK)
2752       _quadraticMesh = (bool) i;
2753     else
2754       load.clear(std::ios::badbit | load.rdstate());
2755
2756     isOK = static_cast<bool>(load >> i);
2757     if (isOK)
2758       _preCADProcess3DTopology = (bool) i;
2759     else
2760       load.clear(std::ios::badbit | load.rdstate());
2761
2762     if (( load >> std::ws).peek() != '_' )
2763     {
2764       isOK = static_cast<bool>(load >> i);
2765       if (isOK)
2766         _preCADRemoveDuplicateCADFaces = (bool) i;
2767       else
2768         load.clear(std::ios::badbit | load.rdstate());
2769
2770       isOK = static_cast<bool>(load >> i);
2771       if (isOK)
2772         _optimiseTinyEdges = (bool) i;
2773       else
2774         load.clear(std::ios::badbit | load.rdstate());
2775
2776       isOK = static_cast<bool>(load >> val);
2777       if (isOK)
2778         _tinyEdgeOptimisationLength = val;
2779       else
2780         load.clear(std::ios::badbit | load.rdstate());
2781
2782       isOK = static_cast<bool>(load >> i);
2783       if (isOK)
2784         _correctSurfaceIntersec = (bool) i;
2785       else
2786         load.clear(std::ios::badbit | load.rdstate());
2787
2788       isOK = static_cast<bool>(load >> val);
2789       if (isOK)
2790         _corrSurfaceIntersCost = val;
2791       else
2792         load.clear(std::ios::badbit | load.rdstate());
2793
2794       isOK = static_cast<bool>(load >> i);
2795       if (isOK)
2796         _useGradation = (bool) i;
2797       else
2798         load.clear(std::ios::badbit | load.rdstate());
2799
2800       isOK = static_cast<bool>(load >> i);
2801       if (isOK)
2802         _useVolumeGradation = (bool) i;
2803       else
2804         load.clear(std::ios::badbit | load.rdstate());
2805
2806       isOK = static_cast<bool>(load >> val);
2807       if (isOK)
2808         _volumeGradation = val;
2809       else
2810         load.clear(std::ios::badbit | load.rdstate());
2811     }
2812   }
2813
2814
2815   if (hasCADSurfOptions) {
2816     isOK = static_cast<bool>(load >> option_or_sm);
2817     if (isOK) {
2818       if (option_or_sm == "__OPTIONS_BEGIN__")
2819         hasOptions = true;
2820       else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
2821         hasCustomOptions = true;
2822       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2823         hasPreCADOptions = true;
2824       else if (option_or_sm == "__SIZEMAP_BEGIN__")
2825         hasSizeMap = true;
2826       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2827         hasAttractor = true;
2828       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2829         hasNewAttractor = true;
2830       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2831         hasEnforcedVertex = true;
2832       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2833         hasPreCADFacesPeriodicity = true;
2834       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2835         hasPreCADEdgesPeriodicity = true;
2836       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2837         hasFacesPeriodicity = true;
2838       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2839         hasEdgesPeriodicity = true;
2840       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2841         hasVerticesPeriodicity = true;
2842     }
2843   }
2844   
2845   std::string optName, optValue;
2846   while (isOK && hasOptions) {
2847     isOK = static_cast<bool>(load >> optName);
2848     if (isOK) {
2849       if (optName == "__OPTIONS_END__")
2850         break;
2851       isOK = static_cast<bool>(load >> optValue);
2852     }
2853     // read the value of the advanced option
2854     // unless this option is no more used
2855     if (isOK
2856 #if MESHGEMS_VERSION_HEX >= 0x020A00
2857         && optName != "enforce_cad_edge_sizes" && optName != "max_number_of_points_per_patch"
2858 #endif
2859         ) {
2860       std::string & value = _option2value[optName];
2861       value = optValue;
2862       int len = (int) value.size();
2863       // continue reading until "%#" encountered
2864       while (value[len - 1] != '#' || value[len - 2] != '%') {
2865         isOK = static_cast<bool>(load >> optValue);
2866         if (isOK) {
2867           value += " ";
2868           value += optValue;
2869           len = (int) value.size();
2870         } else {
2871           break;
2872         }
2873       }
2874       if ( value[ len - 1] == '#' )
2875         value.resize(len - 2); //cut off "%#"
2876     }
2877   }
2878
2879   if (hasOptions) {
2880     isOK = static_cast<bool>(load >> option_or_sm);
2881     if (isOK) {
2882       if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
2883         hasCustomOptions = true;
2884       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2885         hasPreCADOptions = true;
2886       else if (option_or_sm == "__SIZEMAP_BEGIN__")
2887         hasSizeMap = true;
2888       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2889         hasAttractor = true;
2890       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2891         hasNewAttractor = true;
2892       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2893         hasEnforcedVertex = true;
2894       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2895         hasPreCADFacesPeriodicity = true;
2896       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2897         hasPreCADEdgesPeriodicity = true;
2898       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2899         hasFacesPeriodicity = true;
2900       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2901         hasEdgesPeriodicity = true;
2902       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2903         hasVerticesPeriodicity = true;
2904     }
2905   }
2906
2907   while (isOK && hasCustomOptions) {
2908     isOK = static_cast<bool>(load >> optName);
2909     if (isOK) {
2910       if (optName == "__CUSTOM_OPTIONS_END__")
2911         break;
2912       isOK = static_cast<bool>(load >> optValue);
2913     }
2914     if (isOK) {
2915       std::string& value = optValue;
2916       int len = (int) value.size();
2917       // continue reading until "%#" encountered
2918       while (value[len - 1] != '#' || value[len - 2] != '%') {
2919         isOK = static_cast<bool>(load >> optValue);
2920         if (isOK) {
2921           value += " ";
2922           value += optValue;
2923           len = (int) value.size();
2924         } else {
2925           break;
2926         }
2927       }
2928       if ( value[ len - 1] == '#' )
2929         value.resize(len - 2); //cut off "%#"
2930       _customOption2value[optName] = value;
2931     }
2932   }
2933
2934   if (hasCustomOptions) {
2935     isOK = static_cast<bool>(load >> option_or_sm);
2936     if (isOK) {
2937       if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2938         hasPreCADOptions = true;
2939       else if (option_or_sm == "__SIZEMAP_BEGIN__")
2940         hasSizeMap = true;
2941       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2942         hasAttractor = true;
2943       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2944         hasNewAttractor = true;
2945       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2946         hasEnforcedVertex = true;
2947       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2948         hasPreCADFacesPeriodicity = true;
2949       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2950         hasPreCADEdgesPeriodicity = true;
2951       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2952         hasFacesPeriodicity = true;
2953       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2954         hasEdgesPeriodicity = true;
2955       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2956         hasVerticesPeriodicity = true;
2957     }
2958   }
2959
2960   while (isOK && hasPreCADOptions) {
2961     isOK = static_cast<bool>(load >> optName);
2962     if (isOK) {
2963       if (optName == "__PRECAD_OPTIONS_END__")
2964         break;
2965       isOK = static_cast<bool>(load >> optValue);
2966     }
2967     if (isOK) {
2968       std::string & value = _preCADoption2value[optName];
2969       value = optValue;
2970       int len = (int) value.size();
2971       // continue reading until "%#" encountered
2972       while (value[len - 1] != '#' || value[len - 2] != '%') {
2973         isOK = static_cast<bool>(load >> optValue);
2974         if (isOK) {
2975           value += " ";
2976           value += optValue;
2977           len = (int) value.size();
2978         } else {
2979           break;
2980         }
2981       }
2982       if ( value[ len - 1] == '#' )
2983         value.resize(len - 2); //cut off "%#"
2984     }
2985   }
2986
2987   if (hasPreCADOptions) {
2988     isOK = static_cast<bool>(load >> option_or_sm);
2989     if (isOK) {
2990       if (option_or_sm == "__SIZEMAP_BEGIN__")
2991         hasSizeMap = true;
2992       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2993         hasAttractor = true;
2994       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2995         hasNewAttractor = true;
2996       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2997         hasEnforcedVertex = true;
2998       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2999         hasPreCADFacesPeriodicity = true;
3000       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3001         hasPreCADEdgesPeriodicity = true;
3002       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3003         hasFacesPeriodicity = true;
3004       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3005         hasEdgesPeriodicity = true;
3006       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3007         hasVerticesPeriodicity = true;
3008     }
3009   }
3010  
3011   std::string smEntry, smValue;
3012   while (isOK && hasSizeMap) {
3013     isOK = static_cast<bool>(load >> smEntry);
3014     if (isOK) {
3015       if (smEntry == "__SIZEMAP_END__")
3016         break;
3017       isOK = static_cast<bool>(load >> smValue);
3018     }
3019     if (isOK) {
3020       std::string & value2 = _sizeMap[smEntry];
3021       value2 = smValue;
3022       int len2 = (int) value2.size();
3023       // continue reading until "%#" encountered
3024       while (value2[len2 - 1] != '#' || value2[len2 - 2] != '%') {
3025         isOK = static_cast<bool>(load >> smValue);
3026         if (isOK) {
3027           value2 += " ";
3028           value2 += smValue;
3029           len2 = (int) value2.size();
3030         } else {
3031           break;
3032         }
3033       }
3034       value2.resize(len2 - 2); //cut off "%#"
3035     }
3036   }
3037
3038   if (hasSizeMap) {
3039     isOK = static_cast<bool>(load >> option_or_sm);
3040     if (isOK) {
3041       if (option_or_sm == "__ATTRACTORS_BEGIN__")
3042         hasAttractor = true;
3043       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
3044         hasNewAttractor = true;
3045       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
3046         hasEnforcedVertex = true;
3047       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3048         hasPreCADFacesPeriodicity = true;
3049       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3050         hasPreCADEdgesPeriodicity = true;
3051       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3052         hasFacesPeriodicity = true;
3053       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3054         hasEdgesPeriodicity = true;
3055       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3056         hasVerticesPeriodicity = true;
3057     }
3058   }
3059
3060   std::string atEntry, atValue;
3061   while (isOK && hasAttractor) {
3062     isOK = static_cast<bool>(load >> atEntry);
3063     if (isOK) {
3064       if (atEntry == "__ATTRACTORS_END__")
3065         break;
3066       isOK = static_cast<bool>(load >> atValue);
3067     }
3068     if (isOK) {
3069       std::string & value3 = _attractors[atEntry];
3070       value3 = atValue;
3071       int len3 = (int) value3.size();
3072       // continue reading until "%#" encountered
3073       while (value3[len3 - 1] != '#' || value3[len3 - 2] != '%') {
3074         isOK = static_cast<bool>(load >> atValue);
3075         if (isOK) {
3076           value3 += " ";
3077           value3 += atValue;
3078           len3 = (int) value3.size();
3079         } else {
3080           break;
3081         }
3082       }
3083       value3.resize(len3 - 2); //cut off "%#"
3084     }
3085   }
3086
3087   if (hasAttractor) {
3088     isOK = static_cast<bool>(load >> option_or_sm);
3089     if (isOK) {
3090       if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
3091         hasNewAttractor = true;
3092       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
3093         hasEnforcedVertex = true;
3094       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3095         hasPreCADFacesPeriodicity = true;
3096       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3097         hasPreCADEdgesPeriodicity = true;
3098       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3099         hasFacesPeriodicity = true;
3100       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3101         hasEdgesPeriodicity = true;
3102       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3103         hasVerticesPeriodicity = true;
3104     }
3105   }
3106
3107   std::string newAtFaceEntry, atTestString;
3108   std::string newAtShapeEntry;
3109   double attParams[4];
3110   //double step;
3111   while (isOK && hasNewAttractor) {
3112     //std::cout<<"Load new attractor"<<std::endl;
3113     isOK = static_cast<bool>(load >> newAtFaceEntry);
3114     if (isOK) {
3115       if (newAtFaceEntry == "__NEW_ATTRACTORS_END__")
3116         break;
3117       isOK = static_cast<bool>(load >> newAtShapeEntry);
3118       if (!isOK)
3119         break;
3120       isOK = static_cast<bool>(load >> attParams[0]>>attParams[1]>>attParams[2]>>attParams[3]); //>>step);
3121     }
3122     if (isOK) {
3123       const TopoDS_Shape attractorShape = BLSURFPlugin_Hypothesis::entryToShape(newAtShapeEntry);
3124       const TopoDS_Face faceShape = TopoDS::Face(BLSURFPlugin_Hypothesis::entryToShape(newAtFaceEntry));
3125       BLSURFPlugin_Attractor* attractor = new BLSURFPlugin_Attractor(faceShape, attractorShape, newAtShapeEntry);//, step);
3126       attractor->SetParameters(attParams[0], attParams[1], attParams[2], attParams[3]);
3127       //attractor->BuildMap();                     
3128       _classAttractors.insert( make_pair( newAtFaceEntry, attractor ));
3129     }
3130   }
3131   
3132   
3133   if (hasNewAttractor) {
3134     isOK = static_cast<bool>(load >> option_or_sm);
3135     if (isOK) {
3136       if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
3137         hasEnforcedVertex = true;
3138       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3139         hasPreCADFacesPeriodicity = true;
3140       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3141         hasPreCADEdgesPeriodicity = true;
3142       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3143         hasFacesPeriodicity = true;
3144       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3145         hasEdgesPeriodicity = true;
3146       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3147         hasVerticesPeriodicity = true;
3148     }
3149   }
3150
3151
3152 // 
3153 // Here is a example of the saved stream:
3154 // __ENFORCED_VERTICES_BEGIN__ 
3155 // __BEGIN_VERTEX__  => no name, no entry
3156 // __BEGIN_GROUP__ mon groupe __END_GROUP__
3157 // __BEGIN_COORDS__ 10 10 10 __END_COORDS__
3158 // __BEGIN_FACELIST__ 0:1:1:1:1 __END_FACELIST__
3159 // __END_VERTEX__
3160 // __BEGIN_VERTEX__ => no coords
3161 // __BEGIN_NAME__ mes points __END_NAME__
3162 // __BEGIN_ENTRY__ 0:1:1:4 __END_ENTRY__
3163 // __BEGIN_GROUP__ mon groupe __END_GROUP__
3164 // __BEGIN_FACELIST__ 0:1:1:1:3 __END_FACELIST__
3165 // __END_VERTEX__
3166 // __ENFORCED_VERTICES_END__
3167 //
3168
3169   std::string enfSeparator;
3170   std::string enfName;
3171   std::string enfGeomEntry;
3172   std::string enfGroup;
3173   TEntryList enfFaceEntryList;
3174   double enfCoords[3];
3175   bool hasCoords = false;
3176
3177   _faceEntryEnfVertexListMap.clear();
3178   _enfVertexList.clear();
3179   _faceEntryCoordsListMap.clear();
3180   _coordsEnfVertexMap.clear();
3181   _faceEntryEnfVertexEntryListMap.clear();
3182   _enfVertexEntryEnfVertexMap.clear();
3183
3184
3185   while (isOK && hasEnforcedVertex)
3186   {
3187     isOK = static_cast<bool>(load >> enfSeparator); // __BEGIN_VERTEX__
3188     TEnfVertex *enfVertex = new TEnfVertex();
3189     if (enfSeparator == "__ENFORCED_VERTICES_END__")
3190       break; // __ENFORCED_VERTICES_END__
3191     if (enfSeparator != "__BEGIN_VERTEX__")
3192       throw std::exception();
3193
3194     while (isOK) {
3195       isOK = static_cast<bool>(load >> enfSeparator);
3196       if (enfSeparator == "__END_VERTEX__") {
3197
3198         enfVertex->name = enfName;
3199         enfVertex->geomEntry = enfGeomEntry;
3200         enfVertex->grpName = enfGroup;
3201         enfVertex->coords.clear();
3202         if (hasCoords)
3203           enfVertex->coords.assign(enfCoords,enfCoords+3);
3204         enfVertex->faceEntries = enfFaceEntryList;
3205
3206         _enfVertexList.insert(enfVertex);
3207
3208         if (enfVertex->coords.size()) {
3209           _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
3210           for (TEntryList::const_iterator it = enfVertex->faceEntries.begin() ; it != enfVertex->faceEntries.end(); ++it) {
3211             _faceEntryCoordsListMap[(*it)].insert(enfVertex->coords);
3212             _faceEntryEnfVertexListMap[(*it)].insert(enfVertex);
3213           }
3214         }
3215         if (!enfVertex->geomEntry.empty()) {
3216           _enfVertexEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
3217           for (TEntryList::const_iterator it = enfVertex->faceEntries.begin() ; it != enfVertex->faceEntries.end(); ++it) {
3218             _faceEntryEnfVertexEntryListMap[(*it)].insert(enfVertex->geomEntry);
3219             _faceEntryEnfVertexListMap[(*it)].insert(enfVertex);
3220           }
3221         }
3222
3223         enfName.clear();
3224         enfGeomEntry.clear();
3225         enfGroup.clear();
3226         enfFaceEntryList.clear();
3227         hasCoords = false;
3228         break; // __END_VERTEX__
3229       }
3230
3231       if (enfSeparator == "__BEGIN_NAME__") {  // __BEGIN_NAME__
3232         while (isOK && (enfSeparator != "__END_NAME__")) {
3233           isOK = static_cast<bool>(load >> enfSeparator);
3234           if (enfSeparator != "__END_NAME__") {
3235             if (!enfName.empty())
3236               enfName += " ";
3237             enfName += enfSeparator;
3238           }
3239         }
3240       }
3241
3242       if (enfSeparator == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
3243         isOK = static_cast<bool>(load >> enfGeomEntry);
3244         isOK = static_cast<bool>(load >> enfSeparator); // __END_ENTRY__
3245         if (enfSeparator != "__END_ENTRY__")
3246           throw std::exception();
3247       }
3248
3249       if (enfSeparator == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
3250         while (isOK && (enfSeparator != "__END_GROUP__")) {
3251           isOK = static_cast<bool>(load >> enfSeparator);
3252           if (enfSeparator != "__END_GROUP__") {
3253             if (!enfGroup.empty())
3254               enfGroup += " ";
3255             enfGroup += enfSeparator;
3256           }
3257         }
3258       }
3259
3260       if (enfSeparator == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
3261         hasCoords = true;
3262         isOK = static_cast<bool>(load >> enfCoords[0] >> enfCoords[1] >> enfCoords[2]);
3263         isOK = static_cast<bool>(load >> enfSeparator); // __END_COORDS__
3264         if (enfSeparator != "__END_COORDS__")
3265           throw std::exception();
3266       }
3267
3268       if (enfSeparator == "__BEGIN_FACELIST__") {  // __BEGIN_FACELIST__
3269         while (isOK && (enfSeparator != "__END_FACELIST__")) {
3270           isOK = static_cast<bool>(load >> enfSeparator);
3271           if (enfSeparator != "__END_FACELIST__") {
3272             enfFaceEntryList.insert(enfSeparator);
3273           }
3274         }
3275       }
3276     }
3277   }
3278
3279   if ( hasEnforcedVertex ) {
3280     isOK = static_cast<bool>(load >> option_or_sm);
3281     if (isOK) {
3282       if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3283         hasPreCADFacesPeriodicity = true;
3284       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3285         hasPreCADEdgesPeriodicity = true;
3286       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3287         hasFacesPeriodicity = true;
3288       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3289         hasEdgesPeriodicity = true;
3290       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3291         hasVerticesPeriodicity = true;
3292     }
3293   }
3294
3295   // PERIODICITY
3296
3297   if (hasPreCADFacesPeriodicity)
3298   {
3299     LoadPreCADPeriodicity(load, "FACES");
3300
3301     isOK = static_cast<bool>(load >> option_or_sm);
3302     if (isOK) {
3303       if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3304         hasPreCADEdgesPeriodicity = true;
3305       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3306         hasFacesPeriodicity = true;
3307       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3308         hasEdgesPeriodicity = true;
3309       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3310         hasVerticesPeriodicity = true;
3311     }
3312   }
3313
3314   if (hasPreCADEdgesPeriodicity)
3315   {
3316     LoadPreCADPeriodicity(load, "EDGES");
3317
3318     isOK = static_cast<bool>(load >> option_or_sm);
3319     if (isOK) {
3320       if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3321         hasFacesPeriodicity = true;
3322       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3323         hasEdgesPeriodicity = true;
3324       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3325         hasVerticesPeriodicity = true;
3326     }
3327   }
3328
3329   if (hasFacesPeriodicity)
3330   {
3331     LoadFacesPeriodicity(load);
3332
3333     isOK = static_cast<bool>(load >> option_or_sm);
3334     if (isOK) {
3335       if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3336         hasEdgesPeriodicity = true;
3337       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3338         hasVerticesPeriodicity = true;
3339     }
3340   }
3341
3342   if (hasEdgesPeriodicity)
3343   {
3344     LoadEdgesPeriodicity(load);
3345
3346     isOK = static_cast<bool>(load >> option_or_sm);
3347     if (isOK)
3348       if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3349         hasVerticesPeriodicity = true;
3350   }
3351
3352   if (hasVerticesPeriodicity)
3353     LoadVerticesPeriodicity(load);
3354
3355   // HYPER-PATCHES
3356   if ( !option_or_sm.empty() && option_or_sm[0] == '_' )
3357     isOK = static_cast<bool>(load >> option_or_sm);
3358   if ( isOK && !option_or_sm.empty() )
3359   {
3360     int nbPatches = atoi( option_or_sm.c_str() );
3361     if ( nbPatches >= 0 )
3362     {
3363       _hyperPatchList.resize( nbPatches );
3364       for ( int iP = 0; iP < nbPatches && isOK; ++iP )
3365       {
3366         isOK = static_cast<bool>(load >> i) && i >= 2;
3367         if ( !isOK ) break;
3368         int nbTags = i;
3369         for ( int iT = 0; iT < nbTags; ++iT )
3370         {
3371           if (( isOK = static_cast<bool>(load >> i)))
3372             _hyperPatchList[ iP ].insert( i );
3373           else
3374             break;
3375         }
3376       }
3377       if ( !isOK ) // remove invalid patches
3378       {
3379         for ( i = nbPatches - 1; i >= 0; i-- )
3380           if ( _hyperPatchList[i].size() < 2 )
3381             _hyperPatchList.resize( i );
3382       }
3383     }
3384   }
3385
3386   // New options in 2.9.6 (issue #17784)
3387   if ( static_cast<bool>( load >> _useSurfaceProximity ))
3388   {
3389     load >> _nbSurfaceProximityLayers;
3390     load >> _surfaceProximityRatio;
3391     load >> _useVolumeProximity;
3392     load >> _nbVolumeProximityLayers;
3393     isOK = static_cast<bool>( load >> _volumeProximityRatio );
3394   }
3395
3396   // hyper-patches as entries (issue bos #20543)
3397   std::string buffer;
3398   if ( SMESHDS_Hypothesis::LoadStringFromStream( load, buffer ))
3399   {
3400     SMESH_TRY;
3401     SMESHUtils::BoostTxtArchive( buffer ) >> _hyperPatchEntriesList;
3402     SMESH_CATCH( SMESH::printErrorInDebugMode );
3403   }
3404
3405   // Enforced meshes (issue bos $16292)
3406   buffer.clear();
3407   if ( SMESHDS_Hypothesis::LoadStringFromStream( load, buffer ))
3408   {
3409     SMESH_TRY;
3410     SMESHUtils::BoostTxtArchive( buffer ) >> _enforcedMeshes;
3411     SMESH_CATCH( SMESH::printErrorInDebugMode );
3412   }
3413
3414   return load;
3415 }
3416
3417 namespace boost {
3418   namespace serialization {
3419
3420     //=======================================================================
3421     //function : serialize
3422     //purpose  : serialize EnforcedMesh
3423     //=======================================================================
3424
3425     template<class Archive>
3426     void serialize(Archive & ar, BLSURFPlugin_Hypothesis::EnforcedMesh & enfM,
3427                    const unsigned int /*version*/)
3428     {
3429       ar & enfM._meshID;
3430       ar & enfM._subID;
3431       ar & enfM._type;
3432       ar & enfM._groupName;
3433     }
3434
3435   } // namespace serialization
3436 } // namespace boost
3437
3438
3439 void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load)
3440 {
3441   bool isOK = true;
3442
3443   std::string periodicitySeparator;
3444   TEntry shape1Entry;
3445   TEntry shape2Entry;
3446
3447   _facesPeriodicityVector.clear();
3448
3449   while (isOK) {
3450     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3451     TFacesPeriodicity *periodicity_i = new TFacesPeriodicity();
3452     if (periodicitySeparator == "__FACES_PERIODICITY_END__")
3453       break; // __FACES_PERIODICITY_END__
3454     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3455       throw std::exception();
3456     }
3457
3458     while (isOK) {
3459       isOK = static_cast<bool>(load >> periodicitySeparator);
3460       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3461
3462         periodicity_i->first = shape1Entry;
3463         periodicity_i->second = shape2Entry;
3464
3465         _facesPeriodicityVector.push_back(*periodicity_i);
3466
3467         break; // __END_PERIODICITY_DESCRIPTION__
3468       }
3469
3470       if (periodicitySeparator == "__BEGIN_ENTRY1__") {  // __BEGIN_ENTRY1__
3471         isOK = static_cast<bool>(load >> shape1Entry);
3472         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
3473         if (periodicitySeparator != "__END_ENTRY1__")
3474           throw std::exception();
3475       }
3476
3477       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
3478         isOK = static_cast<bool>(load >> shape2Entry);
3479         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
3480         if (periodicitySeparator != "__END_ENTRY2__")
3481           throw std::exception();
3482       }
3483     }
3484   }
3485 }
3486
3487
3488 void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load)
3489 {
3490   bool isOK = true;
3491
3492   std::string periodicitySeparator;
3493   TEntry theFace1Entry;
3494   TEntry theEdge1Entry;
3495   TEntry theFace2Entry;
3496   TEntry theEdge2Entry;
3497   int edge_orientation = 0;
3498
3499   _edgesPeriodicityVector.clear();
3500
3501   while (isOK) {
3502     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3503     TEdgePeriodicity *periodicity_i = new TEdgePeriodicity();
3504     if (periodicitySeparator == "__EDGES_PERIODICITY_END__")
3505       break; // __EDGES_PERIODICITY_END__
3506     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3507       throw std::exception();
3508     }
3509
3510     while (isOK) {
3511       isOK = static_cast<bool>(load >> periodicitySeparator);
3512       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3513
3514         periodicity_i->theFace1Entry = theFace1Entry;
3515         periodicity_i->theEdge1Entry = theEdge1Entry;
3516         periodicity_i->theFace2Entry = theFace2Entry;
3517         periodicity_i->theEdge2Entry = theEdge2Entry;
3518         periodicity_i->edge_orientation = edge_orientation;
3519
3520         _edgesPeriodicityVector.push_back(*periodicity_i);
3521
3522         break; // __END_PERIODICITY_DESCRIPTION__
3523       }
3524
3525       if (periodicitySeparator == "__BEGIN_FACE1__") {  // __BEGIN_FACE1__
3526         isOK = static_cast<bool>(load >> theFace1Entry);
3527         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE1__
3528         if (periodicitySeparator != "__END_FACE1__"){
3529           throw std::exception();
3530         }
3531       }
3532
3533       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
3534         isOK = static_cast<bool>(load >> theEdge1Entry);
3535         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
3536         if (periodicitySeparator != "__END_EDGE1__")
3537           throw std::exception();
3538       }
3539
3540       if (periodicitySeparator == "__BEGIN_FACE2__") {  // __BEGIN_FACE2__
3541         isOK = static_cast<bool>(load >> theFace2Entry);
3542         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE2__
3543         if (periodicitySeparator != "__END_FACE2__")
3544           throw std::exception();
3545       }
3546
3547       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
3548         isOK = static_cast<bool>(load >> theEdge2Entry);
3549         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
3550         if (periodicitySeparator != "__END_EDGE2__")
3551           throw std::exception();
3552       }
3553
3554       if (periodicitySeparator == "__BEGIN_EDGE_ORIENTATION__") {  // __BEGIN_EDGE_ORIENTATION__
3555         isOK = static_cast<bool>(load >> edge_orientation);
3556         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE_ORIENTATION__
3557         if (periodicitySeparator != "__END_EDGE_ORIENTATION__")
3558           throw std::exception();
3559       }
3560     }
3561   }
3562 }
3563
3564 void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load)
3565 {
3566   bool isOK = true;
3567
3568   std::string periodicitySeparator;
3569   TEntry theEdge1Entry;
3570   TEntry theVertex1Entry;
3571   TEntry theEdge2Entry;
3572   TEntry theVertex2Entry;
3573
3574   _verticesPeriodicityVector.clear();
3575
3576   while (isOK) {
3577     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3578     TVertexPeriodicity *periodicity_i = new TVertexPeriodicity();
3579     if (periodicitySeparator == "__VERTICES_PERIODICITY_END__")
3580       break; // __VERTICES_PERIODICITY_END__
3581     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3582       throw std::exception();
3583     }
3584
3585     while (isOK) {
3586       isOK = static_cast<bool>(load >> periodicitySeparator);
3587       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3588
3589         periodicity_i->theEdge1Entry = theEdge1Entry;
3590         periodicity_i->theVertex1Entry = theVertex1Entry;
3591         periodicity_i->theEdge2Entry = theEdge2Entry;
3592         periodicity_i->theVertex2Entry = theVertex2Entry;
3593
3594         _verticesPeriodicityVector.push_back(*periodicity_i);
3595
3596         break; // __END_PERIODICITY_DESCRIPTION__
3597       }
3598
3599       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
3600         isOK = static_cast<bool>(load >> theEdge1Entry);
3601         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
3602         if (periodicitySeparator != "__END_EDGE1__")
3603           throw std::exception();
3604       }
3605
3606       if (periodicitySeparator == "__BEGIN_VERTEX1__") {  // __BEGIN_VERTEX1__
3607         isOK = static_cast<bool>(load >> theVertex1Entry);
3608         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX1__
3609         if (periodicitySeparator != "__END_VERTEX1__")
3610           throw std::exception();
3611       }
3612
3613       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
3614         isOK = static_cast<bool>(load >> theEdge2Entry);
3615         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
3616         if (periodicitySeparator != "__END_EDGE2__")
3617           throw std::exception();
3618       }
3619
3620       if (periodicitySeparator == "__BEGIN_VERTEX2__") {  // __BEGIN_VERTEX2__
3621         isOK = static_cast<bool>(load >> theVertex2Entry);
3622         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX2__
3623         if (periodicitySeparator != "__END_VERTEX2__")
3624           throw std::exception();
3625       }
3626     }
3627   }
3628 }
3629
3630 void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const char* shapeType)
3631 {
3632   bool isOK = true;
3633
3634   std::string periodicitySeparator;
3635   TEntry shape1Entry;
3636   TEntry shape2Entry;
3637   std::vector<std::string> theSourceVerticesEntries;
3638   std::vector<std::string> theTargetVerticesEntries;
3639
3640   bool hasSourceVertices = false;
3641   bool hasTargetVertices = false;
3642
3643   if ( shapeType  &&  strcmp( shapeType, "FACES") == 0 )
3644     _preCadFacesPeriodicityVector.clear();
3645   else
3646     _preCadEdgesPeriodicityVector.clear();
3647
3648
3649   while (isOK) {
3650     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3651     TPreCadPeriodicity *periodicity_i = new TPreCadPeriodicity();
3652     std::string endSeparator = "__PRECAD_" + std::string(shapeType) + "_PERIODICITY_END__";
3653     if (periodicitySeparator == endSeparator)
3654       break; // __PRECAD_FACES_PERIODICITY_END__
3655     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3656       throw std::exception();
3657     }
3658
3659     while (isOK) {
3660       isOK = static_cast<bool>(load >> periodicitySeparator);
3661       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3662
3663         periodicity_i->shape1Entry = shape1Entry;
3664         periodicity_i->shape2Entry = shape2Entry;
3665
3666         if (hasSourceVertices)
3667           periodicity_i->theSourceVerticesEntries = theSourceVerticesEntries;
3668         if (hasTargetVertices)
3669           periodicity_i->theTargetVerticesEntries = theTargetVerticesEntries;
3670
3671         if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
3672           _preCadFacesPeriodicityVector.push_back(*periodicity_i);
3673         else
3674           _preCadEdgesPeriodicityVector.push_back(*periodicity_i);
3675
3676         theSourceVerticesEntries.clear();
3677         theTargetVerticesEntries.clear();
3678         hasSourceVertices = false;
3679         hasTargetVertices = false;
3680         break; // __END_PERIODICITY_DESCRIPTION__
3681       }
3682
3683       if (periodicitySeparator == "__BEGIN_ENTRY1__") {  // __BEGIN_ENTRY1__
3684         isOK = static_cast<bool>(load >> shape1Entry);
3685         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
3686         if (periodicitySeparator != "__END_ENTRY1__")
3687           throw std::exception();
3688       }
3689
3690       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
3691         isOK = static_cast<bool>(load >> shape2Entry);
3692         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
3693         if (periodicitySeparator != "__END_ENTRY2__")
3694           throw std::exception();
3695       }
3696
3697       if (periodicitySeparator == "__BEGIN_SOURCE_VERTICES_LIST__") {  // __BEGIN_SOURCE_VERTICES_LIST__
3698         hasSourceVertices = true;
3699         while (isOK && (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__")) {
3700           isOK = static_cast<bool>(load >> periodicitySeparator);
3701           if (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__") {
3702             theSourceVerticesEntries.push_back(periodicitySeparator);
3703           }
3704         }
3705       }
3706
3707       if (periodicitySeparator == "__BEGIN_TARGET_VERTICES_LIST__") {  // __BEGIN_TARGET_VERTICES_LIST__
3708         hasTargetVertices = true;
3709         while (isOK && (periodicitySeparator != "__END_TARGET_VERTICES_LIST__")) {
3710           isOK = static_cast<bool>(load >> periodicitySeparator);
3711           if (periodicitySeparator != "__END_TARGET_VERTICES_LIST__") {
3712             theTargetVerticesEntries.push_back(periodicitySeparator);
3713           }
3714         }
3715       }
3716     }
3717   }
3718 }
3719
3720 //=============================================================================
3721 std::ostream & operator <<(std::ostream & save, BLSURFPlugin_Hypothesis & hyp) {
3722   return hyp.SaveTo(save);
3723 }
3724
3725 //=============================================================================
3726 std::istream & operator >>(std::istream & load, BLSURFPlugin_Hypothesis & hyp) {
3727   return hyp.LoadFrom(load);
3728 }
3729
3730 //================================================================================
3731 /*!
3732  * \brief Does nothing
3733  */
3734 //================================================================================
3735
3736 bool BLSURFPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* /*theMesh*/, const TopoDS_Shape& /*theShape*/)
3737 {
3738   return false;
3739 }
3740
3741 //================================================================================
3742 /*!
3743  * \brief Returns default global constant physical size given a default value of element length ratio
3744  */
3745 //================================================================================
3746
3747 double BLSURFPlugin_Hypothesis::GetDefaultPhySize(double diagonal, double bbSegmentation)
3748 {
3749   if (bbSegmentation != 0 && diagonal != 0)
3750     return diagonal / bbSegmentation ;
3751   return 10;
3752 }
3753
3754 //================================================================================
3755 /*!
3756  * \brief Returns default min size given a default value of element length ratio
3757  */
3758 //================================================================================
3759
3760 double BLSURFPlugin_Hypothesis::GetDefaultMinSize(double diagonal)
3761 {
3762   if (diagonal != 0)
3763     return diagonal / 1000.0 ;
3764   return undefinedDouble();
3765 }
3766
3767 //================================================================================
3768 /*!
3769  * \brief Returns default max size given a default value of element length ratio
3770  */
3771 //================================================================================
3772
3773 double BLSURFPlugin_Hypothesis::GetDefaultMaxSize(double diagonal)
3774 {
3775   if (diagonal != 0)
3776     return diagonal / 5.0 ;
3777   return undefinedDouble();
3778 }
3779
3780 //================================================================================
3781 /*!
3782  * \brief Returns default chordal error given a default value of element length ratio
3783  */
3784 //================================================================================
3785
3786 double BLSURFPlugin_Hypothesis::GetDefaultChordalError(double diagonal)
3787 {
3788   if (diagonal != 0)
3789     return diagonal;
3790   return undefinedDouble();
3791 }
3792
3793 //================================================================================
3794 /*!
3795  * \brief Returns default tiny edge length given a default value of element length ratio
3796  */
3797 //================================================================================
3798
3799 double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal)
3800 {
3801   if (diagonal != 0)
3802     return diagonal * 1e-6 ;
3803   return undefinedDouble();
3804 }
3805
3806 //================================================================================
3807 /*!
3808  * \brief Returns default tiny edge optimisation length given a default value of element length ratio
3809  */
3810 //================================================================================
3811
3812 double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeOptimisationLength(double diagonal)
3813 {
3814   if (diagonal != 0)
3815     return diagonal * 1e-6 ;
3816   return undefinedDouble();
3817 }
3818
3819 //=============================================================================
3820 /*!
3821  * \brief Initialize my parameter values by default parameters.
3822  *  \retval bool - true if parameter values have been successfully defined
3823  */
3824 //=============================================================================
3825
3826 bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
3827                                                       const SMESH_Mesh* /*theMesh*/)
3828 {
3829   _phySize = GetDefaultPhySize(dflts._diagonal, _gen->GetBoundaryBoxSegmentation());
3830   _minSize = GetDefaultMinSize(dflts._diagonal);
3831   _maxSize = GetDefaultMaxSize(dflts._diagonal);
3832   _chordalError = 0.5 * _phySize; //GetDefaultChordalError(diagonal); IMP 0023307
3833
3834   if ( dflts._way == SMESH_Hypothesis::BY_AVERAGE_LENGTH )
3835   {
3836     _phySize      = dflts._elemLength;
3837     _minSize      = dflts._elemLength / 100.;
3838     _maxSize      = dflts._elemLength * 2.;
3839     _chordalError = dflts._elemLength / 2.;
3840     _elementType  = dflts._quadDominated ? QuadrangleDominant : Triangles;
3841     _physicalMesh = PhysicalLocalSize; // to activate _enforcedInternalVerticesAllFaces
3842     _enforcedInternalVerticesAllFaces = true;
3843   }
3844   else
3845   {
3846     _tinyEdgeLength = GetDefaultTinyEdgeLength(dflts._diagonal);
3847     _tinyEdgeOptimisationLength = GetDefaultTinyEdgeOptimisationLength(dflts._diagonal);
3848   }
3849
3850   return true;
3851 }
3852
3853 //================================================================================
3854 /*!
3855  * \brief Converts a string to a bool
3856  */
3857 //================================================================================
3858
3859 bool BLSURFPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
3860 {
3861   std::string s = str;
3862   if ( isOk ) *isOk = true;
3863
3864   for ( size_t i = 0; i <= s.size(); ++i )
3865     s[i] = (char) tolower( s[i] );
3866
3867   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
3868     return true;
3869
3870   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
3871     return false;
3872
3873   if ( isOk )
3874     *isOk = false;
3875   else {
3876     std::string msg = "Not a Boolean value:'" + str + "'";
3877     throw std::invalid_argument(msg);
3878   }
3879   return false;
3880 }
3881
3882 //================================================================================
3883 /*!
3884  * \brief Converts a string to a real value
3885  */
3886 //================================================================================
3887
3888 double BLSURFPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
3889 {
3890   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
3891
3892   // Forces "C" locale to be set as LC_NUMERIC
3893   Kernel_Utils::Localizer loc;
3894
3895   char * endPtr;
3896   double val = strtod(&str[0], &endPtr);
3897   bool ok = (&str[0] != endPtr);
3898
3899   if ( isOk ) *isOk = ok;
3900
3901   if ( !ok )
3902   {
3903     std::string msg = "Not a real value:'" + str + "'";
3904     throw std::invalid_argument(msg);
3905   }
3906   return val;
3907 }
3908
3909 //================================================================================
3910 /*!
3911  * \brief Converts a string to a integer value
3912  */
3913 //================================================================================
3914
3915 int BLSURFPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
3916 {
3917   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
3918
3919   char * endPtr;
3920   int val = (int)strtol( &str[0], &endPtr, 10);
3921   bool ok = (&str[0] != endPtr);
3922
3923   if ( isOk ) *isOk = ok;
3924
3925   if ( !ok )
3926   {
3927     std::string msg = "Not an integer value:'" + str + "'";
3928     throw std::invalid_argument(msg);
3929   }
3930   return val;
3931 }
3932