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