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