Salome HOME
Merge branch 'occ/new_mg_licnese'
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_Hypothesis.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // ---
21 // File    : 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
1005     switch( enfMesh._type )
1006     {
1007     case ENFORCED_MESH:
1008       it = mesh->GetMeshDS()->elementsIterator( SMDSAbs_Edge );
1009       break;
1010
1011     case ENFORCED_GROUP:
1012       if ( SMESH_Group* grp = mesh->GetGroup( enfMesh._subID ))
1013       {
1014         if ( grp->GetGroupDS()->GetType() == SMDSAbs_Edge )
1015           it = grp->GetGroupDS()->GetElements();
1016       }
1017       break;
1018
1019     case ENFORCED_SUBMESH:
1020       if ( SMESH_subMesh* sm = mesh->GetSubMeshContaining( enfMesh._subID ))
1021         if ( SMESHDS_SubMesh * smDS = sm->GetSubMeshDS() )
1022         {
1023           it = smDS->GetElements();
1024           if ( it->more() && it->next()->GetType() != SMDSAbs_Edge )
1025             it = SMDS_ElemIteratorPtr();
1026           else
1027             it = smDS->GetElements();
1028         }
1029       break;
1030     }
1031   }
1032   return it;
1033 }
1034
1035
1036 //=============================================================================
1037 void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal)
1038 {
1039   if (theVal != ToBool( GetPreCADOptionValue("merge_edges", GET_DEFAULT()))) {
1040     _preCADMergeEdges = theVal;
1041     SetPreCADOptionValue("merge_edges", theVal ? "yes" : "no" );
1042     NotifySubMeshesHypothesisModification();
1043   }
1044 }
1045
1046 //=============================================================================
1047 void BLSURFPlugin_Hypothesis::SetPreCADRemoveDuplicateCADFaces(bool theVal)
1048 {
1049   if (theVal != ToBool( GetPreCADOptionValue("remove_duplicate_cad_faces", GET_DEFAULT()))) {
1050     _preCADRemoveDuplicateCADFaces = theVal;
1051     SetPreCADOptionValue("remove_duplicate_cad_faces", theVal ? "yes" : "no" );
1052     NotifySubMeshesHypothesisModification();
1053   }
1054 }
1055
1056 //=============================================================================
1057 void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal)
1058 {
1059   if (theVal != ToBool( GetPreCADOptionValue("process_3d_topology", GET_DEFAULT()))) {
1060     _preCADProcess3DTopology = theVal;
1061     SetPreCADOptionValue("process_3d_topology", theVal ? "yes" : "no" );
1062     NotifySubMeshesHypothesisModification();
1063   }
1064 }
1065
1066 //=============================================================================
1067 void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal)
1068 {
1069   if (theVal != ToBool( GetPreCADOptionValue("discard_input_topology", GET_DEFAULT()))) {
1070     _preCADDiscardInput = theVal;
1071     SetPreCADOptionValue("discard_input_topology", theVal ? "yes" : "no" );
1072     NotifySubMeshesHypothesisModification();
1073   }
1074 }
1075
1076 //=============================================================================
1077 // Return true if any PreCAD option is activated
1078 bool BLSURFPlugin_Hypothesis::HasPreCADOptions(const BLSURFPlugin_Hypothesis* hyp)
1079 {
1080   if ( !hyp || hyp->_name == GetHypType(/*hasgeom=*/false))
1081   {
1082     return false;
1083   }
1084   bool orDefault, isOk;
1085   return ( ToBool( hyp->GetPreCADOptionValue("closed_geometry"           , &orDefault )) ||
1086            ToBool( hyp->GetPreCADOptionValue("discard_input_topology"    , &orDefault )) ||
1087            ToBool( hyp->GetPreCADOptionValue("merge_edges"               , &orDefault )) ||
1088            ToBool( hyp->GetPreCADOptionValue("remove_duplicate_cad_faces", &orDefault )) ||
1089            ToBool( hyp->GetPreCADOptionValue("process_3d_topology"       , &orDefault )) ||
1090            ToBool( hyp->GetPreCADOption     ("manifold_geometry")        , &isOk       ) ||
1091            hyp->GetPreCADOptionValue("sewing_tolerance", &orDefault ) != "5e-4*D"        ||
1092            !hyp->_preCadFacesPeriodicityVector.empty()                                   ||
1093            !hyp->_preCadEdgesPeriodicityVector.empty()                                   ||
1094            !hyp->_facesPeriodicityVector.empty()                                         ||
1095            !hyp->_edgesPeriodicityVector.empty()                                         ||
1096            !hyp->_verticesPeriodicityVector.empty()                                      ||
1097            !hyp->GetHyperPatches().empty()                                               ||
1098            hyp->GetTopology() != FromCAD );
1099 }
1100
1101 //=============================================================================
1102 // void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName, bool isBinary)
1103 void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName)
1104 {
1105   _GMFFileName = theFileName;
1106   //   _GMFFileMode = isBinary;
1107   NotifySubMeshesHypothesisModification();
1108 }
1109
1110 //=============================================================================
1111 void BLSURFPlugin_Hypothesis::SetOptionValue(const std::string& optionName, const std::string& optionValue)
1112 {
1113   TOptionValues::iterator op_val = _option2value.find(optionName);
1114   if (op_val == _option2value.end())
1115   {
1116     op_val = _preCADoption2value.find(optionName);
1117     if (op_val == _preCADoption2value.end())
1118     {
1119       std::string msg = "Unknown MG-CADSurf option: '" + optionName + "'. Try SetAdvancedOption()";
1120       throw std::invalid_argument(msg);
1121     }
1122   }
1123   if (op_val->second != optionValue)
1124   {
1125     const char* ptr = optionValue.c_str();
1126     // strip white spaces
1127     while (ptr[0] == ' ')
1128       ptr++;
1129     size_t i = strlen(ptr);
1130     while (i != 0 && ptr[i - 1] == ' ')
1131       i--;
1132     // check value type
1133     bool typeOk = true;
1134     std::string typeName;
1135     if (i == 0) {
1136       // empty string
1137     } else if (_charOptions.count(optionName)) {
1138       // do not check strings
1139     } else if (_doubleOptions.count(optionName)) {
1140       // check if value is double
1141       ToDbl(ptr, &typeOk);
1142       typeName = "real";
1143     } else if (_boolOptions.count(optionName)) {
1144       // check if value is bool
1145       ToBool(ptr, &typeOk);
1146       typeName = "bool";
1147     } else {
1148       // check if value is int
1149       ToInt(ptr, &typeOk);
1150       typeName = "integer";
1151     }
1152     if (!typeOk) {
1153       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
1154       throw std::invalid_argument(msg);
1155     }
1156     std::string value( ptr, i );
1157     if ( _defaultOptionValues[ optionName ] == value )
1158       value.clear();
1159
1160     op_val->second = value;
1161
1162     NotifySubMeshesHypothesisModification();
1163   }
1164 }
1165
1166 //=============================================================================
1167 void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName, const std::string& optionValue)
1168 {
1169   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
1170   if (op_val == _preCADoption2value.end()) {
1171     op_val = _option2value.find(optionName);
1172     if (op_val == _option2value.end()) {
1173       std::string msg = "Unknown MG-PreCAD option: '" + optionName + "'. Try SetAdvancedOption()";
1174       throw std::invalid_argument(msg);
1175     }
1176   }
1177   if (op_val->second != optionValue)
1178   {
1179     const char* ptr = optionValue.c_str();
1180     // strip white spaces
1181     while (ptr[0] == ' ')
1182       ptr++;
1183     size_t i = strlen(ptr);
1184     while (i != 0 && ptr[i - 1] == ' ')
1185       i--;
1186     // check value type
1187     bool typeOk = true;
1188     std::string typeName;
1189     if (i == 0) {
1190       // empty string
1191     } else if (_preCADcharOptions.find(optionName) != _preCADcharOptions.end()) {
1192       // do not check strings
1193     } else if (_preCADdoubleOptions.find(optionName) != _preCADdoubleOptions.end()) {
1194       // check if value is double
1195       char * endPtr;
1196       strtod(ptr, &endPtr);
1197       typeOk = (ptr != endPtr);
1198       typeName = "real";
1199     } else if (_boolOptions.count(optionName)) {
1200       // check if value is bool
1201       ToBool(ptr, &typeOk);
1202       typeName = "bool";
1203     } else {
1204       // check if value is int
1205       char * endPtr;
1206       strtol(ptr, &endPtr, 10);
1207       typeOk = (ptr != endPtr);
1208       typeName = "integer";
1209     }
1210     if (!typeOk) {
1211       std::string msg = "PreCAD advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
1212       throw std::invalid_argument(msg);
1213     }
1214     std::string value( ptr, i );
1215     if ( _defaultOptionValues[ optionName ] == value )
1216       value.clear();
1217
1218     op_val->second = value;
1219
1220     NotifySubMeshesHypothesisModification();
1221   }
1222 }
1223
1224 //=============================================================================
1225 std::string BLSURFPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
1226                                                     bool*              isDefault) const
1227 {
1228   TOptionValues::const_iterator op_val = _option2value.find(optionName);
1229   if (op_val == _option2value.end())
1230   {
1231     op_val = _preCADoption2value.find(optionName);
1232     if (op_val == _preCADoption2value.end())
1233     {
1234       op_val = _customOption2value.find(optionName);
1235       if (op_val == _customOption2value.end())
1236       {
1237         std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
1238         throw std::invalid_argument(msg);
1239       }
1240     }
1241   }
1242   std::string val = op_val->second;
1243   if ( isDefault ) *isDefault = ( val.empty() );
1244
1245   if ( val.empty() && isDefault )
1246   {
1247     op_val = _defaultOptionValues.find( optionName );
1248     if (op_val != _defaultOptionValues.end())
1249       val = op_val->second;
1250   }
1251   return val;
1252 }
1253
1254 //=============================================================================
1255 std::string BLSURFPlugin_Hypothesis::GetPreCADOptionValue(const std::string& optionName,
1256                                                           bool*              isDefault) const
1257 {
1258   TOptionValues::const_iterator op_val = _preCADoption2value.find(optionName);
1259   if (op_val == _preCADoption2value.end())
1260   {
1261     op_val = _option2value.find(optionName);
1262     if (op_val == _option2value.end())
1263     {
1264       op_val = _customOption2value.find(optionName);
1265       if (op_val == _customOption2value.end())
1266       {
1267         std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
1268         throw std::invalid_argument(msg);
1269       }
1270     }
1271   }
1272   std::string val = op_val->second;
1273   if ( isDefault ) *isDefault = ( val.empty() );
1274
1275   if ( val.empty() && isDefault )
1276   {
1277     op_val = _defaultOptionValues.find( optionName );
1278     if (op_val != _defaultOptionValues.end())
1279       val = op_val->second;
1280   }
1281   return val;
1282 }
1283
1284 //=============================================================================
1285 void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName)
1286 {
1287   TOptionValues::iterator op_val = _customOption2value.find(optionName);
1288   if (op_val != _customOption2value.end())
1289    _customOption2value.erase(op_val);
1290   else {
1291     op_val = _option2value.find(optionName);
1292     if (op_val != _option2value.end())
1293       op_val->second.clear();
1294     else {
1295       op_val = _preCADoption2value.find(optionName);
1296       if (op_val != _preCADoption2value.end())
1297         op_val->second.clear();
1298     }
1299   }
1300 }
1301
1302 //=============================================================================
1303 void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName)
1304 {
1305   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
1306   if (op_val != _preCADoption2value.end())
1307     op_val->second.clear();
1308 }
1309
1310 //=============================================================================
1311 void BLSURFPlugin_Hypothesis::AddOption(const std::string& optionName, const std::string& optionValue)
1312 {
1313   bool modif = true;
1314   TOptionValues::iterator op_val = _option2value.find(optionName);
1315   if (op_val != _option2value.end())
1316   {
1317     if (op_val->second != optionValue)
1318       op_val->second = optionValue;
1319     else
1320       modif = false;
1321   }
1322   else
1323   {
1324     op_val = _preCADoption2value.find(optionName);
1325     if (op_val != _preCADoption2value.end())
1326     {
1327       if (op_val->second != optionValue)
1328         op_val->second = optionValue;
1329       else
1330         modif = false;
1331     }
1332     else if ( optionValue.empty() )
1333     {
1334       _customOption2value.erase( optionName );
1335     }
1336     else
1337     {
1338       op_val = _customOption2value.find(optionName);
1339       if (op_val == _customOption2value.end())
1340         _customOption2value[optionName] = optionValue;
1341       else if (op_val->second != optionValue)
1342         op_val->second = optionValue;
1343       else
1344         modif = false;
1345     }
1346   }
1347   if ( modif )
1348     NotifySubMeshesHypothesisModification();
1349 }
1350
1351 //=============================================================================
1352 void BLSURFPlugin_Hypothesis::AddPreCADOption(const std::string& optionName, const std::string& optionValue)
1353 {
1354   AddOption( optionName, optionValue );
1355 }
1356
1357 //=============================================================================
1358 std::string BLSURFPlugin_Hypothesis::GetOption(const std::string& optionName) const
1359 {
1360   TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
1361   if (op_val != _customOption2value.end())
1362     return op_val->second;
1363   else
1364     return "";
1365 }
1366
1367 //=============================================================================
1368 std::string BLSURFPlugin_Hypothesis::GetPreCADOption(const std::string& optionName) const
1369 {
1370   TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
1371   if (op_val != _customOption2value.end())
1372     return op_val->second;
1373   else
1374     return "";
1375 }
1376
1377 //=============================================================================
1378 BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetOptionValues() const
1379 {
1380   TOptionValues vals;
1381   TOptionValues::const_iterator op_val = _option2value.begin();
1382   for ( ; op_val != _option2value.end(); ++op_val )
1383     vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
1384
1385   return vals;
1386 }
1387
1388 //=============================================================================
1389 BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetPreCADOptionValues() const
1390 {
1391   TOptionValues vals;
1392   TOptionValues::const_iterator op_val = _preCADoption2value.begin();
1393   for ( ; op_val != _preCADoption2value.end(); ++op_val )
1394     vals.insert( make_pair( op_val->first, GetPreCADOptionValue( op_val->first, GET_DEFAULT() )));
1395
1396   return vals;
1397 }
1398
1399 //=======================================================================
1400 //function : SetSizeMapEntry
1401 //=======================================================================
1402 void BLSURFPlugin_Hypothesis::SetSizeMapEntry(const std::string& entry, const std::string& sizeMap) {
1403   if (_sizeMap[entry].compare(sizeMap) != 0) {
1404     SetPhysicalMesh(PhysicalLocalSize);
1405     _sizeMap[entry] = sizeMap;
1406     NotifySubMeshesHypothesisModification();
1407   }
1408 }
1409
1410 //=======================================================================
1411 //function : GetSizeMapEntry
1412 //=======================================================================
1413 std::string BLSURFPlugin_Hypothesis::GetSizeMapEntry(const std::string& entry) {
1414   TSizeMap::iterator it = _sizeMap.find(entry);
1415   if (it != _sizeMap.end())
1416     return it->second;
1417   else
1418     return "No_Such_Entry";
1419 }
1420
1421 /*!
1422  * \brief Return the size maps
1423  */
1424 BLSURFPlugin_Hypothesis::TSizeMap BLSURFPlugin_Hypothesis::GetSizeMapEntries(const BLSURFPlugin_Hypothesis* hyp) {
1425   return hyp ? hyp->_GetSizeMapEntries() : GetDefaultSizeMap();
1426 }
1427
1428 //=======================================================================
1429 //function : SetAttractorEntry
1430 //=======================================================================
1431 void BLSURFPlugin_Hypothesis::SetAttractorEntry(const std::string& entry, const std::string& attractor) {
1432   if (_attractors[entry].compare(attractor) != 0) {
1433     SetPhysicalMesh(PhysicalLocalSize);
1434     _attractors[entry] = attractor;
1435     NotifySubMeshesHypothesisModification();
1436   }
1437 }
1438
1439 //=======================================================================
1440 //function : GetAttractorEntry
1441 //=======================================================================
1442 std::string BLSURFPlugin_Hypothesis::GetAttractorEntry(const std::string& entry) {
1443   TSizeMap::iterator it = _attractors.find(entry);
1444   if (it != _attractors.end())
1445     return it->second;
1446   else
1447     return "No_Such_Entry";
1448 }
1449
1450 /*!
1451  * \brief Return the attractors
1452  */
1453 BLSURFPlugin_Hypothesis::TSizeMap BLSURFPlugin_Hypothesis::GetAttractorEntries(const BLSURFPlugin_Hypothesis* hyp) {
1454   return hyp ? hyp->_GetAttractorEntries() : GetDefaultSizeMap();
1455 }
1456
1457 //=======================================================================
1458 //function : SetClassAttractorEntry
1459 //=======================================================================
1460 void BLSURFPlugin_Hypothesis::SetClassAttractorEntry(const std::string& entry, const std::string& attEntry, double StartSize, double EndSize, double ActionRadius, double ConstantRadius)
1461 {
1462   SetPhysicalMesh(PhysicalLocalSize);
1463
1464   // The new attractor can't be defined on the same face as another sizemap
1465   TSizeMap::iterator it  = _sizeMap.find( entry );
1466   if ( it != _sizeMap.end() ) {
1467     _sizeMap.erase(it);
1468     NotifySubMeshesHypothesisModification();
1469   }
1470   else {
1471     TSizeMap::iterator itAt  = _attractors.find( entry );
1472     if ( itAt != _attractors.end() ) {
1473       _attractors.erase(itAt);
1474       NotifySubMeshesHypothesisModification();
1475     }
1476   }
1477   
1478   const TopoDS_Shape AttractorShape = BLSURFPlugin_Hypothesis::entryToShape(attEntry);
1479   const TopoDS_Face FaceShape = TopoDS::Face(BLSURFPlugin_Hypothesis::entryToShape(entry));
1480   TAttractorMap::iterator attIt = _classAttractors.find(entry);
1481   for ( ; attIt != _classAttractors.end(); ++attIt )
1482     if ( attIt->first == entry && 
1483          attIt->second->GetAttractorEntry() == attEntry )
1484       break;
1485   bool attExists = (attIt != _classAttractors.end());
1486
1487   BLSURFPlugin_Attractor* myAttractor;
1488   if ( !attExists ) {
1489     myAttractor = new BLSURFPlugin_Attractor(FaceShape, AttractorShape, attEntry);//, 0.1 );
1490     _classAttractors.insert( make_pair( entry, myAttractor ));
1491   }
1492   else {
1493     myAttractor = attIt->second;
1494   }
1495   // if (!myAttractor->IsMapBuilt())
1496   //   myAttractor->BuildMap();
1497   myAttractor->SetParameters(StartSize, EndSize, ActionRadius, ConstantRadius);
1498
1499   NotifySubMeshesHypothesisModification();
1500 }
1501
1502 //=======================================================================
1503 //function : SetConstantSizeOnAdjacentFaces
1504 //=======================================================================
1505 // TODO uncomment and test (include the needed .hxx)
1506 // SetConstantSizeOnAdjacentFaces(myShape, att_entry, startSize, endSize = user_size, const_dist  ) {
1507 //   TopTools_IndexedMapOfShapListOdShape anEdge2FaceMap;
1508 //   TopExp::MapShapesAnAncestors(myShape,TopAbs_EDGE, TopAbs_FACE, anEdge2FaceMap);
1509 //   TopTools_IndexedMapOfShapListOdShape::iterator it;
1510 //   for (it = anEdge2FaceMap.begin();it != anEdge2FaceMap.end();it++){
1511 //       SetClassAttractorEntry((*it).first, att_entry, startSize, endSize, 0, const_dist)
1512 //   }
1513
1514
1515
1516
1517
1518
1519 //=======================================================================
1520 //function : GetClassAttractorEntry
1521 //=======================================================================
1522 // BLSURFPlugin_Attractor&  BLSURFPlugin_Hypothesis::GetClassAttractorEntry(const std::string& entry)
1523 // {
1524 //  TAttractorMap::iterator it  = _classAttractors.find( entry );
1525 //  if ( it != _classAttractors.end() )
1526 //    return it->second;
1527 //  else
1528 //    return "No_Such_Entry";
1529 // }
1530 // 
1531   /*!
1532    * \brief Return the map of attractor instances
1533    */
1534 BLSURFPlugin_Hypothesis::TAttractorMap BLSURFPlugin_Hypothesis::GetClassAttractorEntries(const BLSURFPlugin_Hypothesis* hyp)
1535 {
1536     return hyp ? hyp->_GetClassAttractorEntries():GetDefaultAttractorMap();
1537 }
1538
1539 //=======================================================================
1540 //function : ClearEntry
1541 //=======================================================================
1542 void BLSURFPlugin_Hypothesis::ClearEntry(const std::string& entry,
1543                                          const char * attEntry/*=0*/)
1544 {
1545  TSizeMap::iterator it  = _sizeMap.find( entry );
1546  
1547  if ( it != _sizeMap.end() ) {
1548    _sizeMap.erase(it);
1549    NotifySubMeshesHypothesisModification();
1550  }
1551  else {
1552    TSizeMap::iterator itAt  = _attractors.find( entry );
1553    if ( itAt != _attractors.end() ) {
1554      _attractors.erase(itAt);
1555      NotifySubMeshesHypothesisModification();
1556    }
1557    else {
1558      TAttractorMap::iterator it_clAt = _classAttractors.find( entry );
1559      if ( it_clAt != _classAttractors.end() ) {
1560        do {
1561          if ( !attEntry || it_clAt->second->GetAttractorEntry() == attEntry )
1562            _classAttractors.erase( it_clAt++ );
1563          else
1564            ++it_clAt;
1565        }
1566        while ( it_clAt != _classAttractors.end() );
1567        NotifySubMeshesHypothesisModification();
1568      }
1569      else
1570        std::cout<<"No_Such_Entry"<<std::endl;
1571    }
1572  }
1573 }
1574
1575 //=======================================================================
1576 //function : ClearSizeMaps
1577 //=======================================================================
1578 void BLSURFPlugin_Hypothesis::ClearSizeMaps() {
1579   _sizeMap.clear();
1580   _attractors.clear();
1581   _classAttractors.clear();
1582 }
1583
1584 // Enable internal enforced vertices on specific face if requested by user
1585
1586 ////=======================================================================
1587 ////function : SetInternalEnforcedVertex
1588 ////=======================================================================
1589 //void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertex(TEntry theFaceEntry,
1590 //                                                        bool toEnforceInternalVertices,
1591 //                                                        TEnfGroupName theGroupName) {
1592
1593 //      << toEnforceInternalVertices << ", " << theGroupName << ")");
1594   
1595 //  TFaceEntryInternalVerticesList::iterator it = _faceEntryInternalVerticesList.find(theFaceEntry);
1596 //  if (it != _faceEntryInternalVerticesList.end()) {
1597 //    if (!toEnforceInternalVertices) {
1598 //      _faceEntryInternalVerticesList.erase(it);
1599 //    }
1600 //  }
1601 //  else {
1602 //    if (toEnforceInternalVertices) {
1603 //      _faceEntryInternalVerticesList.insert(theFaceEntry);
1604 //    }
1605 //  }
1606   
1607 //  // TODO
1608 //  // Take care of groups
1609 //}
1610
1611
1612 //=======================================================================
1613 //function : SetEnforcedVertex
1614 //=======================================================================
1615 bool BLSURFPlugin_Hypothesis::SetEnforcedVertex(TEntry        theFaceEntry,
1616                                                 TEnfName      theVertexName,
1617                                                 TEntry        theVertexEntry,
1618                                                 TEnfGroupName theGroupName,
1619                                                 double x, double y, double z)
1620 {
1621   SetPhysicalMesh(PhysicalLocalSize);
1622
1623   bool toNotify = false;
1624   bool toCreate = true;
1625
1626   TEnfVertex *oldEnVertex;
1627   TEnfVertex *newEnfVertex = new TEnfVertex();
1628   newEnfVertex->name = theVertexName;
1629   newEnfVertex->geomEntry = theVertexEntry;
1630   newEnfVertex->coords.clear();
1631   if (theVertexEntry == "") {
1632     newEnfVertex->coords.push_back(x);
1633     newEnfVertex->coords.push_back(y);
1634     newEnfVertex->coords.push_back(z);
1635   }
1636   newEnfVertex->grpName = theGroupName;
1637   newEnfVertex->faceEntries.clear();
1638   newEnfVertex->faceEntries.insert(theFaceEntry);
1639
1640
1641   // update _enfVertexList
1642   TEnfVertexList::iterator it = _enfVertexList.find(newEnfVertex);
1643   if (it != _enfVertexList.end()) {
1644     toCreate = false;
1645     oldEnVertex = (*it);
1646     if (oldEnVertex->name != theVertexName) {
1647       oldEnVertex->name = theVertexName;
1648       toNotify = true;
1649     }
1650     if (oldEnVertex->grpName != theGroupName) {
1651       oldEnVertex->grpName = theGroupName;
1652       toNotify = true;
1653     }
1654     TEntryList::iterator it_faceEntries = oldEnVertex->faceEntries.find(theFaceEntry);
1655     if (it_faceEntries == oldEnVertex->faceEntries.end()) {
1656       oldEnVertex->faceEntries.insert(theFaceEntry);
1657       _faceEntryEnfVertexListMap[theFaceEntry].insert(oldEnVertex);
1658       toNotify = true;
1659     }
1660     if (toNotify) {
1661       // update map coords / enf vertex if needed
1662       if (oldEnVertex->coords.size()) {
1663         _coordsEnfVertexMap[oldEnVertex->coords] = oldEnVertex;
1664         _faceEntryCoordsListMap[theFaceEntry].insert(oldEnVertex->coords);
1665       }
1666
1667       // update map geom entry / enf vertex if needed
1668       if (oldEnVertex->geomEntry != "") {
1669         _enfVertexEntryEnfVertexMap[oldEnVertex->geomEntry] = oldEnVertex;
1670         _faceEntryEnfVertexEntryListMap[theFaceEntry].insert(oldEnVertex->geomEntry);
1671       }
1672     }
1673   }
1674
1675 //   //////// CREATE ////////////
1676   if (toCreate) {
1677     toNotify = true;
1678     AddEnforcedVertex( theFaceEntry, newEnfVertex );
1679   }
1680   else {
1681     delete newEnfVertex;
1682   }
1683
1684   if (toNotify)
1685     NotifySubMeshesHypothesisModification();
1686
1687   return toNotify;
1688 }
1689
1690 //=======================================================================
1691 //function : AddEnforcedVertex
1692 //=======================================================================
1693
1694 void BLSURFPlugin_Hypothesis::AddEnforcedVertex( const TEntry& faceEntry,
1695                                                  TEnfVertex *  newEnfVertex )
1696 {
1697   if ( newEnfVertex )
1698   {
1699     _faceEntryEnfVertexListMap[faceEntry].insert(newEnfVertex);
1700     _enfVertexList.insert(newEnfVertex);
1701     if ( newEnfVertex->geomEntry.empty() ) {
1702       _faceEntryCoordsListMap[faceEntry].insert(newEnfVertex->coords);
1703       _coordsEnfVertexMap[newEnfVertex->coords] = newEnfVertex;
1704     }
1705     else {
1706       _faceEntryEnfVertexEntryListMap[faceEntry].insert(newEnfVertex->geomEntry);
1707       _enfVertexEntryEnfVertexMap[newEnfVertex->geomEntry] = newEnfVertex;
1708     }
1709   }
1710 }
1711
1712 //=======================================================================
1713 //function : GetEnforcedVertices
1714 //=======================================================================
1715
1716 BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetEnfVertexList(const TEntry& theFaceEntry)
1717 {
1718   if (_faceEntryEnfVertexListMap.count(theFaceEntry) > 0)
1719     return _faceEntryEnfVertexListMap[theFaceEntry];
1720   else
1721     return GetDefaultEnfVertexList();
1722
1723   std::ostringstream msg;
1724   msg << "No enforced vertex for face entry " << theFaceEntry;
1725   throw std::invalid_argument(msg.str());
1726 }
1727
1728 //=======================================================================
1729 //function : GetEnfVertexCoordsList
1730 //=======================================================================
1731
1732 BLSURFPlugin_Hypothesis::TEnfVertexCoordsList BLSURFPlugin_Hypothesis::GetEnfVertexCoordsList(const TEntry& theFaceEntry)
1733 {
1734   if (_faceEntryCoordsListMap.count(theFaceEntry) > 0)
1735     return _faceEntryCoordsListMap[theFaceEntry];
1736
1737   std::ostringstream msg;
1738   msg << "No enforced vertex coords for face entry " << theFaceEntry;
1739   throw std::invalid_argument(msg.str());
1740 }
1741
1742 //=======================================================================
1743 //function : GetEnfVertexEntryList
1744 //=======================================================================
1745
1746 BLSURFPlugin_Hypothesis::TEntryList BLSURFPlugin_Hypothesis::GetEnfVertexEntryList(const TEntry& theFaceEntry)
1747 {
1748   if (_faceEntryEnfVertexEntryListMap.count(theFaceEntry) > 0)
1749     return _faceEntryEnfVertexEntryListMap[theFaceEntry];
1750
1751   std::ostringstream msg;
1752   msg << "No enforced vertex entry for face entry " << theFaceEntry;
1753   throw std::invalid_argument(msg.str());
1754 }
1755
1756 //=======================================================================
1757 //function : GetEnfVertex(TEnfVertexCoords coords)
1758 //=======================================================================
1759
1760 BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(TEnfVertexCoords coords)
1761 {
1762   if (_coordsEnfVertexMap.count(coords) > 0)
1763     return _coordsEnfVertexMap[coords];
1764
1765   std::ostringstream msg;
1766   msg << "No enforced vertex with coords (" << coords[0] << ", " << coords[1] << ", " << coords[2] << ")";
1767   throw std::invalid_argument(msg.str());
1768 }
1769
1770 //=======================================================================
1771 //function : GetEnfVertex(const TEntry& theEnfVertexEntry)
1772 //=======================================================================
1773
1774 BLSURFPlugin_Hypothesis::TEnfVertex* BLSURFPlugin_Hypothesis::GetEnfVertex(const TEntry& theEnfVertexEntry)
1775 {
1776   if (_enfVertexEntryEnfVertexMap.count(theEnfVertexEntry) > 0)
1777     return _enfVertexEntryEnfVertexMap[theEnfVertexEntry];
1778
1779   std::ostringstream msg;
1780   msg << "No enforced vertex with entry " << theEnfVertexEntry;
1781   throw std::invalid_argument(msg.str());
1782 }
1783
1784 //Enable internal enforced vertices on specific face if requested by user
1785 ////=======================================================================
1786 ////function : GetInternalEnforcedVertex
1787 ////=======================================================================
1788
1789 //bool BLSURFPlugin_Hypothesis::GetInternalEnforcedVertex(const TEntry& theFaceEntry)
1790 //{
1791 //  if (_faceEntryInternalVerticesList.count(theFaceEntry) > 0)
1792 //    return true;
1793 //  return false;
1794 //}
1795
1796 //=======================================================================
1797 //function : ClearEnforcedVertex
1798 //=======================================================================
1799
1800 bool BLSURFPlugin_Hypothesis::ClearEnforcedVertex(const TEntry& theFaceEntry,
1801                                                   double x, double y, double z,
1802                                                   const TEntry& theVertexEntry)
1803 {
1804   bool toNotify = false;
1805   std::ostringstream msg;
1806   TEnfVertex *oldEnfVertex;
1807   TEnfVertexCoords coords;
1808   coords.clear();
1809   coords.push_back(x);
1810   coords.push_back(y);
1811   coords.push_back(z);
1812
1813   // check that enf vertex with given enf vertex entry exists
1814   TEnfVertexEntryEnfVertexMap::iterator it_enfVertexEntry = _enfVertexEntryEnfVertexMap.find(theVertexEntry);
1815   if (it_enfVertexEntry != _enfVertexEntryEnfVertexMap.end()) {
1816     // Success
1817     oldEnfVertex = it_enfVertexEntry->second;
1818
1819     _enfVertexEntryEnfVertexMap.erase(it_enfVertexEntry);
1820
1821     TEntryList& enfVertexEntryList = _faceEntryEnfVertexEntryListMap[theFaceEntry];
1822     enfVertexEntryList.erase(theVertexEntry);
1823     if (enfVertexEntryList.size() == 0)
1824       _faceEntryEnfVertexEntryListMap.erase(theFaceEntry);
1825     //    TFaceEntryEnfVertexEntryListMap::iterator it_entry_entry = _faceEntryEnfVertexEntryListMap.find(theFaceEntry);
1826     //    TEntryList::iterator it_entryList = it_entry_entry->second.find(theVertexEntry);
1827     //    it_entry_entry->second.erase(it_entryList);
1828     //    if (it_entry_entry->second.size() == 0)
1829     //      _faceEntryEnfVertexEntryListMap.erase(it_entry_entry);
1830   } else {
1831     // Fail
1832     MESSAGE("Enforced vertex with geom entry " << theVertexEntry << " not found");
1833     msg << "No enforced vertex with geom entry " << theVertexEntry;
1834     // check that enf vertex with given coords exists
1835     TCoordsEnfVertexMap::iterator it_coords_enf = _coordsEnfVertexMap.find(coords);
1836     if (it_coords_enf != _coordsEnfVertexMap.end()) {
1837       // Success
1838       oldEnfVertex = it_coords_enf->second;
1839
1840       _coordsEnfVertexMap.erase(it_coords_enf);
1841
1842       TEnfVertexCoordsList& enfVertexCoordsList = _faceEntryCoordsListMap[theFaceEntry];
1843       enfVertexCoordsList.erase(coords);
1844       if (enfVertexCoordsList.size() == 0)
1845         _faceEntryCoordsListMap.erase(theFaceEntry);
1846       //      TFaceEntryCoordsListMap::iterator it_entry_coords = _faceEntryCoordsListMap.find(theFaceEntry);
1847       //      TEnfVertexCoordsList::iterator it_coordsList = it_entry_coords->second.find(coords);
1848       //      it_entry_coords->second.erase(it_coordsList);
1849       //      if (it_entry_coords->second.size() == 0)
1850       //        _faceEntryCoordsListMap.erase(it_entry_coords);
1851     } else {
1852       // Fail
1853       MESSAGE("Enforced vertex with coords " << x << ", " << y << ", " << z << " not found");
1854       msg << std::endl;
1855       msg << "No enforced vertex at " << x << ", " << y << ", " << z;
1856       throw std::invalid_argument(msg.str());
1857     }
1858   }
1859
1860   // update _enfVertexList
1861   TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1862   if (it != _enfVertexList.end()) {
1863     (*it)->faceEntries.erase(theFaceEntry);
1864     if ((*it)->faceEntries.size() == 0){
1865       _enfVertexList.erase(it);
1866       toNotify = true;
1867     }
1868   }
1869
1870   // update _faceEntryEnfVertexListMap
1871   TEnfVertexList& currentEnfVertexList = _faceEntryEnfVertexListMap[theFaceEntry];
1872   currentEnfVertexList.erase(oldEnfVertex);
1873
1874   if (currentEnfVertexList.size() == 0) {
1875     _faceEntryEnfVertexListMap.erase(theFaceEntry);
1876   }
1877
1878   if (toNotify)
1879     NotifySubMeshesHypothesisModification();
1880
1881   return toNotify;
1882 }
1883
1884 //=======================================================================
1885 //function : ClearEnforcedVertices
1886 //=======================================================================
1887
1888 bool BLSURFPlugin_Hypothesis::ClearEnforcedVertices(const TEntry& theFaceEntry)
1889 {
1890   bool toNotify = false;
1891   TEnfVertex *oldEnfVertex;
1892
1893   TFaceEntryCoordsListMap::iterator it_entry_coords = _faceEntryCoordsListMap.find(theFaceEntry);
1894   if (it_entry_coords != _faceEntryCoordsListMap.end()) {
1895     toNotify = true;
1896     TEnfVertexCoordsList coordsList = it_entry_coords->second;
1897     TEnfVertexCoordsList::iterator it_coordsList = coordsList.begin();
1898     for (; it_coordsList != coordsList.end(); ++it_coordsList) {
1899       TEnfVertexCoords coords = (*it_coordsList);
1900       oldEnfVertex = _coordsEnfVertexMap[coords];
1901       _coordsEnfVertexMap.erase(coords);
1902       // update _enfVertexList
1903       TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1904       if (it != _enfVertexList.end()) {
1905         (*it)->faceEntries.erase(theFaceEntry);
1906         if ((*it)->faceEntries.size() == 0){
1907           _enfVertexList.erase(it);
1908           toNotify = true;
1909         }
1910       }
1911     }
1912     _faceEntryCoordsListMap.erase(it_entry_coords);
1913     _faceEntryEnfVertexListMap.erase(theFaceEntry);
1914   }
1915
1916   TFaceEntryEnfVertexEntryListMap::iterator it_entry_entry = _faceEntryEnfVertexEntryListMap.find(theFaceEntry);
1917   if (it_entry_entry != _faceEntryEnfVertexEntryListMap.end()) {
1918     toNotify = true;
1919     TEntryList enfVertexEntryList = it_entry_entry->second;
1920     TEntryList::iterator it_enfVertexEntryList = enfVertexEntryList.begin();
1921     for (; it_enfVertexEntryList != enfVertexEntryList.end(); ++it_enfVertexEntryList) {
1922       TEntry enfVertexEntry = (*it_enfVertexEntryList);
1923       oldEnfVertex = _enfVertexEntryEnfVertexMap[enfVertexEntry];
1924       _enfVertexEntryEnfVertexMap.erase(enfVertexEntry);
1925       // update _enfVertexList
1926       TEnfVertexList::iterator it = _enfVertexList.find(oldEnfVertex);
1927       if (it != _enfVertexList.end()) {
1928         (*it)->faceEntries.erase(theFaceEntry);
1929         if ((*it)->faceEntries.size() == 0){
1930           _enfVertexList.erase(it);
1931           toNotify = true;
1932         }
1933       }
1934     }
1935     _faceEntryEnfVertexEntryListMap.erase(it_entry_entry);
1936     _faceEntryEnfVertexListMap.erase(theFaceEntry);
1937   }
1938
1939   if (toNotify)
1940     NotifySubMeshesHypothesisModification();
1941
1942   return toNotify;
1943   //  std::ostringstream msg;
1944   //  msg << "No enforced vertex for " << theFaceEntry;
1945   //  throw std::invalid_argument(msg.str());
1946 }
1947
1948 //=======================================================================
1949 //function : ClearAllEnforcedVertices
1950 //=======================================================================
1951 void BLSURFPlugin_Hypothesis::ClearAllEnforcedVertices()
1952 {
1953   _faceEntryEnfVertexListMap.clear();
1954   _faceEntryCoordsListMap.clear();
1955   _coordsEnfVertexMap.clear();
1956   _faceEntryEnfVertexEntryListMap.clear();
1957   _enfVertexEntryEnfVertexMap.clear();
1958   
1959   TEnfVertexList::iterator it_enfVertex = _enfVertexList.begin();
1960   for ( ; it_enfVertex != _enfVertexList.end(); ++it_enfVertex )
1961     delete *it_enfVertex;
1962   _enfVertexList.clear();
1963
1964 //  Enable internal enforced vertices on specific face if requested by user
1965 //  _faceEntryInternalVerticesList.clear();
1966   NotifySubMeshesHypothesisModification();
1967 }
1968
1969
1970 //================================================================================
1971 /*!
1972  * \brief Return the enforced vertices
1973  */
1974 //================================================================================
1975
1976
1977 BLSURFPlugin_Hypothesis::TFaceEntryEnfVertexListMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByFace(
1978     const BLSURFPlugin_Hypothesis* hyp)
1979 {
1980   return hyp ? hyp->_GetAllEnforcedVerticesByFace() : GetDefaultFaceEntryEnfVertexListMap();
1981 }
1982
1983 //Enable internal enforced vertices on specific face if requested by user
1984 //BLSURFPlugin_Hypothesis::TFaceEntryInternalVerticesList BLSURFPlugin_Hypothesis::GetAllInternalEnforcedVerticesByFace(
1985 //    const BLSURFPlugin_Hypothesis* hyp) {
1986 //  return hyp ? hyp->_GetAllInternalEnforcedVerticesByFace() : GetDefaultFaceEntryInternalVerticesMap();
1987 //}
1988
1989 bool BLSURFPlugin_Hypothesis::GetInternalEnforcedVertexAllFaces(const BLSURFPlugin_Hypothesis* hyp)
1990 {
1991   return hyp ? hyp->_GetInternalEnforcedVertexAllFaces() : GetDefaultInternalEnforcedVertex();
1992 }
1993
1994 BLSURFPlugin_Hypothesis::TEnfGroupName BLSURFPlugin_Hypothesis::GetInternalEnforcedVertexAllFacesGroup(const BLSURFPlugin_Hypothesis* hyp)
1995 {
1996   return hyp ? hyp->_GetInternalEnforcedVertexAllFacesGroup() : BLSURFPlugin_Hypothesis::TEnfGroupName();
1997 }
1998
1999 BLSURFPlugin_Hypothesis::TEnfVertexList BLSURFPlugin_Hypothesis::GetAllEnforcedVertices(
2000     const BLSURFPlugin_Hypothesis* hyp)
2001 {
2002   return hyp ? hyp->_GetAllEnforcedVertices() : GetDefaultEnfVertexList();
2003 }
2004
2005 BLSURFPlugin_Hypothesis::TFaceEntryCoordsListMap BLSURFPlugin_Hypothesis::GetAllCoordsByFace(
2006     const BLSURFPlugin_Hypothesis* hyp)
2007 {
2008   return hyp ? hyp->_GetAllCoordsByFace() : GetDefaultFaceEntryCoordsListMap();
2009 }
2010
2011 BLSURFPlugin_Hypothesis::TCoordsEnfVertexMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByCoords(
2012     const BLSURFPlugin_Hypothesis* hyp)
2013 {
2014   return hyp ? hyp->_GetAllEnforcedVerticesByCoords() : GetDefaultCoordsEnfVertexMap();
2015 }
2016
2017 BLSURFPlugin_Hypothesis::TFaceEntryEnfVertexEntryListMap BLSURFPlugin_Hypothesis::GetAllEnfVertexEntriesByFace(
2018     const BLSURFPlugin_Hypothesis* hyp)
2019 {
2020   return hyp ? hyp->_GetAllEnfVertexEntriesByFace() : GetDefaultFaceEntryEnfVertexEntryListMap();
2021 }
2022
2023 BLSURFPlugin_Hypothesis::TEnfVertexEntryEnfVertexMap BLSURFPlugin_Hypothesis::GetAllEnforcedVerticesByEnfVertexEntry(
2024     const BLSURFPlugin_Hypothesis* hyp)
2025 {
2026   return hyp ? hyp->_GetAllEnforcedVerticesByEnfVertexEntry() : GetDefaultEnfVertexEntryEnfVertexMap();
2027 }
2028
2029 std::set<smIdType> BLSURFPlugin_Hypothesis::GetEnfVertexNodeIDs(TEnfGroupName theGroupName)
2030 {
2031   TGroupNameNodeIDMap::const_iterator it = _groupNameNodeIDMap.find(theGroupName);
2032   if (it != _groupNameNodeIDMap.end()) {
2033     return it->second;
2034   }
2035   std::ostringstream msg;
2036   msg << "No group " << theGroupName;
2037   throw std::invalid_argument(msg.str());
2038 }
2039
2040 void BLSURFPlugin_Hypothesis::AddEnfVertexNodeID(TEnfGroupName theGroupName,smIdType theNodeID)
2041 {
2042   _groupNameNodeIDMap[theGroupName].insert(theNodeID);
2043 }
2044
2045 void BLSURFPlugin_Hypothesis::RemoveEnfVertexNodeID(TEnfGroupName theGroupName,smIdType theNodeID)
2046 {
2047   TGroupNameNodeIDMap::iterator it = _groupNameNodeIDMap.find(theGroupName);
2048   if (it != _groupNameNodeIDMap.end()) {
2049     std::set<smIdType>::iterator IDit = it->second.find(theNodeID);
2050     if (IDit != it->second.end())
2051       it->second.erase(IDit);
2052     std::ostringstream msg;
2053     msg << "No node IDs " << theNodeID << " for group " << theGroupName;
2054     throw std::invalid_argument(msg.str());
2055   }
2056   std::ostringstream msg;
2057   msg << "No group " << theGroupName;
2058   throw std::invalid_argument(msg.str());
2059 }
2060
2061
2062 //=============================================================================
2063 void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceInternalVertices)
2064 {
2065   if (toEnforceInternalVertices != _enforcedInternalVerticesAllFaces) {
2066     _enforcedInternalVerticesAllFaces = toEnforceInternalVertices;
2067     if (toEnforceInternalVertices)
2068       SetPhysicalMesh(PhysicalLocalSize);
2069     NotifySubMeshesHypothesisModification();
2070   }
2071 }
2072
2073
2074 //=============================================================================
2075 void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugin_Hypothesis::TEnfGroupName theGroupName)
2076 {
2077   if (std::string(theGroupName) != std::string(_enforcedInternalVerticesAllFacesGroup)) {
2078     _enforcedInternalVerticesAllFacesGroup = theGroupName;
2079     NotifySubMeshesHypothesisModification();
2080   }
2081 }
2082
2083 //=============================================================================
2084 BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector BLSURFPlugin_Hypothesis::GetPreCadFacesPeriodicityVector(
2085     const BLSURFPlugin_Hypothesis* hyp)
2086 {
2087   return hyp ? hyp->_GetPreCadFacesPeriodicityVector() : GetDefaultPreCadFacesPeriodicityVector();
2088 }
2089
2090 //=============================================================================
2091 BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector BLSURFPlugin_Hypothesis::GetPreCadEdgesPeriodicityVector(
2092     const BLSURFPlugin_Hypothesis* hyp)
2093 {
2094   return hyp ? hyp->_GetPreCadEdgesPeriodicityVector() : GetDefaultPreCadEdgesPeriodicityVector();
2095 }
2096
2097 //=============================================================================
2098 BLSURFPlugin_Hypothesis::TFacesPeriodicityVector BLSURFPlugin_Hypothesis::GetFacesPeriodicityVector(
2099     const BLSURFPlugin_Hypothesis* hyp)
2100 {
2101   return hyp ? hyp->_GetFacesPeriodicityVector() : GetDefaultFacesPeriodicityVector();
2102 }
2103
2104 //=============================================================================
2105 BLSURFPlugin_Hypothesis::TEdgesPeriodicityVector BLSURFPlugin_Hypothesis::GetEdgesPeriodicityVector(
2106     const BLSURFPlugin_Hypothesis* hyp)
2107 {
2108   return hyp ? hyp->_GetEdgesPeriodicityVector() : GetDefaultEdgesPeriodicityVector();
2109 }
2110
2111 //=============================================================================
2112 BLSURFPlugin_Hypothesis::TVerticesPeriodicityVector BLSURFPlugin_Hypothesis::GetVerticesPeriodicityVector(
2113     const BLSURFPlugin_Hypothesis* hyp)
2114 {
2115   return hyp ? hyp->_GetVerticesPeriodicityVector() : GetDefaultVerticesPeriodicityVector();
2116 }
2117
2118 //=======================================================================
2119 //function : ClearAllEnforcedVertices
2120 //=======================================================================
2121 void BLSURFPlugin_Hypothesis::ClearPreCadPeriodicityVectors()
2122 {
2123   _preCadFacesPeriodicityVector.clear();
2124   _preCadEdgesPeriodicityVector.clear();
2125   NotifySubMeshesHypothesisModification();
2126 }
2127
2128 //=======================================================================
2129 //function : AddPreCadFacesPeriodicity
2130 //=======================================================================
2131 void BLSURFPlugin_Hypothesis::AddPreCadFacesPeriodicity(TEntry theFace1Entry, TEntry theFace2Entry,
2132                                                         std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries)
2133 {
2134
2135   TPreCadPeriodicity preCadFacesPeriodicity;
2136   preCadFacesPeriodicity.shape1Entry = theFace1Entry;
2137   preCadFacesPeriodicity.shape2Entry = theFace2Entry;
2138   preCadFacesPeriodicity.theSourceVerticesEntries = theSourceVerticesEntries;
2139   preCadFacesPeriodicity.theTargetVerticesEntries = theTargetVerticesEntries;
2140
2141   _preCadFacesPeriodicityVector.push_back(preCadFacesPeriodicity);
2142
2143   NotifySubMeshesHypothesisModification();
2144 }
2145
2146 //=======================================================================
2147 //function : AddPreCadEdgesPeriodicity
2148 //=======================================================================
2149 void BLSURFPlugin_Hypothesis::AddPreCadEdgesPeriodicity(TEntry theEdge1Entry, TEntry theEdge2Entry,
2150     std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries)
2151 {
2152   TPreCadPeriodicity preCadEdgesPeriodicity;
2153   preCadEdgesPeriodicity.shape1Entry = theEdge1Entry;
2154   preCadEdgesPeriodicity.shape2Entry = theEdge2Entry;
2155   preCadEdgesPeriodicity.theSourceVerticesEntries = theSourceVerticesEntries;
2156   preCadEdgesPeriodicity.theTargetVerticesEntries = theTargetVerticesEntries;
2157
2158   _preCadEdgesPeriodicityVector.push_back(preCadEdgesPeriodicity);
2159
2160   NotifySubMeshesHypothesisModification();
2161 }
2162
2163 //=============================================================================
2164 std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save)
2165 {
2166   // We must keep at least the same number of arguments when increasing the SALOME version
2167   // When MG-CADSurf becomes CADMESH, some parameters were fused into a single one. Thus the same
2168   // parameter can be written several times to keep the old global number of parameters.
2169
2170   // Treat old options which are now in the advanced options
2171   TOptionValues::iterator op_val;
2172   int _decimesh = -1;
2173   int _preCADRemoveNanoEdges = -1;
2174   double _preCADEpsNano = -1.0;
2175   op_val = _option2value.find("respect_geometry");
2176   if (op_val != _option2value.end()) {
2177     std::string value = op_val->second;
2178     if (!value.empty())
2179       _decimesh = value.compare("1") == 0 ? 1 : 0;
2180   }
2181   op_val = _preCADoption2value.find("remove_tiny_edges");
2182   if (op_val != _preCADoption2value.end()) {
2183     std::string value = op_val->second;
2184     if (!value.empty())
2185       _preCADRemoveNanoEdges = value.compare("1") == 0 ? 1 : 0;
2186   }
2187   op_val = _preCADoption2value.find("tiny_edge_length");
2188   if (op_val != _preCADoption2value.end()) {
2189     std::string value = op_val->second;
2190     if (!value.empty())
2191       _preCADEpsNano = strtod(value.c_str(), NULL);
2192   }
2193
2194   save << " " << (int) _topology << " " << (int) _physicalMesh << " " << (int) _geometricMesh << " " << _phySize << " "
2195        << _angleMesh << " " << _gradation << " " << (int) _elementType << " " << _decimesh;
2196   save << " " << _minSize << " " << _maxSize << " " << _angleMesh << " " << _minSize << " " << _maxSize << " " << _verb;
2197   save << " " << (int) _preCADMergeEdges << " " << _preCADRemoveNanoEdges << " " << (int) _preCADDiscardInput << " " << _preCADEpsNano ;
2198   save << " " << (int) _enforcedInternalVerticesAllFaces;
2199   save << " " << (int) _phySizeRel << " " << (int) _minSizeRel << " " << (int) _maxSizeRel << " " << _chordalError ;
2200   save << " " << (int) _anisotropic << " " << _anisotropicRatio << " " << (int) _removeTinyEdges << " " << _tinyEdgeLength ;
2201   save << " " << (int) _badElementRemoval << " " << _badElementAspectRatio << " " << (int) _optimizeMesh << " " << (int) _quadraticMesh ;
2202   save << " " << (int) _preCADProcess3DTopology << " " << (int) _preCADRemoveDuplicateCADFaces;
2203   save << " " << (int)_optimiseTinyEdges << " " << _tinyEdgeOptimisationLength;
2204   save << " " << (int)_correctSurfaceIntersec << " " << _corrSurfaceIntersCost;
2205   save << " " << (int)_useGradation << " " << (int)_useVolumeGradation << " " << _volumeGradation;
2206
2207   op_val = _option2value.begin();
2208   if (op_val != _option2value.end()) {
2209     save << " " << "__OPTIONS_BEGIN__";
2210     for (; op_val != _option2value.end(); ++op_val) {
2211       if (!op_val->second.empty())
2212         save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
2213     }
2214     save << " " << "__OPTIONS_END__";
2215   }
2216   
2217   op_val = _customOption2value.begin();
2218   if (op_val != _customOption2value.end()) {
2219     save << " " << "__CUSTOM_OPTIONS_BEGIN__";
2220     for (; op_val != _customOption2value.end(); ++op_val) {
2221       if (!op_val->second.empty())
2222         save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
2223     }
2224     save << " " << "__CUSTOM_OPTIONS_END__";
2225   }
2226
2227   op_val = _preCADoption2value.begin();
2228   if (op_val != _preCADoption2value.end()) {
2229     save << " " << "__PRECAD_OPTIONS_BEGIN__";
2230     for (; op_val != _preCADoption2value.end(); ++op_val) {
2231       if (!op_val->second.empty())
2232         save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
2233     }
2234     save << " " << "__PRECAD_OPTIONS_END__";
2235   }
2236
2237   TSizeMap::iterator it_sm = _sizeMap.begin();
2238   if (it_sm != _sizeMap.end()) {
2239     save << " " << "__SIZEMAP_BEGIN__";
2240     for (; it_sm != _sizeMap.end(); ++it_sm) {
2241       save << " " << it_sm->first << " " << it_sm->second << "%#"; // "%#" is a mark of value end
2242     }
2243     save << " " << "__SIZEMAP_END__";
2244   }
2245
2246   TSizeMap::iterator it_at = _attractors.begin();
2247   if (it_at != _attractors.end()) {
2248     save << " " << "__ATTRACTORS_BEGIN__";
2249     for (; it_at != _attractors.end(); ++it_at) {
2250       save << " " << it_at->first << " " << it_at->second << "%#"; // "%#" is a mark of value end
2251     }
2252     save << " " << "__ATTRACTORS_END__";
2253   }
2254   
2255   TAttractorMap::iterator it_At = _classAttractors.begin();
2256   if (it_At != _classAttractors.end()) {
2257     std::ostringstream test;
2258     save << " " << "__NEW_ATTRACTORS_BEGIN__";
2259     test << " " << "__NEW_ATTRACTORS_BEGIN__";
2260     for (; it_At != _classAttractors.end(); ++it_At) {
2261       std::vector<double> attParams;
2262       attParams   = it_At->second->GetParameters();
2263 //       double step = it_At->second->GetStep();
2264       save << " " << it_At->first;
2265       save << " " << it_At->second->GetAttractorEntry();
2266       save << " " << attParams[0]  << " " <<  attParams[1] << " " <<  attParams[2] << " " <<  attParams[3];
2267 //       save << " " << step;
2268       test << " " << it_At->first;
2269       test << " " << it_At->second->GetAttractorEntry();
2270       test << " " << attParams[0]  << " " <<  attParams[1] << " " <<  attParams[2] << " " <<  attParams[3];
2271 //       test << " " << step;
2272     }
2273     save << " " << "__NEW_ATTRACTORS_END__";
2274     test << " " << "__NEW_ATTRACTORS_END__";
2275   }
2276
2277   TEnfVertexList::const_iterator it_enf = _enfVertexList.begin();
2278   if (it_enf != _enfVertexList.end()) {
2279     save << " " << "__ENFORCED_VERTICES_BEGIN__";
2280     for (; it_enf != _enfVertexList.end(); ++it_enf) {
2281       TEnfVertex *enfVertex = (*it_enf);
2282       save << " " << "__BEGIN_VERTEX__";
2283       if (!enfVertex->name.empty()) {
2284         save << " " << "__BEGIN_NAME__";
2285         save << " " << enfVertex->name;
2286         save << " " << "__END_NAME__";
2287       }
2288       if (!enfVertex->geomEntry.empty()) {
2289         save << " " << "__BEGIN_ENTRY__";
2290         save << " " << enfVertex->geomEntry;
2291         save << " " << "__END_ENTRY__";
2292       }
2293       if (!enfVertex->grpName.empty()) {
2294         save << " " << "__BEGIN_GROUP__";
2295         save << " " << enfVertex->grpName;
2296         save << " " << "__END_GROUP__";
2297       }
2298       if (enfVertex->coords.size()) {
2299         save << " " << "__BEGIN_COORDS__";
2300         for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
2301           save << " " << enfVertex->coords[i];
2302         save << " " << "__END_COORDS__";
2303       }
2304       TEntryList::const_iterator faceEntriesIt = enfVertex->faceEntries.begin();
2305       bool hasFaces = false;
2306       if (faceEntriesIt != enfVertex->faceEntries.end()) {
2307         hasFaces = true;
2308         save << " " << "__BEGIN_FACELIST__";
2309       }
2310       for (; faceEntriesIt != enfVertex->faceEntries.end(); ++faceEntriesIt)
2311         if ( faceEntriesIt->empty() )
2312           save << " _no_face_";
2313         else
2314           save << " " << (*faceEntriesIt);
2315       if (hasFaces)
2316         save << " " << "__END_FACELIST__";
2317       save << " " << "__END_VERTEX__";
2318     }
2319     save << " " << "__ENFORCED_VERTICES_END__";
2320   }
2321
2322   //PERIODICITY
2323
2324   SavePreCADPeriodicity(save, "FACES");
2325   SavePreCADPeriodicity(save, "EDGES");
2326
2327   SaveFacesPeriodicity(save);
2328   SaveEdgesPeriodicity(save);
2329   SaveVerticesPeriodicity(save);
2330
2331   // HYPER-PATCHES
2332   save << " " << _hyperPatchList.size() << " ";
2333   for ( size_t i = 0; i < _hyperPatchList.size(); ++i )
2334   {
2335     THyperPatchTags& patch = _hyperPatchList[i];
2336     save << patch.size() << " ";
2337     THyperPatchTags::iterator tag = patch.begin();
2338     for ( ; tag != patch.end(); ++tag )
2339       save << *tag << " ";
2340   }
2341
2342   // New options in 2.9.6 (issue #17784)
2343   save << " " << _useSurfaceProximity;
2344   save << " " << _nbSurfaceProximityLayers;
2345   save << " " << _surfaceProximityRatio;
2346   save << " " << _useVolumeProximity;
2347   save << " " << _nbVolumeProximityLayers;
2348   save << " " << _volumeProximityRatio;
2349
2350   // hyper-patches as entries
2351   std::ostringstream hpStream;
2352   boost::archive::text_oarchive( hpStream ) << _hyperPatchEntriesList;
2353   std::string hpString = hpStream.str();
2354   SMESHDS_Hypothesis::SaveStringToStream( save, hpString );
2355
2356   // Enforced meshes
2357   std::ostringstream enfMStream;
2358   boost::archive::text_oarchive( enfMStream ) << _enforcedMeshes;
2359   std::string enfMString = enfMStream.str();
2360   SMESHDS_Hypothesis::SaveStringToStream( save, enfMString );
2361
2362   return save;
2363 }
2364
2365 void BLSURFPlugin_Hypothesis::SaveFacesPeriodicity(std::ostream & save)
2366 {
2367   TFacesPeriodicityVector::const_iterator it_faces_periodicity = _facesPeriodicityVector.begin();
2368   if (it_faces_periodicity != _facesPeriodicityVector.end()) {
2369     save << " " << "__FACES_PERIODICITY_BEGIN__";
2370     for (; it_faces_periodicity != _facesPeriodicityVector.end(); ++it_faces_periodicity) {
2371       TFacesPeriodicity periodicity_i = (*it_faces_periodicity);
2372       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2373       save << " " << "__BEGIN_ENTRY1__";
2374       save << " " << periodicity_i.first;
2375       save << " " << "__END_ENTRY1__";
2376       save << " " << "__BEGIN_ENTRY2__";
2377       save << " " << periodicity_i.second;
2378       save << " " << "__END_ENTRY2__";
2379       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2380     }
2381     save << " " << "__FACES_PERIODICITY_END__";
2382   }
2383 }
2384
2385 void BLSURFPlugin_Hypothesis::SaveEdgesPeriodicity(std::ostream & save)
2386 {
2387   TEdgesPeriodicityVector::const_iterator it_edges_periodicity = _edgesPeriodicityVector.begin();
2388   if (it_edges_periodicity != _edgesPeriodicityVector.end()) {
2389     save << " " << "__EDGES_PERIODICITY_BEGIN__";
2390     for (; it_edges_periodicity != _edgesPeriodicityVector.end(); ++it_edges_periodicity) {
2391       TEdgePeriodicity periodicity_i = (*it_edges_periodicity);
2392       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2393       if (! periodicity_i.theFace1Entry.empty()){
2394         save << " " << "__BEGIN_FACE1__";
2395         save << " " << periodicity_i.theFace1Entry;
2396         save << " " << "__END_FACE1__";
2397       }
2398       save << " " << "__BEGIN_EDGE1__";
2399       save << " " << periodicity_i.theEdge1Entry;
2400       save << " " << "__END_EDGE1__";
2401       if (! periodicity_i.theFace2Entry.empty()){
2402         save << " " << "__BEGIN_FACE2__";
2403         save << " " << periodicity_i.theFace2Entry;
2404         save << " " << "__END_FACE2__";
2405       }
2406       save << " " << "__BEGIN_EDGE2__";
2407       save << " " << periodicity_i.theEdge2Entry;
2408       save << " " << "__END_EDGE2__";
2409       save << " " << "__BEGIN_EDGE_ORIENTATION__";
2410       save << " " << periodicity_i.edge_orientation;
2411       save << " " << "__END_EDGE_ORIENTATION__";
2412       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2413     }
2414     save << " " << "__EDGES_PERIODICITY_END__";
2415   }
2416 }
2417
2418 void BLSURFPlugin_Hypothesis::SaveVerticesPeriodicity(std::ostream & save)
2419 {
2420   TVerticesPeriodicityVector::const_iterator it_vertices_periodicity = _verticesPeriodicityVector.begin();
2421   if (it_vertices_periodicity != _verticesPeriodicityVector.end()) {
2422     save << " " << "__VERTICES_PERIODICITY_BEGIN__";
2423     for (; it_vertices_periodicity != _verticesPeriodicityVector.end(); ++it_vertices_periodicity) {
2424       TVertexPeriodicity periodicity_i = (*it_vertices_periodicity);
2425       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2426       save << " " << "__BEGIN_EDGE1__";
2427       save << " " << periodicity_i.theEdge1Entry;
2428       save << " " << "__END_EDGE1__";
2429       save << " " << "__BEGIN_VERTEX1__";
2430       save << " " << periodicity_i.theVertex1Entry;
2431       save << " " << "__END_VERTEX1__";
2432       save << " " << "__BEGIN_EDGE2__";
2433       save << " " << periodicity_i.theEdge2Entry;
2434       save << " " << "__END_EDGE2__";
2435       save << " " << "__BEGIN_VERTEX2__";
2436       save << " " << periodicity_i.theVertex2Entry;
2437       save << " " << "__END_VERTEX2__";
2438       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2439     }
2440     save << " " << "__VERTICES_PERIODICITY_END__";
2441   }
2442 }
2443
2444 void BLSURFPlugin_Hypothesis::SavePreCADPeriodicity(std::ostream & save, const char* shapeType)
2445 {
2446   TPreCadPeriodicityVector precad_periodicity;
2447   if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
2448     precad_periodicity = _preCadFacesPeriodicityVector;
2449   else
2450     precad_periodicity = _preCadEdgesPeriodicityVector;
2451   TPreCadPeriodicityVector::const_iterator it_precad_periodicity = precad_periodicity.begin();
2452   if (it_precad_periodicity != precad_periodicity.end()) {
2453     save << " " << "__PRECAD_" << shapeType << "_PERIODICITY_BEGIN__";
2454     for (; it_precad_periodicity != precad_periodicity.end(); ++it_precad_periodicity) {
2455       TPreCadPeriodicity periodicity_i = (*it_precad_periodicity);
2456       save << " " << "__BEGIN_PERIODICITY_DESCRIPTION__";
2457       if (!periodicity_i.shape1Entry.empty()) {
2458         save << " " << "__BEGIN_ENTRY1__";
2459         save << " " << periodicity_i.shape1Entry;
2460         save << " " << "__END_ENTRY1__";
2461       }
2462       if (!periodicity_i.shape2Entry.empty()) {
2463         save << " " << "__BEGIN_ENTRY2__";
2464         save << " " << periodicity_i.shape2Entry;
2465         save << " " << "__END_ENTRY2__";
2466       }
2467
2468       std::vector<std::string>::const_iterator sourceVerticesEntriesIt = periodicity_i.theSourceVerticesEntries.begin();
2469       bool hasSourceVertices = false;
2470       if (sourceVerticesEntriesIt != periodicity_i.theSourceVerticesEntries.end()) {
2471         hasSourceVertices = true;
2472         save << " " << "__BEGIN_SOURCE_VERTICES_LIST__";
2473       }
2474       for (; sourceVerticesEntriesIt != periodicity_i.theSourceVerticesEntries.end(); ++sourceVerticesEntriesIt)
2475         save << " " << (*sourceVerticesEntriesIt);
2476       if (hasSourceVertices)
2477         save << " " << "__END_SOURCE_VERTICES_LIST__";
2478
2479       std::vector<std::string>::const_iterator targetVerticesEntriesIt = periodicity_i.theTargetVerticesEntries.begin();
2480       bool hasTargetVertices = false;
2481       if (targetVerticesEntriesIt != periodicity_i.theTargetVerticesEntries.end()) {
2482         hasTargetVertices = true;
2483         save << " " << "__BEGIN_TARGET_VERTICES_LIST__";
2484       }
2485       for (; targetVerticesEntriesIt != periodicity_i.theTargetVerticesEntries.end(); ++targetVerticesEntriesIt)
2486         save << " " << (*targetVerticesEntriesIt);
2487       if (hasTargetVertices)
2488         save << " " << "__END_TARGET_VERTICES_LIST__";
2489
2490       save << " " << "__END_PERIODICITY_DESCRIPTION__";
2491     }
2492     save << " " << "__PRECAD_" << shapeType << "_PERIODICITY_END__";
2493   }
2494
2495 }
2496
2497 //=============================================================================
2498 std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load)
2499 {
2500   bool isOK = true;
2501   int i;
2502   double val;
2503   std::string option_or_sm;
2504
2505   isOK = static_cast<bool>(load >> i);
2506   if (isOK)
2507     _topology = (Topology) i;
2508   else
2509     load.clear(std::ios::badbit | load.rdstate());
2510
2511   isOK = static_cast<bool>(load >> i);
2512   if (isOK)
2513     _physicalMesh = (PhysicalMesh) i;
2514   else
2515     load.clear(std::ios::badbit | load.rdstate());
2516
2517   isOK = static_cast<bool>(load >> i);
2518   if (isOK)
2519     _geometricMesh = (GeometricMesh) i;
2520   else
2521     load.clear(std::ios::badbit | load.rdstate());
2522
2523   isOK = static_cast<bool>(load >> val);
2524   if (isOK)
2525     _phySize = val;
2526   else
2527     load.clear(std::ios::badbit | load.rdstate());
2528
2529   isOK = static_cast<bool>(load >> val);
2530   if (isOK)
2531     _angleMesh = val;
2532   else
2533     load.clear(std::ios::badbit | load.rdstate());
2534
2535   isOK = static_cast<bool>(load >> val);
2536   if (isOK)
2537     _gradation = val;
2538   else
2539     load.clear(std::ios::badbit | load.rdstate());
2540
2541   isOK = static_cast<bool>(load >> i);
2542   if (isOK)
2543     _elementType = (ElementType) i;
2544   else
2545     load.clear(std::ios::badbit | load.rdstate());
2546
2547   isOK = static_cast<bool>(load >> i);
2548   if (isOK) {
2549     if ( i != -1) { // if value is -1, then this is no longer a standard option
2550       std::string & value = _option2value["respect_geometry"];
2551       bool _decimesh = (bool) i;
2552       value = _decimesh ? "1" : "0";
2553     }
2554   }
2555   else
2556     load.clear(std::ios::badbit | load.rdstate());
2557
2558   isOK = static_cast<bool>(load >> val);
2559   if (isOK)
2560     _minSize = val;
2561   else
2562     load.clear(std::ios::badbit | load.rdstate());
2563
2564   isOK = static_cast<bool>(load >> val);
2565   if (isOK)
2566     _maxSize = val;
2567   else
2568     load.clear(std::ios::badbit | load.rdstate());
2569
2570   isOK = static_cast<bool>(load >> val);
2571   if (isOK)
2572     // former parameter: get min value
2573     _angleMesh = std::min(val,_angleMesh);
2574   else
2575     load.clear(std::ios::badbit | load.rdstate());
2576
2577   isOK = static_cast<bool>(load >> val);
2578   if (isOK)
2579     // former parameter: get min value
2580     _minSize = std::min(val,_minSize);
2581   else
2582     load.clear(std::ios::badbit | load.rdstate());
2583
2584   isOK = static_cast<bool>(load >> val);
2585   if (isOK)
2586     // former parameter: get max value
2587     _maxSize = std::max(val,_maxSize);
2588   else
2589     load.clear(std::ios::badbit | load.rdstate());
2590
2591   isOK = static_cast<bool>(load >> i);
2592   if (isOK)
2593     _verb = i;
2594   else
2595     load.clear(std::ios::badbit | load.rdstate());
2596
2597   isOK = static_cast<bool>(load >> i);
2598   if (isOK)
2599     _preCADMergeEdges = (bool) i;
2600   else
2601     load.clear(std::ios::badbit | load.rdstate());
2602
2603   isOK = static_cast<bool>(load >> i);
2604   if (isOK) {
2605     if ( i != -1) { // if value is -1, then this is no longer a standard option
2606       std::string & value = _preCADoption2value["remove_tiny_edges"];
2607       bool _preCADRemoveNanoEdges = (bool) i;
2608       value = _preCADRemoveNanoEdges ? "1" : "0";
2609     }
2610   }
2611   else
2612     load.clear(std::ios::badbit | load.rdstate());
2613
2614   isOK = static_cast<bool>(load >> i);
2615   if (isOK)
2616     _preCADDiscardInput = (bool) i;
2617   else
2618     load.clear(std::ios::badbit | load.rdstate());
2619
2620   isOK = static_cast<bool>(load >> val);
2621   if (isOK) { // _preCADEpsNano
2622     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
2623       std::string & value = _preCADoption2value["tiny_edge_length"];
2624       std::ostringstream oss;
2625       oss << i;
2626       value = oss.str();
2627     }
2628   }
2629   else
2630     load.clear(std::ios::badbit | load.rdstate());
2631
2632   isOK = static_cast<bool>(load >> i);
2633   if (isOK)
2634     _enforcedInternalVerticesAllFaces = (bool) i;
2635   else
2636     load.clear(std::ios::badbit | load.rdstate());
2637
2638   // New options with MeshGems-CADSurf
2639
2640   bool hasCADSurfOptions = false;
2641   bool hasOptions = false;
2642   bool hasCustomOptions = false;
2643   bool hasPreCADOptions = false;
2644   bool hasSizeMap = false;
2645   bool hasAttractor = false;
2646   bool hasNewAttractor = false;
2647   bool hasEnforcedVertex = false;
2648   bool hasPreCADFacesPeriodicity = false;
2649   bool hasPreCADEdgesPeriodicity = false;
2650   bool hasFacesPeriodicity = false;
2651   bool hasEdgesPeriodicity = false;
2652   bool hasVerticesPeriodicity = false;
2653
2654   isOK = static_cast<bool>(load >> option_or_sm);
2655   if (isOK) {
2656     if (( option_or_sm == "1" ) || ( option_or_sm == "0" )) {
2657       i = atoi(option_or_sm.c_str());
2658       hasCADSurfOptions = true;
2659       _phySizeRel = (bool) i;
2660     }
2661     else if (option_or_sm == "__OPTIONS_BEGIN__")
2662       hasOptions = true;
2663     else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
2664       hasCustomOptions = true;
2665     else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2666       hasPreCADOptions = true;
2667     else if (option_or_sm == "__SIZEMAP_BEGIN__")
2668       hasSizeMap = true;
2669     else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2670       hasAttractor = true;
2671     else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2672       hasNewAttractor = true;
2673     else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2674       hasEnforcedVertex = true;
2675     else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2676       hasPreCADFacesPeriodicity = true;
2677     else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2678       hasPreCADEdgesPeriodicity = true;
2679     else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2680       hasFacesPeriodicity = true;
2681     else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2682       hasEdgesPeriodicity = true;
2683     else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2684       hasVerticesPeriodicity = true;
2685   }
2686
2687   if (isOK && hasCADSurfOptions) {
2688     isOK = static_cast<bool>(load >> i);
2689     if (isOK)
2690       _minSizeRel = (bool) i;
2691     else
2692       load.clear(std::ios::badbit | load.rdstate());
2693
2694     isOK = static_cast<bool>(load >> i);
2695     if (isOK)
2696       _maxSizeRel = (bool) i;
2697     else
2698       load.clear(std::ios::badbit | load.rdstate());
2699
2700     isOK = static_cast<bool>(load >> val);
2701     if (isOK)
2702       _chordalError = val;
2703     else
2704       load.clear(std::ios::badbit | load.rdstate());
2705
2706     isOK = static_cast<bool>(load >> i);
2707     if (isOK)
2708       _anisotropic = (bool) i;
2709     else
2710       load.clear(std::ios::badbit | load.rdstate());
2711
2712     isOK = static_cast<bool>(load >> val);
2713     if (isOK)
2714       _anisotropicRatio = val;
2715     else
2716       load.clear(std::ios::badbit | load.rdstate());
2717
2718     isOK = static_cast<bool>(load >> i);
2719     if (isOK)
2720       _removeTinyEdges = (bool) i;
2721     else
2722       load.clear(std::ios::badbit | load.rdstate());
2723
2724     isOK = static_cast<bool>(load >> val);
2725     if (isOK)
2726       _tinyEdgeLength = val;
2727     else
2728       load.clear(std::ios::badbit | load.rdstate());
2729
2730     isOK = static_cast<bool>(load >> i);
2731     if (isOK)
2732       _badElementRemoval = (bool) i;
2733     else
2734       load.clear(std::ios::badbit | load.rdstate());
2735
2736     isOK = static_cast<bool>(load >> val);
2737     if (isOK)
2738       _badElementAspectRatio = val;
2739     else
2740       load.clear(std::ios::badbit | load.rdstate());
2741
2742     isOK = static_cast<bool>(load >> i);
2743     if (isOK)
2744       _optimizeMesh = (bool) i;
2745     else
2746       load.clear(std::ios::badbit | load.rdstate());
2747
2748     isOK = static_cast<bool>(load >> i);
2749     if (isOK)
2750       _quadraticMesh = (bool) i;
2751     else
2752       load.clear(std::ios::badbit | load.rdstate());
2753
2754     isOK = static_cast<bool>(load >> i);
2755     if (isOK)
2756       _preCADProcess3DTopology = (bool) i;
2757     else
2758       load.clear(std::ios::badbit | load.rdstate());
2759
2760     if (( load >> std::ws).peek() != '_' )
2761     {
2762       isOK = static_cast<bool>(load >> i);
2763       if (isOK)
2764         _preCADRemoveDuplicateCADFaces = (bool) i;
2765       else
2766         load.clear(std::ios::badbit | load.rdstate());
2767
2768       isOK = static_cast<bool>(load >> i);
2769       if (isOK)
2770         _optimiseTinyEdges = (bool) i;
2771       else
2772         load.clear(std::ios::badbit | load.rdstate());
2773
2774       isOK = static_cast<bool>(load >> val);
2775       if (isOK)
2776         _tinyEdgeOptimisationLength = val;
2777       else
2778         load.clear(std::ios::badbit | load.rdstate());
2779
2780       isOK = static_cast<bool>(load >> i);
2781       if (isOK)
2782         _correctSurfaceIntersec = (bool) i;
2783       else
2784         load.clear(std::ios::badbit | load.rdstate());
2785
2786       isOK = static_cast<bool>(load >> val);
2787       if (isOK)
2788         _corrSurfaceIntersCost = val;
2789       else
2790         load.clear(std::ios::badbit | load.rdstate());
2791
2792       isOK = static_cast<bool>(load >> i);
2793       if (isOK)
2794         _useGradation = (bool) i;
2795       else
2796         load.clear(std::ios::badbit | load.rdstate());
2797
2798       isOK = static_cast<bool>(load >> i);
2799       if (isOK)
2800         _useVolumeGradation = (bool) i;
2801       else
2802         load.clear(std::ios::badbit | load.rdstate());
2803
2804       isOK = static_cast<bool>(load >> val);
2805       if (isOK)
2806         _volumeGradation = val;
2807       else
2808         load.clear(std::ios::badbit | load.rdstate());
2809     }
2810   }
2811
2812
2813   if (hasCADSurfOptions) {
2814     isOK = static_cast<bool>(load >> option_or_sm);
2815     if (isOK) {
2816       if (option_or_sm == "__OPTIONS_BEGIN__")
2817         hasOptions = true;
2818       else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
2819         hasCustomOptions = true;
2820       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2821         hasPreCADOptions = true;
2822       else if (option_or_sm == "__SIZEMAP_BEGIN__")
2823         hasSizeMap = true;
2824       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2825         hasAttractor = true;
2826       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2827         hasNewAttractor = true;
2828       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2829         hasEnforcedVertex = true;
2830       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2831         hasPreCADFacesPeriodicity = true;
2832       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2833         hasPreCADEdgesPeriodicity = true;
2834       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2835         hasFacesPeriodicity = true;
2836       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2837         hasEdgesPeriodicity = true;
2838       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2839         hasVerticesPeriodicity = true;
2840     }
2841   }
2842   
2843   std::string optName, optValue;
2844   while (isOK && hasOptions) {
2845     isOK = static_cast<bool>(load >> optName);
2846     if (isOK) {
2847       if (optName == "__OPTIONS_END__")
2848         break;
2849       isOK = static_cast<bool>(load >> optValue);
2850     }
2851     // read the value of the advanced option
2852     // unless this option is no more used
2853     if (isOK
2854 #if MESHGEMS_VERSION_HEX >= 0x020A00
2855         && optName != "enforce_cad_edge_sizes" && optName != "max_number_of_points_per_patch"
2856 #endif
2857         ) {
2858       std::string & value = _option2value[optName];
2859       value = optValue;
2860       int len = (int) value.size();
2861       // continue reading until "%#" encountered
2862       while (value[len - 1] != '#' || value[len - 2] != '%') {
2863         isOK = static_cast<bool>(load >> optValue);
2864         if (isOK) {
2865           value += " ";
2866           value += optValue;
2867           len = (int) value.size();
2868         } else {
2869           break;
2870         }
2871       }
2872       if ( value[ len - 1] == '#' )
2873         value.resize(len - 2); //cut off "%#"
2874     }
2875   }
2876
2877   if (hasOptions) {
2878     isOK = static_cast<bool>(load >> option_or_sm);
2879     if (isOK) {
2880       if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
2881         hasCustomOptions = true;
2882       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2883         hasPreCADOptions = true;
2884       else if (option_or_sm == "__SIZEMAP_BEGIN__")
2885         hasSizeMap = true;
2886       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2887         hasAttractor = true;
2888       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2889         hasNewAttractor = true;
2890       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2891         hasEnforcedVertex = true;
2892       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2893         hasPreCADFacesPeriodicity = true;
2894       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2895         hasPreCADEdgesPeriodicity = true;
2896       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2897         hasFacesPeriodicity = true;
2898       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2899         hasEdgesPeriodicity = true;
2900       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2901         hasVerticesPeriodicity = true;
2902     }
2903   }
2904
2905   while (isOK && hasCustomOptions) {
2906     isOK = static_cast<bool>(load >> optName);
2907     if (isOK) {
2908       if (optName == "__CUSTOM_OPTIONS_END__")
2909         break;
2910       isOK = static_cast<bool>(load >> optValue);
2911     }
2912     if (isOK) {
2913       std::string& value = optValue;
2914       int len = (int) value.size();
2915       // continue reading until "%#" encountered
2916       while (value[len - 1] != '#' || value[len - 2] != '%') {
2917         isOK = static_cast<bool>(load >> optValue);
2918         if (isOK) {
2919           value += " ";
2920           value += optValue;
2921           len = (int) value.size();
2922         } else {
2923           break;
2924         }
2925       }
2926       if ( value[ len - 1] == '#' )
2927         value.resize(len - 2); //cut off "%#"
2928       _customOption2value[optName] = value;
2929     }
2930   }
2931
2932   if (hasCustomOptions) {
2933     isOK = static_cast<bool>(load >> option_or_sm);
2934     if (isOK) {
2935       if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
2936         hasPreCADOptions = true;
2937       else if (option_or_sm == "__SIZEMAP_BEGIN__")
2938         hasSizeMap = true;
2939       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2940         hasAttractor = true;
2941       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2942         hasNewAttractor = true;
2943       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2944         hasEnforcedVertex = true;
2945       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2946         hasPreCADFacesPeriodicity = true;
2947       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2948         hasPreCADEdgesPeriodicity = true;
2949       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
2950         hasFacesPeriodicity = true;
2951       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
2952         hasEdgesPeriodicity = true;
2953       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
2954         hasVerticesPeriodicity = true;
2955     }
2956   }
2957
2958   while (isOK && hasPreCADOptions) {
2959     isOK = static_cast<bool>(load >> optName);
2960     if (isOK) {
2961       if (optName == "__PRECAD_OPTIONS_END__")
2962         break;
2963       isOK = static_cast<bool>(load >> optValue);
2964     }
2965     if (isOK) {
2966       std::string & value = _preCADoption2value[optName];
2967       value = optValue;
2968       int len = (int) value.size();
2969       // continue reading until "%#" encountered
2970       while (value[len - 1] != '#' || value[len - 2] != '%') {
2971         isOK = static_cast<bool>(load >> optValue);
2972         if (isOK) {
2973           value += " ";
2974           value += optValue;
2975           len = (int) value.size();
2976         } else {
2977           break;
2978         }
2979       }
2980       if ( value[ len - 1] == '#' )
2981         value.resize(len - 2); //cut off "%#"
2982     }
2983   }
2984
2985   if (hasPreCADOptions) {
2986     isOK = static_cast<bool>(load >> option_or_sm);
2987     if (isOK) {
2988       if (option_or_sm == "__SIZEMAP_BEGIN__")
2989         hasSizeMap = true;
2990       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
2991         hasAttractor = true;
2992       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
2993         hasNewAttractor = true;
2994       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
2995         hasEnforcedVertex = true;
2996       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
2997         hasPreCADFacesPeriodicity = true;
2998       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
2999         hasPreCADEdgesPeriodicity = true;
3000       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3001         hasFacesPeriodicity = true;
3002       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3003         hasEdgesPeriodicity = true;
3004       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3005         hasVerticesPeriodicity = true;
3006     }
3007   }
3008  
3009   std::string smEntry, smValue;
3010   while (isOK && hasSizeMap) {
3011     isOK = static_cast<bool>(load >> smEntry);
3012     if (isOK) {
3013       if (smEntry == "__SIZEMAP_END__")
3014         break;
3015       isOK = static_cast<bool>(load >> smValue);
3016     }
3017     if (isOK) {
3018       std::string & value2 = _sizeMap[smEntry];
3019       value2 = smValue;
3020       int len2 = (int) value2.size();
3021       // continue reading until "%#" encountered
3022       while (value2[len2 - 1] != '#' || value2[len2 - 2] != '%') {
3023         isOK = static_cast<bool>(load >> smValue);
3024         if (isOK) {
3025           value2 += " ";
3026           value2 += smValue;
3027           len2 = (int) value2.size();
3028         } else {
3029           break;
3030         }
3031       }
3032       value2.resize(len2 - 2); //cut off "%#"
3033     }
3034   }
3035
3036   if (hasSizeMap) {
3037     isOK = static_cast<bool>(load >> option_or_sm);
3038     if (isOK) {
3039       if (option_or_sm == "__ATTRACTORS_BEGIN__")
3040         hasAttractor = true;
3041       else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
3042         hasNewAttractor = true;
3043       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
3044         hasEnforcedVertex = true;
3045       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3046         hasPreCADFacesPeriodicity = true;
3047       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3048         hasPreCADEdgesPeriodicity = true;
3049       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3050         hasFacesPeriodicity = true;
3051       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3052         hasEdgesPeriodicity = true;
3053       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3054         hasVerticesPeriodicity = true;
3055     }
3056   }
3057
3058   std::string atEntry, atValue;
3059   while (isOK && hasAttractor) {
3060     isOK = static_cast<bool>(load >> atEntry);
3061     if (isOK) {
3062       if (atEntry == "__ATTRACTORS_END__")
3063         break;
3064       isOK = static_cast<bool>(load >> atValue);
3065     }
3066     if (isOK) {
3067       std::string & value3 = _attractors[atEntry];
3068       value3 = atValue;
3069       int len3 = (int) value3.size();
3070       // continue reading until "%#" encountered
3071       while (value3[len3 - 1] != '#' || value3[len3 - 2] != '%') {
3072         isOK = static_cast<bool>(load >> atValue);
3073         if (isOK) {
3074           value3 += " ";
3075           value3 += atValue;
3076           len3 = (int) value3.size();
3077         } else {
3078           break;
3079         }
3080       }
3081       value3.resize(len3 - 2); //cut off "%#"
3082     }
3083   }
3084
3085   if (hasAttractor) {
3086     isOK = static_cast<bool>(load >> option_or_sm);
3087     if (isOK) {
3088       if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
3089         hasNewAttractor = true;
3090       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
3091         hasEnforcedVertex = true;
3092       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3093         hasPreCADFacesPeriodicity = true;
3094       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3095         hasPreCADEdgesPeriodicity = true;
3096       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3097         hasFacesPeriodicity = true;
3098       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3099         hasEdgesPeriodicity = true;
3100       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3101         hasVerticesPeriodicity = true;
3102     }
3103   }
3104
3105   std::string newAtFaceEntry, atTestString;
3106   std::string newAtShapeEntry;
3107   double attParams[4];
3108   //double step;
3109   while (isOK && hasNewAttractor) {
3110     //std::cout<<"Load new attractor"<<std::endl;
3111     isOK = static_cast<bool>(load >> newAtFaceEntry);
3112     if (isOK) {
3113       if (newAtFaceEntry == "__NEW_ATTRACTORS_END__")
3114         break;
3115       isOK = static_cast<bool>(load >> newAtShapeEntry);
3116       if (!isOK)
3117         break;
3118       isOK = static_cast<bool>(load >> attParams[0]>>attParams[1]>>attParams[2]>>attParams[3]); //>>step);
3119     }
3120     if (isOK) {
3121       const TopoDS_Shape attractorShape = BLSURFPlugin_Hypothesis::entryToShape(newAtShapeEntry);
3122       const TopoDS_Face faceShape = TopoDS::Face(BLSURFPlugin_Hypothesis::entryToShape(newAtFaceEntry));
3123       BLSURFPlugin_Attractor* attractor = new BLSURFPlugin_Attractor(faceShape, attractorShape, newAtShapeEntry);//, step);
3124       attractor->SetParameters(attParams[0], attParams[1], attParams[2], attParams[3]);
3125       //attractor->BuildMap();                     
3126       _classAttractors.insert( make_pair( newAtFaceEntry, attractor ));
3127     }
3128   }
3129   
3130   
3131   if (hasNewAttractor) {
3132     isOK = static_cast<bool>(load >> option_or_sm);
3133     if (isOK) {
3134       if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
3135         hasEnforcedVertex = true;
3136       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3137         hasPreCADFacesPeriodicity = true;
3138       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3139         hasPreCADEdgesPeriodicity = true;
3140       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3141         hasFacesPeriodicity = true;
3142       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3143         hasEdgesPeriodicity = true;
3144       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3145         hasVerticesPeriodicity = true;
3146     }
3147   }
3148
3149
3150 // 
3151 // Here is a example of the saved stream:
3152 // __ENFORCED_VERTICES_BEGIN__ 
3153 // __BEGIN_VERTEX__  => no name, no entry
3154 // __BEGIN_GROUP__ mon groupe __END_GROUP__
3155 // __BEGIN_COORDS__ 10 10 10 __END_COORDS__
3156 // __BEGIN_FACELIST__ 0:1:1:1:1 __END_FACELIST__
3157 // __END_VERTEX__
3158 // __BEGIN_VERTEX__ => no coords
3159 // __BEGIN_NAME__ mes points __END_NAME__
3160 // __BEGIN_ENTRY__ 0:1:1:4 __END_ENTRY__
3161 // __BEGIN_GROUP__ mon groupe __END_GROUP__
3162 // __BEGIN_FACELIST__ 0:1:1:1:3 __END_FACELIST__
3163 // __END_VERTEX__
3164 // __ENFORCED_VERTICES_END__
3165 //
3166
3167   std::string enfSeparator;
3168   std::string enfName;
3169   std::string enfGeomEntry;
3170   std::string enfGroup;
3171   TEntryList enfFaceEntryList;
3172   double enfCoords[3];
3173   bool hasCoords = false;
3174
3175   _faceEntryEnfVertexListMap.clear();
3176   _enfVertexList.clear();
3177   _faceEntryCoordsListMap.clear();
3178   _coordsEnfVertexMap.clear();
3179   _faceEntryEnfVertexEntryListMap.clear();
3180   _enfVertexEntryEnfVertexMap.clear();
3181
3182
3183   while (isOK && hasEnforcedVertex)
3184   {
3185     isOK = static_cast<bool>(load >> enfSeparator); // __BEGIN_VERTEX__
3186     TEnfVertex *enfVertex = new TEnfVertex();
3187     if (enfSeparator == "__ENFORCED_VERTICES_END__")
3188       break; // __ENFORCED_VERTICES_END__
3189     if (enfSeparator != "__BEGIN_VERTEX__")
3190       throw std::exception();
3191
3192     while (isOK) {
3193       isOK = static_cast<bool>(load >> enfSeparator);
3194       if (enfSeparator == "__END_VERTEX__") {
3195
3196         enfVertex->name = enfName;
3197         enfVertex->geomEntry = enfGeomEntry;
3198         enfVertex->grpName = enfGroup;
3199         enfVertex->coords.clear();
3200         if (hasCoords)
3201           enfVertex->coords.assign(enfCoords,enfCoords+3);
3202         enfVertex->faceEntries = enfFaceEntryList;
3203
3204         _enfVertexList.insert(enfVertex);
3205
3206         if (enfVertex->coords.size()) {
3207           _coordsEnfVertexMap[enfVertex->coords] = enfVertex;
3208           for (TEntryList::const_iterator it = enfVertex->faceEntries.begin() ; it != enfVertex->faceEntries.end(); ++it) {
3209             _faceEntryCoordsListMap[(*it)].insert(enfVertex->coords);
3210             _faceEntryEnfVertexListMap[(*it)].insert(enfVertex);
3211           }
3212         }
3213         if (!enfVertex->geomEntry.empty()) {
3214           _enfVertexEntryEnfVertexMap[enfVertex->geomEntry] = enfVertex;
3215           for (TEntryList::const_iterator it = enfVertex->faceEntries.begin() ; it != enfVertex->faceEntries.end(); ++it) {
3216             _faceEntryEnfVertexEntryListMap[(*it)].insert(enfVertex->geomEntry);
3217             _faceEntryEnfVertexListMap[(*it)].insert(enfVertex);
3218           }
3219         }
3220
3221         enfName.clear();
3222         enfGeomEntry.clear();
3223         enfGroup.clear();
3224         enfFaceEntryList.clear();
3225         hasCoords = false;
3226         break; // __END_VERTEX__
3227       }
3228
3229       if (enfSeparator == "__BEGIN_NAME__") {  // __BEGIN_NAME__
3230         while (isOK && (enfSeparator != "__END_NAME__")) {
3231           isOK = static_cast<bool>(load >> enfSeparator);
3232           if (enfSeparator != "__END_NAME__") {
3233             if (!enfName.empty())
3234               enfName += " ";
3235             enfName += enfSeparator;
3236           }
3237         }
3238       }
3239
3240       if (enfSeparator == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
3241         isOK = static_cast<bool>(load >> enfGeomEntry);
3242         isOK = static_cast<bool>(load >> enfSeparator); // __END_ENTRY__
3243         if (enfSeparator != "__END_ENTRY__")
3244           throw std::exception();
3245       }
3246
3247       if (enfSeparator == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
3248         while (isOK && (enfSeparator != "__END_GROUP__")) {
3249           isOK = static_cast<bool>(load >> enfSeparator);
3250           if (enfSeparator != "__END_GROUP__") {
3251             if (!enfGroup.empty())
3252               enfGroup += " ";
3253             enfGroup += enfSeparator;
3254           }
3255         }
3256       }
3257
3258       if (enfSeparator == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
3259         hasCoords = true;
3260         isOK = static_cast<bool>(load >> enfCoords[0] >> enfCoords[1] >> enfCoords[2]);
3261         isOK = static_cast<bool>(load >> enfSeparator); // __END_COORDS__
3262         if (enfSeparator != "__END_COORDS__")
3263           throw std::exception();
3264       }
3265
3266       if (enfSeparator == "__BEGIN_FACELIST__") {  // __BEGIN_FACELIST__
3267         while (isOK && (enfSeparator != "__END_FACELIST__")) {
3268           isOK = static_cast<bool>(load >> enfSeparator);
3269           if (enfSeparator != "__END_FACELIST__") {
3270             enfFaceEntryList.insert(enfSeparator);
3271           }
3272         }
3273       }
3274     }
3275   }
3276
3277   if ( hasEnforcedVertex ) {
3278     isOK = static_cast<bool>(load >> option_or_sm);
3279     if (isOK) {
3280       if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
3281         hasPreCADFacesPeriodicity = true;
3282       else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3283         hasPreCADEdgesPeriodicity = true;
3284       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3285         hasFacesPeriodicity = true;
3286       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3287         hasEdgesPeriodicity = true;
3288       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3289         hasVerticesPeriodicity = true;
3290     }
3291   }
3292
3293   // PERIODICITY
3294
3295   if (hasPreCADFacesPeriodicity)
3296   {
3297     LoadPreCADPeriodicity(load, "FACES");
3298
3299     isOK = static_cast<bool>(load >> option_or_sm);
3300     if (isOK) {
3301       if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
3302         hasPreCADEdgesPeriodicity = true;
3303       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3304         hasFacesPeriodicity = true;
3305       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3306         hasEdgesPeriodicity = true;
3307       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3308         hasVerticesPeriodicity = true;
3309     }
3310   }
3311
3312   if (hasPreCADEdgesPeriodicity)
3313   {
3314     LoadPreCADPeriodicity(load, "EDGES");
3315
3316     isOK = static_cast<bool>(load >> option_or_sm);
3317     if (isOK) {
3318       if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
3319         hasFacesPeriodicity = true;
3320       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3321         hasEdgesPeriodicity = true;
3322       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3323         hasVerticesPeriodicity = true;
3324     }
3325   }
3326
3327   if (hasFacesPeriodicity)
3328   {
3329     LoadFacesPeriodicity(load);
3330
3331     isOK = static_cast<bool>(load >> option_or_sm);
3332     if (isOK) {
3333       if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
3334         hasEdgesPeriodicity = true;
3335       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3336         hasVerticesPeriodicity = true;
3337     }
3338   }
3339
3340   if (hasEdgesPeriodicity)
3341   {
3342     LoadEdgesPeriodicity(load);
3343
3344     isOK = static_cast<bool>(load >> option_or_sm);
3345     if (isOK)
3346       if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
3347         hasVerticesPeriodicity = true;
3348   }
3349
3350   if (hasVerticesPeriodicity)
3351     LoadVerticesPeriodicity(load);
3352
3353   // HYPER-PATCHES
3354   if ( !option_or_sm.empty() && option_or_sm[0] == '_' )
3355     isOK = static_cast<bool>(load >> option_or_sm);
3356   if ( isOK && !option_or_sm.empty() )
3357   {
3358     int nbPatches = atoi( option_or_sm.c_str() );
3359     if ( nbPatches >= 0 )
3360     {
3361       _hyperPatchList.resize( nbPatches );
3362       for ( int iP = 0; iP < nbPatches && isOK; ++iP )
3363       {
3364         isOK = static_cast<bool>(load >> i) && i >= 2;
3365         if ( !isOK ) break;
3366         int nbTags = i;
3367         for ( int iT = 0; iT < nbTags; ++iT )
3368         {
3369           if (( isOK = static_cast<bool>(load >> i)))
3370             _hyperPatchList[ iP ].insert( i );
3371           else
3372             break;
3373         }
3374       }
3375       if ( !isOK ) // remove invalid patches
3376       {
3377         for ( i = nbPatches - 1; i >= 0; i-- )
3378           if ( _hyperPatchList[i].size() < 2 )
3379             _hyperPatchList.resize( i );
3380       }
3381     }
3382   }
3383
3384   // New options in 2.9.6 (issue #17784)
3385   if ( static_cast<bool>( load >> _useSurfaceProximity ))
3386   {
3387     load >> _nbSurfaceProximityLayers;
3388     load >> _surfaceProximityRatio;
3389     load >> _useVolumeProximity;
3390     load >> _nbVolumeProximityLayers;
3391     isOK = static_cast<bool>( load >> _volumeProximityRatio );
3392   }
3393
3394   // hyper-patches as entries (issue bos #20543)
3395   std::string buffer;
3396   if ( SMESHDS_Hypothesis::LoadStringFromStream( load, buffer ))
3397   {
3398     SMESH_TRY;
3399     SMESHUtils::BoostTxtArchive( buffer ) >> _hyperPatchEntriesList;
3400     SMESH_CATCH( SMESH::printErrorInDebugMode );
3401   }
3402
3403   // Enforced meshes (issue bos $16292)
3404   buffer.clear();
3405   if ( SMESHDS_Hypothesis::LoadStringFromStream( load, buffer ))
3406   {
3407     SMESH_TRY;
3408     SMESHUtils::BoostTxtArchive( buffer ) >> _enforcedMeshes;
3409     SMESH_CATCH( SMESH::printErrorInDebugMode );
3410   }
3411
3412   return load;
3413 }
3414
3415 namespace boost {
3416   namespace serialization {
3417
3418     //=======================================================================
3419     //function : serialize
3420     //purpose  : serialize EnforcedMesh
3421     //=======================================================================
3422
3423     template<class Archive>
3424     void serialize(Archive & ar, BLSURFPlugin_Hypothesis::EnforcedMesh & enfM,
3425                    const unsigned int /*version*/)
3426     {
3427       ar & enfM._meshID;
3428       ar & enfM._subID;
3429       ar & enfM._type;
3430       ar & enfM._groupName;
3431     }
3432
3433   } // namespace serialization
3434 } // namespace boost
3435
3436
3437 void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load)
3438 {
3439   bool isOK = true;
3440
3441   std::string periodicitySeparator;
3442   TEntry shape1Entry;
3443   TEntry shape2Entry;
3444
3445   _facesPeriodicityVector.clear();
3446
3447   while (isOK) {
3448     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3449     TFacesPeriodicity *periodicity_i = new TFacesPeriodicity();
3450     if (periodicitySeparator == "__FACES_PERIODICITY_END__")
3451       break; // __FACES_PERIODICITY_END__
3452     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3453       throw std::exception();
3454     }
3455
3456     while (isOK) {
3457       isOK = static_cast<bool>(load >> periodicitySeparator);
3458       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3459
3460         periodicity_i->first = shape1Entry;
3461         periodicity_i->second = shape2Entry;
3462
3463         _facesPeriodicityVector.push_back(*periodicity_i);
3464
3465         break; // __END_PERIODICITY_DESCRIPTION__
3466       }
3467
3468       if (periodicitySeparator == "__BEGIN_ENTRY1__") {  // __BEGIN_ENTRY1__
3469         isOK = static_cast<bool>(load >> shape1Entry);
3470         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
3471         if (periodicitySeparator != "__END_ENTRY1__")
3472           throw std::exception();
3473       }
3474
3475       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
3476         isOK = static_cast<bool>(load >> shape2Entry);
3477         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
3478         if (periodicitySeparator != "__END_ENTRY2__")
3479           throw std::exception();
3480       }
3481     }
3482   }
3483 }
3484
3485
3486 void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load)
3487 {
3488   bool isOK = true;
3489
3490   std::string periodicitySeparator;
3491   TEntry theFace1Entry;
3492   TEntry theEdge1Entry;
3493   TEntry theFace2Entry;
3494   TEntry theEdge2Entry;
3495   int edge_orientation = 0;
3496
3497   _edgesPeriodicityVector.clear();
3498
3499   while (isOK) {
3500     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3501     TEdgePeriodicity *periodicity_i = new TEdgePeriodicity();
3502     if (periodicitySeparator == "__EDGES_PERIODICITY_END__")
3503       break; // __EDGES_PERIODICITY_END__
3504     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3505       throw std::exception();
3506     }
3507
3508     while (isOK) {
3509       isOK = static_cast<bool>(load >> periodicitySeparator);
3510       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3511
3512         periodicity_i->theFace1Entry = theFace1Entry;
3513         periodicity_i->theEdge1Entry = theEdge1Entry;
3514         periodicity_i->theFace2Entry = theFace2Entry;
3515         periodicity_i->theEdge2Entry = theEdge2Entry;
3516         periodicity_i->edge_orientation = edge_orientation;
3517
3518         _edgesPeriodicityVector.push_back(*periodicity_i);
3519
3520         break; // __END_PERIODICITY_DESCRIPTION__
3521       }
3522
3523       if (periodicitySeparator == "__BEGIN_FACE1__") {  // __BEGIN_FACE1__
3524         isOK = static_cast<bool>(load >> theFace1Entry);
3525         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE1__
3526         if (periodicitySeparator != "__END_FACE1__"){
3527           throw std::exception();
3528         }
3529       }
3530
3531       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
3532         isOK = static_cast<bool>(load >> theEdge1Entry);
3533         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
3534         if (periodicitySeparator != "__END_EDGE1__")
3535           throw std::exception();
3536       }
3537
3538       if (periodicitySeparator == "__BEGIN_FACE2__") {  // __BEGIN_FACE2__
3539         isOK = static_cast<bool>(load >> theFace2Entry);
3540         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE2__
3541         if (periodicitySeparator != "__END_FACE2__")
3542           throw std::exception();
3543       }
3544
3545       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
3546         isOK = static_cast<bool>(load >> theEdge2Entry);
3547         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
3548         if (periodicitySeparator != "__END_EDGE2__")
3549           throw std::exception();
3550       }
3551
3552       if (periodicitySeparator == "__BEGIN_EDGE_ORIENTATION__") {  // __BEGIN_EDGE_ORIENTATION__
3553         isOK = static_cast<bool>(load >> edge_orientation);
3554         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE_ORIENTATION__
3555         if (periodicitySeparator != "__END_EDGE_ORIENTATION__")
3556           throw std::exception();
3557       }
3558     }
3559   }
3560 }
3561
3562 void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load)
3563 {
3564   bool isOK = true;
3565
3566   std::string periodicitySeparator;
3567   TEntry theEdge1Entry;
3568   TEntry theVertex1Entry;
3569   TEntry theEdge2Entry;
3570   TEntry theVertex2Entry;
3571
3572   _verticesPeriodicityVector.clear();
3573
3574   while (isOK) {
3575     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3576     TVertexPeriodicity *periodicity_i = new TVertexPeriodicity();
3577     if (periodicitySeparator == "__VERTICES_PERIODICITY_END__")
3578       break; // __VERTICES_PERIODICITY_END__
3579     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3580       throw std::exception();
3581     }
3582
3583     while (isOK) {
3584       isOK = static_cast<bool>(load >> periodicitySeparator);
3585       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3586
3587         periodicity_i->theEdge1Entry = theEdge1Entry;
3588         periodicity_i->theVertex1Entry = theVertex1Entry;
3589         periodicity_i->theEdge2Entry = theEdge2Entry;
3590         periodicity_i->theVertex2Entry = theVertex2Entry;
3591
3592         _verticesPeriodicityVector.push_back(*periodicity_i);
3593
3594         break; // __END_PERIODICITY_DESCRIPTION__
3595       }
3596
3597       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
3598         isOK = static_cast<bool>(load >> theEdge1Entry);
3599         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
3600         if (periodicitySeparator != "__END_EDGE1__")
3601           throw std::exception();
3602       }
3603
3604       if (periodicitySeparator == "__BEGIN_VERTEX1__") {  // __BEGIN_VERTEX1__
3605         isOK = static_cast<bool>(load >> theVertex1Entry);
3606         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX1__
3607         if (periodicitySeparator != "__END_VERTEX1__")
3608           throw std::exception();
3609       }
3610
3611       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
3612         isOK = static_cast<bool>(load >> theEdge2Entry);
3613         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
3614         if (periodicitySeparator != "__END_EDGE2__")
3615           throw std::exception();
3616       }
3617
3618       if (periodicitySeparator == "__BEGIN_VERTEX2__") {  // __BEGIN_VERTEX2__
3619         isOK = static_cast<bool>(load >> theVertex2Entry);
3620         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX2__
3621         if (periodicitySeparator != "__END_VERTEX2__")
3622           throw std::exception();
3623       }
3624     }
3625   }
3626 }
3627
3628 void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const char* shapeType)
3629 {
3630   bool isOK = true;
3631
3632   std::string periodicitySeparator;
3633   TEntry shape1Entry;
3634   TEntry shape2Entry;
3635   std::vector<std::string> theSourceVerticesEntries;
3636   std::vector<std::string> theTargetVerticesEntries;
3637
3638   bool hasSourceVertices = false;
3639   bool hasTargetVertices = false;
3640
3641   if ( shapeType  &&  strcmp( shapeType, "FACES") == 0 )
3642     _preCadFacesPeriodicityVector.clear();
3643   else
3644     _preCadEdgesPeriodicityVector.clear();
3645
3646
3647   while (isOK) {
3648     isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
3649     TPreCadPeriodicity *periodicity_i = new TPreCadPeriodicity();
3650     std::string endSeparator = "__PRECAD_" + std::string(shapeType) + "_PERIODICITY_END__";
3651     if (periodicitySeparator == endSeparator)
3652       break; // __PRECAD_FACES_PERIODICITY_END__
3653     if (periodicitySeparator != "__BEGIN_PERIODICITY_DESCRIPTION__"){
3654       throw std::exception();
3655     }
3656
3657     while (isOK) {
3658       isOK = static_cast<bool>(load >> periodicitySeparator);
3659       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
3660
3661         periodicity_i->shape1Entry = shape1Entry;
3662         periodicity_i->shape2Entry = shape2Entry;
3663
3664         if (hasSourceVertices)
3665           periodicity_i->theSourceVerticesEntries = theSourceVerticesEntries;
3666         if (hasTargetVertices)
3667           periodicity_i->theTargetVerticesEntries = theTargetVerticesEntries;
3668
3669         if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
3670           _preCadFacesPeriodicityVector.push_back(*periodicity_i);
3671         else
3672           _preCadEdgesPeriodicityVector.push_back(*periodicity_i);
3673
3674         theSourceVerticesEntries.clear();
3675         theTargetVerticesEntries.clear();
3676         hasSourceVertices = false;
3677         hasTargetVertices = false;
3678         break; // __END_PERIODICITY_DESCRIPTION__
3679       }
3680
3681       if (periodicitySeparator == "__BEGIN_ENTRY1__") {  // __BEGIN_ENTRY1__
3682         isOK = static_cast<bool>(load >> shape1Entry);
3683         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
3684         if (periodicitySeparator != "__END_ENTRY1__")
3685           throw std::exception();
3686       }
3687
3688       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
3689         isOK = static_cast<bool>(load >> shape2Entry);
3690         isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
3691         if (periodicitySeparator != "__END_ENTRY2__")
3692           throw std::exception();
3693       }
3694
3695       if (periodicitySeparator == "__BEGIN_SOURCE_VERTICES_LIST__") {  // __BEGIN_SOURCE_VERTICES_LIST__
3696         hasSourceVertices = true;
3697         while (isOK && (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__")) {
3698           isOK = static_cast<bool>(load >> periodicitySeparator);
3699           if (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__") {
3700             theSourceVerticesEntries.push_back(periodicitySeparator);
3701           }
3702         }
3703       }
3704
3705       if (periodicitySeparator == "__BEGIN_TARGET_VERTICES_LIST__") {  // __BEGIN_TARGET_VERTICES_LIST__
3706         hasTargetVertices = true;
3707         while (isOK && (periodicitySeparator != "__END_TARGET_VERTICES_LIST__")) {
3708           isOK = static_cast<bool>(load >> periodicitySeparator);
3709           if (periodicitySeparator != "__END_TARGET_VERTICES_LIST__") {
3710             theTargetVerticesEntries.push_back(periodicitySeparator);
3711           }
3712         }
3713       }
3714     }
3715   }
3716 }
3717
3718 //=============================================================================
3719 std::ostream & operator <<(std::ostream & save, BLSURFPlugin_Hypothesis & hyp) {
3720   return hyp.SaveTo(save);
3721 }
3722
3723 //=============================================================================
3724 std::istream & operator >>(std::istream & load, BLSURFPlugin_Hypothesis & hyp) {
3725   return hyp.LoadFrom(load);
3726 }
3727
3728 //================================================================================
3729 /*!
3730  * \brief Does nothing
3731  */
3732 //================================================================================
3733
3734 bool BLSURFPlugin_Hypothesis::SetParametersByMesh(const SMESH_Mesh* /*theMesh*/, const TopoDS_Shape& /*theShape*/)
3735 {
3736   return false;
3737 }
3738
3739 //================================================================================
3740 /*!
3741  * \brief Returns default global constant physical size given a default value of element length ratio
3742  */
3743 //================================================================================
3744
3745 double BLSURFPlugin_Hypothesis::GetDefaultPhySize(double diagonal, double bbSegmentation)
3746 {
3747   if (bbSegmentation != 0 && diagonal != 0)
3748     return diagonal / bbSegmentation ;
3749   return 10;
3750 }
3751
3752 //================================================================================
3753 /*!
3754  * \brief Returns default min size given a default value of element length ratio
3755  */
3756 //================================================================================
3757
3758 double BLSURFPlugin_Hypothesis::GetDefaultMinSize(double diagonal)
3759 {
3760   if (diagonal != 0)
3761     return diagonal / 1000.0 ;
3762   return undefinedDouble();
3763 }
3764
3765 //================================================================================
3766 /*!
3767  * \brief Returns default max size given a default value of element length ratio
3768  */
3769 //================================================================================
3770
3771 double BLSURFPlugin_Hypothesis::GetDefaultMaxSize(double diagonal)
3772 {
3773   if (diagonal != 0)
3774     return diagonal / 5.0 ;
3775   return undefinedDouble();
3776 }
3777
3778 //================================================================================
3779 /*!
3780  * \brief Returns default chordal error given a default value of element length ratio
3781  */
3782 //================================================================================
3783
3784 double BLSURFPlugin_Hypothesis::GetDefaultChordalError(double diagonal)
3785 {
3786   if (diagonal != 0)
3787     return diagonal;
3788   return undefinedDouble();
3789 }
3790
3791 //================================================================================
3792 /*!
3793  * \brief Returns default tiny edge length given a default value of element length ratio
3794  */
3795 //================================================================================
3796
3797 double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal)
3798 {
3799   if (diagonal != 0)
3800     return diagonal * 1e-6 ;
3801   return undefinedDouble();
3802 }
3803
3804 //================================================================================
3805 /*!
3806  * \brief Returns default tiny edge optimisation length given a default value of element length ratio
3807  */
3808 //================================================================================
3809
3810 double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeOptimisationLength(double diagonal)
3811 {
3812   if (diagonal != 0)
3813     return diagonal * 1e-6 ;
3814   return undefinedDouble();
3815 }
3816
3817 //=============================================================================
3818 /*!
3819  * \brief Initialize my parameter values by default parameters.
3820  *  \retval bool - true if parameter values have been successfully defined
3821  */
3822 //=============================================================================
3823
3824 bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  dflts,
3825                                                       const SMESH_Mesh* /*theMesh*/)
3826 {
3827   _phySize = GetDefaultPhySize(dflts._diagonal, _gen->GetBoundaryBoxSegmentation());
3828   _minSize = GetDefaultMinSize(dflts._diagonal);
3829   _maxSize = GetDefaultMaxSize(dflts._diagonal);
3830   _chordalError = 0.5 * _phySize; //GetDefaultChordalError(diagonal); IMP 0023307
3831
3832   if ( dflts._way == SMESH_Hypothesis::BY_AVERAGE_LENGTH )
3833   {
3834     _phySize      = dflts._elemLength;
3835     _minSize      = dflts._elemLength / 100.;
3836     _maxSize      = dflts._elemLength * 2.;
3837     _chordalError = dflts._elemLength / 2.;
3838     _elementType  = dflts._quadDominated ? QuadrangleDominant : Triangles;
3839     _physicalMesh = PhysicalLocalSize; // to activate _enforcedInternalVerticesAllFaces
3840     _enforcedInternalVerticesAllFaces = true;
3841   }
3842   else
3843   {
3844     _tinyEdgeLength = GetDefaultTinyEdgeLength(dflts._diagonal);
3845     _tinyEdgeOptimisationLength = GetDefaultTinyEdgeOptimisationLength(dflts._diagonal);
3846   }
3847
3848   return true;
3849 }
3850
3851 //================================================================================
3852 /*!
3853  * \brief Converts a string to a bool
3854  */
3855 //================================================================================
3856
3857 bool BLSURFPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
3858 {
3859   std::string s = str;
3860   if ( isOk ) *isOk = true;
3861
3862   for ( size_t i = 0; i <= s.size(); ++i )
3863     s[i] = (char) tolower( s[i] );
3864
3865   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
3866     return true;
3867
3868   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
3869     return false;
3870
3871   if ( isOk )
3872     *isOk = false;
3873   else {
3874     std::string msg = "Not a Boolean value:'" + str + "'";
3875     throw std::invalid_argument(msg);
3876   }
3877   return false;
3878 }
3879
3880 //================================================================================
3881 /*!
3882  * \brief Converts a string to a real value
3883  */
3884 //================================================================================
3885
3886 double BLSURFPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
3887 {
3888   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
3889
3890   // Forces "C" locale to be set as LC_NUMERIC
3891   Kernel_Utils::Localizer loc;
3892
3893   char * endPtr;
3894   double val = strtod(&str[0], &endPtr);
3895   bool ok = (&str[0] != endPtr);
3896
3897   if ( isOk ) *isOk = ok;
3898
3899   if ( !ok )
3900   {
3901     std::string msg = "Not a real value:'" + str + "'";
3902     throw std::invalid_argument(msg);
3903   }
3904   return val;
3905 }
3906
3907 //================================================================================
3908 /*!
3909  * \brief Converts a string to a integer value
3910  */
3911 //================================================================================
3912
3913 int BLSURFPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
3914 {
3915   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
3916
3917   char * endPtr;
3918   int val = (int)strtol( &str[0], &endPtr, 10);
3919   bool ok = (&str[0] != endPtr);
3920
3921   if ( isOk ) *isOk = ok;
3922
3923   if ( !ok )
3924   {
3925     std::string msg = "Not an integer value:'" + str + "'";
3926     throw std::invalid_argument(msg);
3927   }
3928   return val;
3929 }
3930