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