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