Salome HOME
23338: [CEA 1943] Regression on the quality of the meshes obtained by CADSurf
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_Hypothesis.cxx
index 45600425748366978e922705ff0343831aacbf1d..d7c494fe82affda5bc5019f76a29ac3301dded6d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include CORBA_CLIENT_HEADER(SALOMEDS)
 #include CORBA_CLIENT_HEADER(GEOM_Gen)
 
+namespace
+{
+  struct GET_DEFAULT // struct used to get default value from GetOptionValue()
+  {
+    bool isDefault;
+    operator bool* () { return &isDefault; }
+  };
+}
+
 //=============================================================================
 BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen * gen) :
   SMESH_Hypothesis(hypId, studyId, gen), 
@@ -47,10 +56,13 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   _phySize(GetDefaultPhySize()),
   _phySizeRel(GetDefaultPhySizeRel()),
   _minSize(GetDefaultMinSize()),
-  _minSizeRel(GetDefaultMinSizeRel()),
   _maxSize(GetDefaultMaxSize()),
+  _minSizeRel(GetDefaultMinSizeRel()),
   _maxSizeRel(GetDefaultMaxSizeRel()),
+  _useGradation(GetDefaultUseGradation()),
   _gradation(GetDefaultGradation()),
+  _useVolumeGradation(GetDefaultUseVolumeGradation()),
+  _volumeGradation(GetDefaultVolumeGradation()),
   _quadAllowed(GetDefaultQuadAllowed()),
   _angleMesh(GetDefaultAngleMesh()),
   _chordalError(GetDefaultChordalError()), 
@@ -58,6 +70,10 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   _anisotropicRatio(GetDefaultAnisotropicRatio()),
   _removeTinyEdges(GetDefaultRemoveTinyEdges()),
   _tinyEdgeLength(GetDefaultTinyEdgeLength()),
+  _optimiseTinyEdges(GetDefaultOptimiseTinyEdges()),
+  _tinyEdgeOptimisationLength(GetDefaultTinyEdgeOptimisationLength()),
+  _correctSurfaceIntersec(GetDefaultCorrectSurfaceIntersection()),
+  _corrSurfaceIntersCost(GetDefaultCorrectSurfaceIntersectionMaxCost()),
   _badElementRemoval(GetDefaultBadElementRemoval()),
   _badElementAspectRatio(GetDefaultBadElementAspectRatio()),
   _optimizeMesh(GetDefaultOptimizeMesh()),
@@ -65,6 +81,8 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   _verb(GetDefaultVerbosity()),
   _topology(GetDefaultTopology()),
   _preCADMergeEdges(GetDefaultPreCADMergeEdges()),
+  _preCADRemoveTinyUVEdges(GetDefaultPreCADRemoveTinyUVEdges()),
+  _preCADRemoveDuplicateCADFaces(GetDefaultPreCADRemoveDuplicateCADFaces()),
   _preCADProcess3DTopology(GetDefaultPreCADProcess3DTopology()),
   _preCADDiscardInput(GetDefaultPreCADDiscardInput()),
   _sizeMap(GetDefaultSizeMap()),
@@ -77,57 +95,61 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   _faceEntryEnfVertexEntryListMap(GetDefaultFaceEntryEnfVertexEntryListMap()),
   _enfVertexEntryEnfVertexMap(GetDefaultEnfVertexEntryEnfVertexMap()),
   _groupNameNodeIDMap(GetDefaultGroupNameNodeIDMap()),
-  _GMFFileName(GetDefaultGMFFile()),
   _enforcedInternalVerticesAllFaces(GetDefaultInternalEnforcedVertex()),
   _preCadFacesPeriodicityVector(GetDefaultPreCadFacesPeriodicityVector()),
-  _preCadEdgesPeriodicityVector(GetDefaultPreCadEdgesPeriodicityVector())
+  _preCadEdgesPeriodicityVector(GetDefaultPreCadEdgesPeriodicityVector()),
+  _GMFFileName(GetDefaultGMFFile())
 {
-  _name = "BLSURF_Parameters";
+  _name = GetHypType();
   _param_algo_dim = 2;
   
 //   _GMFFileMode = false; // GMF ascii mode
 
-  const char* boolOptionNames[] = {         "correct_surface_intersections",            // default = 1
-                                            "create_tag_on_collision",                  // default = 1
-                                            "debug",                                    // default = 0
-                                            "enforce_cad_edge_sizes",                   // default = 0
-                                            "frontal",                                  // ok default = 1
+  // Advanced options with their defaults according to MG User Manual
+
+  const char* boolOptionNames[] = {         "enforce_cad_edge_sizes",                   // default = 0
+                                            // "correct_surface_intersections",            // default = 1
+                                            // "create_tag_on_collision",                  // default = 1
                                             "jacobian_rectification_respect_geometry",  // default = 1
-                                            "proximity",                                // default = 0
                                             "rectify_jacobian",                         // default = 1
                                             "respect_geometry",                         // default = 1
+                                            // "optimise_tiny_edges",                      // default = 0
+                                            // "remove_duplicate_cad_faces",               // default = 1
+                                            "tiny_edge_avoid_surface_intersections",    // default = 1
+                                            // "tiny_edge_respect_geometry",               // default = 0
                                             "" // mark of end
       };
 
-  const char* intOptionNames[] = {          "hinterpol_flag",                           // ok default = 0
-                                            "hmean_flag",                               // ok default = 0
-                                            "max_number_of_points_per_patch",           // default = 100000
-                                            "prox_nb_layer",                            // detects the volumic proximity of surfaces
+  const char* intOptionNames[] = {          "max_number_of_points_per_patch",           // default = 100000
                                             "" // mark of end
       };
-  const char* doubleOptionNames[] = {       "surface_intersections_processing_max_cost",// default = 15
-                                            "periodic_tolerance",                       // default = diag/100
-                                            "prox_ratio",
+  const char* doubleOptionNames[] = {       // "surface_intersections_processing_max_cost",// default = 15
+                                            // "periodic_tolerance",                       // default = diag/100
+                                            // "volume_gradation",
+                                            // "tiny_edge_optimisation_length",            // default = diag * 1e-6
                                             "" // mark of end
       };
-  const char* charOptionNames[] = {         "required_entities",                        // default = "respect"
-                                            "tags",                                     // default = "respect"
+  const char* charOptionNames[] = {         // "required_entities",                        // default = "respect"
+                                            // "tags",                                     // default = "respect"
                                             "" // mark of end
       };
 
   // PreCAD advanced options
   const char* preCADboolOptionNames[] = {   "closed_geometry",                          // default = 0
-                                            "create_tag_on_collision",                  // default = 1
+                                            "discard_input_topology",                   // default = 0
+                                            "merge_edges",                              // default =  = 1
+                                            "remove_duplicate_cad_faces",               // default = 1
+                                            // "create_tag_on_collision",                  // default = 1
                                             "debug",                                    // default = 0 
-                                            "remove_tiny_edges",                        // default = 0
+                                            // "remove_tiny_edges",                        // default = 0
                                             "" // mark of end
       };
-  const char* preCADintOptionNames[] = {    "manifold_geometry",                        // default = 0
+  const char* preCADintOptionNames[] = {    // "manifold_geometry",                        // default = 0
                                             "" // mark of end
       };
   const char* preCADdoubleOptionNames[] = { "periodic_tolerance",                       // default = diag * 1e-5
                                             "sewing_tolerance",                         // default = diag * 5e-4
-                                            "tiny_edge_length",                         // default = diag * 1e-5
+                                            // "tiny_edge_length",                         // default = diag * 1e-5
                                             "" // mark of end
       };
   const char* preCADcharOptionNames[] = {   "required_entities",                        // default = "respect"
@@ -137,12 +159,16 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
   
   int i = 0;
   while (boolOptionNames[i][0])
+  {
+    _boolOptions.insert( boolOptionNames[i] );
     _option2value[boolOptionNames[i++]].clear();
-  
+  }
   i = 0;
   while (preCADboolOptionNames[i][0])
+  {
+    _boolOptions.insert( preCADboolOptionNames[i] );
     _preCADoption2value[preCADboolOptionNames[i++]].clear();
-  
+  }
   i = 0;
   while (intOptionNames[i][0])
     _option2value[intOptionNames[i++]].clear();
@@ -171,8 +197,32 @@ BLSURFPlugin_Hypothesis::BLSURFPlugin_Hypothesis(int hypId, int studyId, SMESH_G
     _preCADcharOptions.insert(preCADcharOptionNames[i]);
     _preCADoption2value[preCADcharOptionNames[i++]].clear();
   }
-  
 
+  // default values to be used while MG meshing
+
+  _defaultOptionValues["enforce_cad_edge_sizes"                 ] = "no";
+  _defaultOptionValues["jacobian_rectification_respect_geometry"] = "yes";
+  _defaultOptionValues["max_number_of_points_per_patch"         ] = "0";
+  _defaultOptionValues["rectify_jacobian"                       ] = "yes";
+  _defaultOptionValues["respect_geometry"                       ] = "yes";
+  _defaultOptionValues["tiny_edge_avoid_surface_intersections"  ] = "yes";
+  _defaultOptionValues["closed_geometry"                        ] = "no";
+  _defaultOptionValues["debug"                                  ] = "no";
+  _defaultOptionValues["discard_input_topology"                 ] = "no";
+  _defaultOptionValues["merge_edges"                            ] = "no";
+  _defaultOptionValues["periodic_tolerance"                     ] = "1e-5*D";
+  _defaultOptionValues["remove_duplicate_cad_faces"             ] = "no";
+  _defaultOptionValues["required_entities"                      ] = "respect";
+  _defaultOptionValues["sewing_tolerance"                       ] = "5e-4*D";
+  _defaultOptionValues["tags"                                   ] = "respect";
+
+#ifdef _DEBUG_
+  // check validity of option names of _defaultOptionValues
+  TOptionValues::iterator n2v = _defaultOptionValues.begin();
+  for ( ; n2v != _defaultOptionValues.end(); ++n2v )
+    ASSERT( _option2value.count( n2v->first ) || _preCADoption2value.count( n2v->first ));
+  ASSERT( _option2value.size() + _preCADoption2value.size() == _defaultOptionValues.size() );
+#endif
       
   _sizeMap.clear();
   _attractors.clear();
@@ -264,14 +314,40 @@ void BLSURFPlugin_Hypothesis::SetMaxSize(double theMaxSize, bool isRelative) {
   }
 }
 
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetUseGradation(bool theVal) {
+  if (theVal != _useGradation) {
+    _useGradation = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetGradation(double theVal) {
+  _useGradation = ( theVal > 0 );
   if (theVal != _gradation) {
     _gradation = theVal;
     NotifySubMeshesHypothesisModification();
   }
 }
 
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetUseVolumeGradation(bool theVal) {
+  if (theVal != _useVolumeGradation) {
+    _useVolumeGradation = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetVolumeGradation(double theVal) {
+  _useVolumeGradation = ( theVal > 0 );
+  if (theVal != _volumeGradation) {
+    _volumeGradation = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetQuadAllowed(bool theVal) {
   if (theVal != _quadAllowed) {
@@ -328,6 +404,38 @@ void BLSURFPlugin_Hypothesis::SetTinyEdgeLength(double theVal) {
   }
 }
 
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetOptimiseTinyEdges(bool theVal) {
+  if (theVal != _optimiseTinyEdges) {
+    _optimiseTinyEdges = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetTinyEdgeOptimisationLength(double theVal) {
+  if (theVal != _tinyEdgeOptimisationLength) {
+    _tinyEdgeOptimisationLength = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetCorrectSurfaceIntersection(bool theVal) {
+  if (theVal != _correctSurfaceIntersec) {
+    _correctSurfaceIntersec = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetCorrectSurfaceIntersectionMaxCost(double theVal) {
+  if (theVal != _corrSurfaceIntersCost) {
+    _corrSurfaceIntersCost = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetBadElementRemoval(bool theVal) {
   if (theVal != _badElementRemoval) {
@@ -377,50 +485,302 @@ void BLSURFPlugin_Hypothesis::SetVerbosity(int theVal) {
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetEnforceCadEdgesSize( bool toEnforce )
+{
+  if ( GetEnforceCadEdgesSize() != toEnforce )
+  {
+    SetOptionValue( "enforce_cad_edge_sizes", toEnforce ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetEnforceCadEdgesSize()
+{
+  return ToBool( GetOptionValue( "enforce_cad_edge_sizes" ), GET_DEFAULT() );
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetJacobianRectificationRespectGeometry( bool allowRectification )
+{
+  if ( GetJacobianRectificationRespectGeometry() != allowRectification )
+  {
+    SetOptionValue("jacobian_rectification_respect_geometry", allowRectification ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetJacobianRectificationRespectGeometry()
+{
+  return ToBool( GetOptionValue("jacobian_rectification_respect_geometry", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetJacobianRectification( bool allowRectification )
+{
+  if ( GetJacobianRectification() != allowRectification )
+  {
+    SetOptionValue( "rectify_jacobian", allowRectification ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetJacobianRectification()
+{
+  return ToBool( GetOptionValue("rectify_jacobian", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetMaxNumberOfPointsPerPatch( int nb )
+  throw (std::invalid_argument)
+{
+  if ( nb < 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid number of points: ") << nb );
+
+  if ( GetMaxNumberOfPointsPerPatch() != nb )
+  {
+    SetOptionValue("max_number_of_points_per_patch", SMESH_Comment( nb ));
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+int BLSURFPlugin_Hypothesis::GetMaxNumberOfPointsPerPatch()
+{
+  return ToInt( GetOptionValue("max_number_of_points_per_patch", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetRespectGeometry( bool toRespect )
+{
+  if ( GetRespectGeometry() != toRespect )
+  {
+    SetOptionValue("respect_geometry", toRespect ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetRespectGeometry()
+{
+  return ToBool( GetOptionValue( "respect_geometry", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetTinyEdgesAvoidSurfaceIntersections( bool toAvoidIntersection )
+{
+  if ( GetTinyEdgesAvoidSurfaceIntersections() != toAvoidIntersection )
+  {
+    SetOptionValue("tiny_edge_avoid_surface_intersections", toAvoidIntersection ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetTinyEdgesAvoidSurfaceIntersections()
+{
+  return ToBool( GetOptionValue("tiny_edge_avoid_surface_intersections", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetClosedGeometry( bool isClosed )
+{
+  if ( GetClosedGeometry() != isClosed )
+  {
+    SetPreCADOptionValue("closed_geometry", isClosed ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetClosedGeometry()
+{
+  return ToBool( GetPreCADOptionValue( "closed_geometry", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetDebug( bool isDebug )
+{
+  if ( GetDebug() != isDebug )
+  {
+    SetPreCADOptionValue("debug", isDebug ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+bool BLSURFPlugin_Hypothesis::GetDebug()
+{
+  return ToBool( GetPreCADOptionValue("debug", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetPeriodicTolerance( CORBA::Double tol )
+  throw (std::invalid_argument)
+{
+  if ( tol <= 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid tolerance: ") << tol );
+  if ( GetPeriodicTolerance() != tol )
+  {
+    SetPreCADOptionValue("periodic_tolerance", SMESH_Comment( tol ) );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+double BLSURFPlugin_Hypothesis::GetPeriodicTolerance()
+{
+  return ToDbl( GetPreCADOptionValue( "periodic_tolerance", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetRequiredEntities( const std::string& howToTreat )
+  throw (std::invalid_argument)
+{
+  if ( howToTreat != "respect" && howToTreat != "ignore" && howToTreat != "clear"  )
+    throw std::invalid_argument
+      ( SMESH_Comment("required_entities must be in ['respect','ignore','clear'] "));
+
+  if ( GetRequiredEntities() != howToTreat )
+  {
+    SetPreCADOptionValue("required_entities", howToTreat );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+std::string BLSURFPlugin_Hypothesis::GetRequiredEntities()
+{
+  return GetPreCADOptionValue("required_entities", GET_DEFAULT());
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetSewingTolerance( CORBA::Double tol )
+  throw (std::invalid_argument)
+{
+  if ( tol <= 0 )
+    throw std::invalid_argument( SMESH_Comment("Invalid tolerance: ") << tol );
+  if ( GetSewingTolerance() != tol )
+  {
+    SetPreCADOptionValue("sewing_tolerance", SMESH_Comment( tol ) );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+CORBA::Double BLSURFPlugin_Hypothesis::GetSewingTolerance()
+{
+  return ToDbl( GetPreCADOptionValue("sewing_tolerance", GET_DEFAULT()));
+}
+//=============================================================================
+
+void BLSURFPlugin_Hypothesis::SetTags( const std::string& howToTreat )
+  throw (std::invalid_argument)
+{
+  if ( howToTreat != "respect" && howToTreat != "ignore" && howToTreat != "clear"  )
+    throw std::invalid_argument
+      ( SMESH_Comment("'tags' must be in ['respect','ignore','clear'] "));
+
+  if ( GetTags() != howToTreat )
+  {
+    SetPreCADOptionValue("tags", howToTreat );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+//=============================================================================
+std::string BLSURFPlugin_Hypothesis::GetTags()
+{
+  return GetPreCADOptionValue("tags", GET_DEFAULT());
+}
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetPreCADMergeEdges(bool theVal)
+{
   if (theVal != _preCADMergeEdges) {
 //     SetTopology(PreCAD);
     _preCADMergeEdges = theVal;
+    SetPreCADOptionValue("merge_edges", theVal ? "yes" : "no" );
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal) {
-  if (theVal != _preCADProcess3DTopology) {
+void BLSURFPlugin_Hypothesis::SetPreCADRemoveTinyUVEdges(bool theVal)
+{
+  if (theVal != _preCADRemoveTinyUVEdges) {
 //     SetTopology(PreCAD);
+    _preCADRemoveTinyUVEdges = theVal;
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetPreCADRemoveDuplicateCADFaces(bool theVal)
+{
+  if (theVal != _preCADRemoveDuplicateCADFaces) {
+    //     SetTopology(PreCAD);
+    _preCADRemoveDuplicateCADFaces = theVal;
+    SetPreCADOptionValue("remove_duplicate_cad_faces", theVal ? "yes" : "no" );
+    NotifySubMeshesHypothesisModification();
+  }
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::SetPreCADProcess3DTopology(bool theVal)
+{
+  if (theVal != _preCADProcess3DTopology) {
+    //     SetTopology(PreCAD);
     _preCADProcess3DTopology = theVal;
+    AddPreCADOption("process_3d_topology", theVal ? "yes" : "no" );
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal) {
+void BLSURFPlugin_Hypothesis::SetPreCADDiscardInput(bool theVal)
+{
   if (theVal != _preCADDiscardInput) {
-//     SetTopology(PreCAD);
+    //     SetTopology(PreCAD);
     _preCADDiscardInput = theVal;
+    SetPreCADOptionValue("discard_input_topology", theVal ? "yes" : "no" );
     NotifySubMeshesHypothesisModification();
   }
 }
 
+//=============================================================================
+// Return true if any PreCAD option is activated
+bool BLSURFPlugin_Hypothesis::HasPreCADOptions(const BLSURFPlugin_Hypothesis* hyp)
+{
+  if ( !hyp )
+  {
+    return false;
+  }
+  bool orDefault, isOk;
+  return ( ToBool( hyp->GetPreCADOptionValue("closed_geometry"           , &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("discard_input_topology"    , &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("merge_edges"               , &orDefault )) ||
+           ToBool( hyp->GetPreCADOptionValue("remove_duplicate_cad_faces", &orDefault )) ||
+           ToBool( hyp->GetPreCADOption     ("process_3d_topology")      , &isOk       ) ||
+           ToBool( hyp->GetPreCADOption     ("manifold_geometry")        , &isOk       ) ||
+           hyp->GetPreCADOptionValue("sewing_tolerance") != "5e-4*D"                     ||
+           hyp->GetPreCADProcess3DTopology() );
+}
+
 //=============================================================================
 // void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName, bool isBinary)
 void BLSURFPlugin_Hypothesis::SetGMFFile(const std::string& theFileName)
 {
   _GMFFileName = theFileName;
-//   _GMFFileMode = isBinary;
+  //   _GMFFileMode = isBinary;
   NotifySubMeshesHypothesisModification();
 }
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetOptionValue(const std::string& optionName, const std::string& optionValue)
-    throw (std::invalid_argument) {
+  throw (std::invalid_argument) {
+
   TOptionValues::iterator op_val = _option2value.find(optionName);
-  if (op_val == _option2value.end()) {
-    std::string msg = "Unknown BLSURF option: '" + optionName + "'";
-    throw std::invalid_argument(msg);
+  if (op_val == _option2value.end())
+  {
+    op_val = _preCADoption2value.find(optionName);
+    if (op_val == _preCADoption2value.end())
+    {
+      std::string msg = "Unknown MG-CADSurf option: '" + optionName + "'. Try SetAdvancedOption()";
+      throw std::invalid_argument(msg);
+    }
   }
-  if (op_val->second != optionValue) {
+  if (op_val->second != optionValue)
+  {
     const char* ptr = optionValue.c_str();
     // strip white spaces
     while (ptr[0] == ' ')
@@ -433,39 +793,49 @@ void BLSURFPlugin_Hypothesis::SetOptionValue(const std::string& optionName, cons
     std::string typeName;
     if (i == 0) {
       // empty string
-    } else if (_charOptions.find(optionName) != _charOptions.end()) {
+    } else if (_charOptions.count(optionName)) {
       // do not check strings
-    } else if (_doubleOptions.find(optionName) != _doubleOptions.end()) {
+    } else if (_doubleOptions.count(optionName)) {
       // check if value is double
-      char * endPtr;
-      strtod(ptr, &endPtr);
-      typeOk = (ptr != endPtr);
+      ToDbl(ptr, &typeOk);
       typeName = "real";
+    } else if (_boolOptions.count(optionName)) {
+      // check if value is bool
+      ToBool(ptr, &typeOk);
+      typeName = "bool";
     } else {
       // check if value is int
-      char * endPtr;
-      strtol(ptr, &endPtr, 10);
-      typeOk = (ptr != endPtr);
+      ToInt(ptr, &typeOk);
       typeName = "integer";
     }
     if (!typeOk) {
       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
       throw std::invalid_argument(msg);
     }
-    op_val->second = optionValue;
+    std::string value( ptr, i );
+    if ( _defaultOptionValues[ optionName ] == value )
+      value.clear();
+
+    op_val->second = value;
+
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName, const std::string& optionValue)
-    throw (std::invalid_argument) {
+  throw (std::invalid_argument) {
+
   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
   if (op_val == _preCADoption2value.end()) {
-    std::string msg = "Unknown BLSURF option: '" + optionName + "'";
-    throw std::invalid_argument(msg);
+    op_val = _option2value.find(optionName);
+    if (op_val == _option2value.end()) {
+      std::string msg = "Unknown MG-PreCAD option: '" + optionName + "'. Try SetAdvancedOption()";
+      throw std::invalid_argument(msg);
+    }
   }
-  if (op_val->second != optionValue) {
+  if (op_val->second != optionValue)
+  {
     const char* ptr = optionValue.c_str();
     // strip white spaces
     while (ptr[0] == ' ')
@@ -486,6 +856,10 @@ void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName
       strtod(ptr, &endPtr);
       typeOk = (ptr != endPtr);
       typeName = "real";
+    } else if (_boolOptions.count(optionName)) {
+      // check if value is bool
+      ToBool(ptr, &typeOk);
+      typeName = "bool";
     } else {
       // check if value is int
       char * endPtr;
@@ -497,47 +871,193 @@ void BLSURFPlugin_Hypothesis::SetPreCADOptionValue(const std::string& optionName
       std::string msg = "PreCAD advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
       throw std::invalid_argument(msg);
     }
-    op_val->second = optionValue;
+    std::string value( ptr, i );
+    if ( _defaultOptionValues[ optionName ] == value )
+      value.clear();
+
+    op_val->second = value;
+
     NotifySubMeshesHypothesisModification();
   }
 }
 
 //=============================================================================
-std::string BLSURFPlugin_Hypothesis::GetOptionValue(const std::string& optionName) throw (std::invalid_argument) {
-  TOptionValues::iterator op_val = _option2value.find(optionName);
-  if (op_val == _option2value.end()) {
-    std::string msg = "Unknown BLSURF option: <";
-    msg += optionName + ">";
-    throw std::invalid_argument(msg);
+std::string BLSURFPlugin_Hypothesis::GetOptionValue(const std::string& optionName,
+                                                    bool*              isDefault) const
+  throw (std::invalid_argument)
+{
+  TOptionValues::const_iterator op_val = _option2value.find(optionName);
+  if (op_val == _option2value.end())
+  {
+    op_val = _preCADoption2value.find(optionName);
+    if (op_val == _preCADoption2value.end())
+    {
+      op_val = _customOption2value.find(optionName);
+      if (op_val == _customOption2value.end())
+      {
+        std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
+        throw std::invalid_argument(msg);
+      }
+    }
+  }
+  std::string val = op_val->second;
+  if ( isDefault ) *isDefault = ( val.empty() );
+
+  if ( val.empty() && isDefault )
+  {
+    op_val = _defaultOptionValues.find( optionName );
+    if (op_val != _defaultOptionValues.end())
+      val = op_val->second;
   }
-  return op_val->second;
+  return val;
 }
 
 //=============================================================================
-std::string BLSURFPlugin_Hypothesis::GetPreCADOptionValue(const std::string& optionName) throw (std::invalid_argument) {
-  TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
-  if (op_val == _preCADoption2value.end()) {
-    std::string msg = "Unknown PRECAD option: <";
-    msg += optionName + ">";
-    throw std::invalid_argument(msg);
+std::string BLSURFPlugin_Hypothesis::GetPreCADOptionValue(const std::string& optionName,
+                                                          bool*              isDefault) const
+  throw (std::invalid_argument)
+{
+  TOptionValues::const_iterator op_val = _preCADoption2value.find(optionName);
+  if (op_val == _preCADoption2value.end())
+  {
+    op_val = _option2value.find(optionName);
+    if (op_val == _option2value.end())
+    {
+      op_val = _customOption2value.find(optionName);
+      if (op_val == _customOption2value.end())
+      {
+        std::string msg = "Unknown MG-CADSurf option: <" + optionName + ">";
+        throw std::invalid_argument(msg);
+      }
+    }
   }
-  return op_val->second;
+  std::string val = op_val->second;
+  if ( isDefault ) *isDefault = ( val.empty() );
+
+  if ( val.empty() && isDefault )
+  {
+    op_val = _defaultOptionValues.find( optionName );
+    if (op_val != _option2value.end())
+      val = op_val->second;
+  }
+  return val;
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName) {
-  TOptionValues::iterator op_val = _option2value.find(optionName);
-  if (op_val != _option2value.end())
-    op_val->second.clear();
+void BLSURFPlugin_Hypothesis::ClearOption(const std::string& optionName)
+{
+  TOptionValues::iterator op_val = _customOption2value.find(optionName);
+  if (op_val != _customOption2value.end())
+   _customOption2value.erase(op_val);
+  else {
+    op_val = _option2value.find(optionName);
+    if (op_val != _option2value.end())
+      op_val->second.clear();
+    else {
+      op_val = _preCADoption2value.find(optionName);
+      if (op_val != _preCADoption2value.end())
+        op_val->second.clear();
+    }
+  }
 }
 
 //=============================================================================
-void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName) {
+void BLSURFPlugin_Hypothesis::ClearPreCADOption(const std::string& optionName)
+{
   TOptionValues::iterator op_val = _preCADoption2value.find(optionName);
   if (op_val != _preCADoption2value.end())
     op_val->second.clear();
 }
 
+//=============================================================================
+void BLSURFPlugin_Hypothesis::AddOption(const std::string& optionName, const std::string& optionValue)
+{
+  bool modif = true;
+  TOptionValues::iterator op_val = _option2value.find(optionName);
+  if (op_val != _option2value.end())
+  {
+    if (op_val->second != optionValue)
+      op_val->second = optionValue;
+    else
+      modif = false;
+  }
+  else
+  {
+    op_val = _preCADoption2value.find(optionName);
+    if (op_val != _preCADoption2value.end())
+    {
+      if (op_val->second != optionValue)
+        op_val->second = optionValue;
+      else
+        modif = false;
+    }
+    else if ( optionValue.empty() )
+    {
+      _customOption2value.erase( optionName );
+    }
+    else
+    {
+      op_val = _customOption2value.find(optionName);
+      if (op_val == _customOption2value.end())
+        _customOption2value[optionName] = optionValue;
+      else if (op_val->second != optionValue)
+        op_val->second = optionValue;
+      else
+        modif = false;
+    }
+  }
+  if ( modif )
+    NotifySubMeshesHypothesisModification();
+}
+
+//=============================================================================
+void BLSURFPlugin_Hypothesis::AddPreCADOption(const std::string& optionName, const std::string& optionValue)
+{
+  AddOption( optionName, optionValue );
+}
+
+//=============================================================================
+std::string BLSURFPlugin_Hypothesis::GetOption(const std::string& optionName) const
+{
+  TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
+  if (op_val != _customOption2value.end())
+    return op_val->second;
+  else
+    return "";
+}
+
+//=============================================================================
+std::string BLSURFPlugin_Hypothesis::GetPreCADOption(const std::string& optionName) const
+{
+  TOptionValues::const_iterator op_val = _customOption2value.find(optionName);
+  if (op_val != _customOption2value.end())
+    return op_val->second;
+  else
+    return "";
+}
+
+//=============================================================================
+BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetOptionValues() const
+{
+  TOptionValues vals;
+  TOptionValues::const_iterator op_val = _option2value.begin();
+  for ( ; op_val != _option2value.end(); ++op_val )
+    vals.insert( make_pair( op_val->first, GetOptionValue( op_val->first, GET_DEFAULT() )));
+
+  return vals;
+}
+
+//=============================================================================
+BLSURFPlugin_Hypothesis::TOptionValues BLSURFPlugin_Hypothesis::GetPreCADOptionValues() const
+{
+  TOptionValues vals;
+  TOptionValues::const_iterator op_val = _preCADoption2value.begin();
+  for ( ; op_val != _preCADoption2value.end(); ++op_val )
+    vals.insert( make_pair( op_val->first, GetPreCADOptionValue( op_val->first, GET_DEFAULT() )));
+
+  return vals;
+}
+
 //=======================================================================
 //function : SetSizeMapEntry
 //=======================================================================
@@ -681,7 +1201,8 @@ BLSURFPlugin_Hypothesis::TAttractorMap BLSURFPlugin_Hypothesis::GetClassAttracto
 //=======================================================================
 //function : ClearEntry
 //=======================================================================
-void BLSURFPlugin_Hypothesis::ClearEntry(const std::string& entry)
+void BLSURFPlugin_Hypothesis::ClearEntry(const std::string& entry,
+                                         const char * attEntry/*=0*/)
 {
  TSizeMap::iterator it  = _sizeMap.find( entry );
  
@@ -699,8 +1220,10 @@ void BLSURFPlugin_Hypothesis::ClearEntry(const std::string& entry)
      TAttractorMap::iterator it_clAt = _classAttractors.find( entry );
      if ( it_clAt != _classAttractors.end() ) {
        do {
-         _classAttractors.erase(it_clAt);
-         it_clAt = _classAttractors.find( entry );
+         if ( !attEntry || it_clAt->second->GetAttractorEntry() == attEntry )
+           _classAttractors.erase( it_clAt++ );
+         else
+           ++it_clAt;
        }
        while ( it_clAt != _classAttractors.end() );
        MESSAGE("_classAttractors.size() = "<<_classAttractors.size())
@@ -1205,7 +1728,7 @@ void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFaces(bool toEnforceIn
 
 //=============================================================================
 void BLSURFPlugin_Hypothesis::SetInternalEnforcedVertexAllFacesGroup(BLSURFPlugin_Hypothesis::TEnfGroupName theGroupName) {
-  if (string(theGroupName) != string(_enforcedInternalVerticesAllFacesGroup)) {
+  if (std::string(theGroupName) != std::string(_enforcedInternalVerticesAllFacesGroup)) {
     _enforcedInternalVerticesAllFacesGroup = theGroupName;
     NotifySubMeshesHypothesisModification();
   }
@@ -1254,7 +1777,7 @@ void BLSURFPlugin_Hypothesis::ClearPreCadPeriodicityVectors() {
 //function : AddPreCadFacesPeriodicity
 //=======================================================================
 void BLSURFPlugin_Hypothesis::AddPreCadFacesPeriodicity(TEntry theFace1Entry, TEntry theFace2Entry,
-    vector<string> &theSourceVerticesEntries, vector<string> &theTargetVerticesEntries) {
+    std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries) {
 
   TPreCadPeriodicity preCadFacesPeriodicity;
   preCadFacesPeriodicity.shape1Entry = theFace1Entry;
@@ -1271,7 +1794,7 @@ void BLSURFPlugin_Hypothesis::AddPreCadFacesPeriodicity(TEntry theFace1Entry, TE
 //function : AddPreCadEdgesPeriodicity
 //=======================================================================
 void BLSURFPlugin_Hypothesis::AddPreCadEdgesPeriodicity(TEntry theEdge1Entry, TEntry theEdge2Entry,
-    vector<string> &theSourceVerticesEntries, vector<string> &theTargetVerticesEntries) {
+    std::vector<std::string> &theSourceVerticesEntries, std::vector<std::string> &theTargetVerticesEntries) {
 
   TPreCadPeriodicity preCadEdgesPeriodicity;
   preCadEdgesPeriodicity.shape1Entry = theEdge1Entry;
@@ -1284,62 +1807,10 @@ void BLSURFPlugin_Hypothesis::AddPreCadEdgesPeriodicity(TEntry theEdge1Entry, TE
   NotifySubMeshesHypothesisModification();
 }
 
-//=======================================================================
-//function : AddFacePeriodicity
-//=======================================================================
-void BLSURFPlugin_Hypothesis::AddFacePeriodicity(TEntry theFace1Entry, TEntry theFace2Entry) {
-
-  std::pair< TEntry, TEntry > pairOfFacesEntries = std::make_pair(theFace1Entry, theFace2Entry);
-
-  _facesPeriodicityVector.push_back(pairOfFacesEntries);
-
-  // Removed for performance reason since AddFacePeriodicity is called multiple times (one time for each face)
-  // Does not affect the behaviour since it is only called via python, not via GUI.
-  //NotifySubMeshesHypothesisModification();
-}
-
-
-//=======================================================================
-//function : AddEdgePeriodicity
-//=======================================================================
-void BLSURFPlugin_Hypothesis::AddEdgePeriodicity(TEntry theFace1Entry, TEntry theEdge1Entry, TEntry theFace2Entry, TEntry theEdge2Entry, int edge_orientation) {
-
-  TEdgePeriodicity edgePeriodicity;
-  edgePeriodicity.theFace1Entry = theFace1Entry;
-  edgePeriodicity.theEdge1Entry = theEdge1Entry;
-  edgePeriodicity.theFace2Entry = theFace2Entry;
-  edgePeriodicity.theEdge2Entry = theEdge2Entry;
-  edgePeriodicity.edge_orientation = edge_orientation;
-
-  _edgesPeriodicityVector.push_back(edgePeriodicity);
-
-  // Removed for performance reason since AddEdgePeriodicity is called multiple times (one time for each edge)
-  // Does not affect the behaviour since it is only called via python, not via GUI.
-  //NotifySubMeshesHypothesisModification();
-}
-
-//=======================================================================
-//function : AddVertexPeriodicity
-//=======================================================================
-void BLSURFPlugin_Hypothesis::AddVertexPeriodicity(TEntry theEdge1Entry, TEntry theVertex1Entry, TEntry theEdge2Entry, TEntry theVertex2Entry) {
-
-  TVertexPeriodicity vertexPeriodicity;
-  vertexPeriodicity.theEdge1Entry = theEdge1Entry;
-  vertexPeriodicity.theVertex1Entry = theVertex1Entry;
-  vertexPeriodicity.theEdge2Entry = theEdge2Entry;
-  vertexPeriodicity.theVertex2Entry = theVertex2Entry;
-
-  _verticesPeriodicityVector.push_back(vertexPeriodicity);
-
-  // Removed for performance reason since AddVertexPeriodicity is called multiple times (one time for each vertex)
-  // Does not affect the behaviour since it is only called via python, not via GUI.
-  //NotifySubMeshesHypothesisModification();
-}
-
 //=============================================================================
 std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
    // We must keep at least the same number of arguments when increasing the SALOME version
-   // When BLSURF becomes CADMESH, some parameters were fused into a single one. Thus the same
+   // When MG-CADSurf becomes CADMESH, some parameters were fused into a single one. Thus the same
    // parameter can be written several times to keep the old global number of parameters.
 
    // Treat old options which are now in the advanced options
@@ -1374,7 +1845,10 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
   save << " " << (int) _phySizeRel << " " << (int) _minSizeRel << " " << (int) _maxSizeRel << " " << _chordalError ;
   save << " " << (int) _anisotropic << " " << _anisotropicRatio << " " << (int) _removeTinyEdges << " " << _tinyEdgeLength ;
   save << " " << (int) _badElementRemoval << " " << _badElementAspectRatio << " " << (int) _optimizeMesh << " " << (int) _quadraticMesh ;
-  save << " " << (int) _preCADProcess3DTopology;
+  save << " " << (int) _preCADProcess3DTopology << " " << (int) _preCADRemoveDuplicateCADFaces << " " << (int) _preCADRemoveTinyUVEdges;
+  save << " " << (int)_optimiseTinyEdges << " " << _tinyEdgeOptimisationLength;
+  save << " " << (int)_correctSurfaceIntersec << " " << _corrSurfaceIntersCost;
+  save << " " << (int)_useGradation << " " << (int)_useVolumeGradation << " " << _volumeGradation;
 
   op_val = _option2value.begin();
   if (op_val != _option2value.end()) {
@@ -1386,6 +1860,16 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
     save << " " << "__OPTIONS_END__";
   }
   
+  op_val = _customOption2value.begin();
+  if (op_val != _customOption2value.end()) {
+    save << " " << "__CUSTOM_OPTIONS_BEGIN__";
+    for (; op_val != _customOption2value.end(); ++op_val) {
+      if (!op_val->second.empty())
+        save << " " << op_val->first << " " << op_val->second << "%#"; // "%#" is a mark of value end
+    }
+    save << " " << "__CUSTOM_OPTIONS_END__";
+  }
+
   op_val = _preCADoption2value.begin();
   if (op_val != _preCADoption2value.end()) {
     save << " " << "__PRECAD_OPTIONS_BEGIN__";
@@ -1460,7 +1944,7 @@ std::ostream & BLSURFPlugin_Hypothesis::SaveTo(std::ostream & save) {
       }
       if (enfVertex->coords.size()) {
         save << " " << "__BEGIN_COORDS__";
-        for (int i=0;i<enfVertex->coords.size();i++)
+        for ( size_t i = 0; i < enfVertex->coords.size(); i++ )
           save << " " << enfVertex->coords[i];
         save << " " << "__END_COORDS__";
       }
@@ -1578,7 +2062,7 @@ void BLSURFPlugin_Hypothesis::SaveVerticesPeriodicity(std::ostream & save){
 
 void BLSURFPlugin_Hypothesis::SavePreCADPeriodicity(std::ostream & save, const char* shapeType) {
   TPreCadPeriodicityVector precad_periodicity;
-  if (shapeType == "FACES")
+  if ( shapeType  &&  strcmp( shapeType, "FACES" ) == 0 )
     precad_periodicity = _preCadFacesPeriodicityVector;
   else
     precad_periodicity = _preCadEdgesPeriodicityVector;
@@ -1635,49 +2119,49 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   double val;
   std::string option_or_sm;
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _topology = (Topology) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _physicalMesh = (PhysicalMesh) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _geometricMesh = (GeometricMesh) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     _phySize = val;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     _angleMesh = val;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     _gradation = val;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _quadAllowed = (bool) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK) {
     if ( i != -1) { // if value is -1, then this is no longer a standard option
       std::string & value = _option2value["respect_geometry"];
@@ -1688,52 +2172,52 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     _minSize = val;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     _maxSize = val;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     // former parameter: get min value
-    _angleMesh = min(val,_angleMesh);
+    _angleMesh = std::min(val,_angleMesh);
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     // former parameter: get min value
-    _minSize = min(val,_minSize);
+    _minSize = std::min(val,_minSize);
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK)
     // former parameter: get max value
-    _maxSize = max(val,_maxSize);
+    _maxSize = std::max(val,_maxSize);
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _verb = i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _preCADMergeEdges = (bool) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK) {
     if ( i != -1) { // if value is -1, then this is no longer a standard option
       std::string & value = _preCADoption2value["remove_tiny_edges"];
@@ -1744,13 +2228,13 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _preCADDiscardInput = (bool) i;
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> val);
+  isOK = static_cast<bool>(load >> val);
   if (isOK) { // _preCADEpsNano
     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
       std::string & value = _preCADoption2value["tiny_edge_length"];
@@ -1762,7 +2246,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   else
     load.clear(std::ios::badbit | load.rdstate());
 
-  isOK = (load >> i);
+  isOK = static_cast<bool>(load >> i);
   if (isOK)
     _enforcedInternalVerticesAllFaces = (bool) i;
   else
@@ -1772,6 +2256,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
 
   bool hasCADSurfOptions = false;
   bool hasOptions = false;
+  bool hasCustomOptions = false;
   bool hasPreCADOptions = false;
   bool hasSizeMap = false;
   bool hasAttractor = false;
@@ -1783,7 +2268,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   bool hasEdgesPeriodicity = false;
   bool hasVerticesPeriodicity = false;
 
-  isOK = (load >> option_or_sm);
+  isOK = static_cast<bool>(load >> option_or_sm);
   if (isOK)
     if ( (option_or_sm == "1")||(option_or_sm == "0") ) {
       i = atoi(option_or_sm.c_str());
@@ -1792,6 +2277,8 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
     }
     if (option_or_sm == "__OPTIONS_BEGIN__")
       hasOptions = true;
+    else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
+      hasCustomOptions = true;
     else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
       hasPreCADOptions = true;
     else if (option_or_sm == "__SIZEMAP_BEGIN__")
@@ -1814,86 +2301,144 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       hasVerticesPeriodicity = true;
 
   if (isOK && hasCADSurfOptions) {
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _minSizeRel = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _maxSizeRel = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> val);
+    isOK = static_cast<bool>(load >> val);
     if (isOK)
       _chordalError = val;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _anisotropic = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> val);
+    isOK = static_cast<bool>(load >> val);
     if (isOK)
       _anisotropicRatio = val;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _removeTinyEdges = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> val);
+    isOK = static_cast<bool>(load >> val);
     if (isOK)
       _tinyEdgeLength = val;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _badElementRemoval = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> val);
+    isOK = static_cast<bool>(load >> val);
     if (isOK)
       _badElementAspectRatio = val;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _optimizeMesh = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _quadraticMesh = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
-    isOK = (load >> i);
+    isOK = static_cast<bool>(load >> i);
     if (isOK)
       _preCADProcess3DTopology = (bool) i;
     else
       load.clear(std::ios::badbit | load.rdstate());
 
+    if (( load >> std::ws).peek() != '_' )
+    {
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _preCADRemoveDuplicateCADFaces = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _preCADRemoveTinyUVEdges = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _optimiseTinyEdges = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> val);
+      if (isOK)
+        _tinyEdgeOptimisationLength = val;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _correctSurfaceIntersec = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> val);
+      if (isOK)
+        _corrSurfaceIntersCost = val;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _useGradation = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> i);
+      if (isOK)
+        _useVolumeGradation = (bool) i;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+
+      isOK = static_cast<bool>(load >> val);
+      if (isOK)
+        _volumeGradation = val;
+      else
+        load.clear(std::ios::badbit | load.rdstate());
+    }
   }
-  
+
 
   if (hasCADSurfOptions) {
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__OPTIONS_BEGIN__")
         hasOptions = true;
+      else if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
+        hasCustomOptions = true;
       else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
         hasPreCADOptions = true;
       else if (option_or_sm == "__SIZEMAP_BEGIN__")
@@ -1914,15 +2459,16 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
   
   std::string optName, optValue;
   while (isOK && hasOptions) {
-    isOK = (load >> optName);
+    isOK = static_cast<bool>(load >> optName);
     if (isOK) {
       if (optName == "__OPTIONS_END__")
         break;
-      isOK = (load >> optValue);
+      isOK = static_cast<bool>(load >> optValue);
     }
     if (isOK) {
       std::string & value = _option2value[optName];
@@ -1930,7 +2476,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       int len = value.size();
       // continue reading until "%#" encountered
       while (value[len - 1] != '#' || value[len - 2] != '%') {
-        isOK = (load >> optValue);
+        isOK = static_cast<bool>(load >> optValue);
         if (isOK) {
           value += " ";
           value += optValue;
@@ -1939,13 +2485,67 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
           break;
         }
       }
-      value[len - 2] = '\0'; //cut off "%#"
+      value.resize(len - 2); //cut off "%#"
     }
   }
 
   if (hasOptions) {
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
+      if (option_or_sm == "__CUSTOM_OPTIONS_BEGIN__")
+        hasCustomOptions = true;
+      else if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
+        hasPreCADOptions = true;
+      else if (option_or_sm == "__SIZEMAP_BEGIN__")
+        hasSizeMap = true;
+      else if (option_or_sm == "__ATTRACTORS_BEGIN__")
+        hasAttractor = true;
+      else if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
+        hasNewAttractor = true;
+      else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
+        hasEnforcedVertex = true;
+      else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
+        hasPreCADFacesPeriodicity = true;
+      else if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
+        hasPreCADEdgesPeriodicity = true;
+      else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
+        hasFacesPeriodicity = true;
+      else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
+        hasEdgesPeriodicity = true;
+      else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
+        hasVerticesPeriodicity = true;
+    }
+  }
+
+  while (isOK && hasCustomOptions) {
+    isOK = static_cast<bool>(load >> optName);
+    if (isOK) {
+      if (optName == "__CUSTOM_OPTIONS_END__")
+        break;
+      isOK = static_cast<bool>(load >> optValue);
+    }
+    if (isOK) {
+      std::string& value = optValue;
+      int len = value.size();
+      // continue reading until "%#" encountered
+      while (value[len - 1] != '#' || value[len - 2] != '%') {
+        isOK = static_cast<bool>(load >> optValue);
+        if (isOK) {
+          value += " ";
+          value += optValue;
+          len = value.size();
+        } else {
+          break;
+        }
+      }
+      value.resize(len - 2); //cut off "%#"
+      _customOption2value[optName] = value;
+    }
+  }
+
+  if (hasCustomOptions) {
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__PRECAD_OPTIONS_BEGIN__")
         hasPreCADOptions = true;
       else if (option_or_sm == "__SIZEMAP_BEGIN__")
@@ -1966,14 +2566,15 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
   while (isOK && hasPreCADOptions) {
-    isOK = (load >> optName);
+    isOK = static_cast<bool>(load >> optName);
     if (isOK) {
       if (optName == "__PRECAD_OPTIONS_END__")
         break;
-      isOK = (load >> optValue);
+      isOK = static_cast<bool>(load >> optValue);
     }
     if (isOK) {
       std::string & value = _preCADoption2value[optName];
@@ -1981,7 +2582,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       int len = value.size();
       // continue reading until "%#" encountered
       while (value[len - 1] != '#' || value[len - 2] != '%') {
-        isOK = (load >> optValue);
+        isOK = static_cast<bool>(load >> optValue);
         if (isOK) {
           value += " ";
           value += optValue;
@@ -1990,13 +2591,13 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
           break;
         }
       }
-      value[len - 2] = '\0'; //cut off "%#"
+      value.resize(len - 2); //cut off "%#"
     }
   }
 
   if (hasPreCADOptions) {
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__SIZEMAP_BEGIN__")
         hasSizeMap = true;
       else if (option_or_sm == "__ATTRACTORS_BEGIN__")
@@ -2015,15 +2616,16 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
-  
   std::string smEntry, smValue;
   while (isOK && hasSizeMap) {
-    isOK = (load >> smEntry);
+    isOK = static_cast<bool>(load >> smEntry);
     if (isOK) {
       if (smEntry == "__SIZEMAP_END__")
         break;
-      isOK = (load >> smValue);
+      isOK = static_cast<bool>(load >> smValue);
     }
     if (isOK) {
       std::string & value2 = _sizeMap[smEntry];
@@ -2031,7 +2633,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       int len2 = value2.size();
       // continue reading until "%#" encountered
       while (value2[len2 - 1] != '#' || value2[len2 - 2] != '%') {
-        isOK = (load >> smValue);
+        isOK = static_cast<bool>(load >> smValue);
         if (isOK) {
           value2 += " ";
           value2 += smValue;
@@ -2040,12 +2642,12 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
           break;
         }
       }
-      value2[len2 - 2] = '\0'; //cut off "%#"
+      value2.resize(len2 - 2); //cut off "%#"
     }
   }
 
   if (hasSizeMap) {
-    isOK = (load >> option_or_sm);
+    isOK = static_cast<bool>(load >> option_or_sm);
     if (isOK)
       if (option_or_sm == "__ATTRACTORS_BEGIN__")
         hasAttractor = true;
@@ -2067,11 +2669,11 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
 
   std::string atEntry, atValue;
   while (isOK && hasAttractor) {
-    isOK = (load >> atEntry);
+    isOK = static_cast<bool>(load >> atEntry);
     if (isOK) {
       if (atEntry == "__ATTRACTORS_END__")
         break;
-      isOK = (load >> atValue);
+      isOK = static_cast<bool>(load >> atValue);
     }
     if (isOK) {
       std::string & value3 = _attractors[atEntry];
@@ -2079,7 +2681,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       int len3 = value3.size();
       // continue reading until "%#" encountered
       while (value3[len3 - 1] != '#' || value3[len3 - 2] != '%') {
-        isOK = (load >> atValue);
+        isOK = static_cast<bool>(load >> atValue);
         if (isOK) {
           value3 += " ";
           value3 += atValue;
@@ -2088,13 +2690,13 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
           break;
         }
       }
-      value3[len3 - 2] = '\0'; //cut off "%#"
+      value3.resize(len3 - 2); //cut off "%#"
     }
   }
 
   if (hasAttractor) {
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__NEW_ATTRACTORS_BEGIN__")
         hasNewAttractor = true;
       else if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
@@ -2109,22 +2711,23 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
   std::string newAtFaceEntry, atTestString;
   std::string newAtShapeEntry;
   double attParams[4];
-  double step;
+  //double step;
   while (isOK && hasNewAttractor) {
     //std::cout<<"Load new attractor"<<std::endl;
-    isOK = (load >> newAtFaceEntry);
+    isOK = static_cast<bool>(load >> newAtFaceEntry);
     if (isOK) {
       if (newAtFaceEntry == "__NEW_ATTRACTORS_END__")
         break;
-      isOK = (load >> newAtShapeEntry);
+      isOK = static_cast<bool>(load >> newAtShapeEntry);
       if (!isOK)
     break;
-      isOK = (load >> attParams[0]>>attParams[1]>>attParams[2]>>attParams[3]); //>>step);
+      isOK = static_cast<bool>(load >> attParams[0]>>attParams[1]>>attParams[2]>>attParams[3]); //>>step);
     }
     if (isOK) {
       MESSAGE(" LOADING ATTRACTOR HYPOTHESIS ")
@@ -2139,8 +2742,8 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   
   
   if (hasNewAttractor) {
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__ENFORCED_VERTICES_BEGIN__")
         hasEnforcedVertex = true;
       else if (option_or_sm == "__PRECAD_FACES_PERIODICITY_BEGIN__")
@@ -2153,6 +2756,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
 
@@ -2190,7 +2794,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   
   
   while (isOK && hasEnforcedVertex) {
-    isOK = (load >> enfSeparator); // __BEGIN_VERTEX__
+    isOK = static_cast<bool>(load >> enfSeparator); // __BEGIN_VERTEX__
     TEnfVertex *enfVertex = new TEnfVertex();
 //     MESSAGE("enfSeparator: " <<enfSeparator);
     if (enfSeparator == "__ENFORCED_VERTICES_END__")
@@ -2199,7 +2803,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       throw std::exception();
     
     while (isOK) {
-      isOK = (load >> enfSeparator);
+      isOK = static_cast<bool>(load >> enfSeparator);
       MESSAGE("enfSeparator: " <<enfSeparator);
       if (enfSeparator == "__END_VERTEX__") {
         
@@ -2238,7 +2842,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         
       if (enfSeparator == "__BEGIN_NAME__") {  // __BEGIN_NAME__
         while (isOK && (enfSeparator != "__END_NAME__")) {
-          isOK = (load >> enfSeparator);
+          isOK = static_cast<bool>(load >> enfSeparator);
           if (enfSeparator != "__END_NAME__") {
             if (!enfName.empty())
               enfName += " ";
@@ -2249,8 +2853,8 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
       }
         
       if (enfSeparator == "__BEGIN_ENTRY__") {  // __BEGIN_ENTRY__
-        isOK = (load >> enfGeomEntry);
-        isOK = (load >> enfSeparator); // __END_ENTRY__
+        isOK = static_cast<bool>(load >> enfGeomEntry);
+        isOK = static_cast<bool>(load >> enfSeparator); // __END_ENTRY__
         if (enfSeparator != "__END_ENTRY__")
           throw std::exception();
         MESSAGE("enfGeomEntry: " <<enfGeomEntry);
@@ -2258,7 +2862,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         
       if (enfSeparator == "__BEGIN_GROUP__") {  // __BEGIN_GROUP__
         while (isOK && (enfSeparator != "__END_GROUP__")) {
-          isOK = (load >> enfSeparator);
+          isOK = static_cast<bool>(load >> enfSeparator);
           if (enfSeparator != "__END_GROUP__") {
             if (!enfGroup.empty())
               enfGroup += " ";
@@ -2270,8 +2874,8 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         
       if (enfSeparator == "__BEGIN_COORDS__") {  // __BEGIN_COORDS__
         hasCoords = true;
-        isOK = (load >> enfCoords[0] >> enfCoords[1] >> enfCoords[2]);
-        isOK = (load >> enfSeparator); // __END_COORDS__
+        isOK = static_cast<bool>(load >> enfCoords[0] >> enfCoords[1] >> enfCoords[2]);
+        isOK = static_cast<bool>(load >> enfSeparator); // __END_COORDS__
         if (enfSeparator != "__END_COORDS__")
           throw std::exception();
         MESSAGE("enfCoords: " << enfCoords[0] <<","<< enfCoords[1] <<","<< enfCoords[2]);
@@ -2279,7 +2883,7 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         
       if (enfSeparator == "__BEGIN_FACELIST__") {  // __BEGIN_FACELIST__
         while (isOK && (enfSeparator != "__END_FACELIST__")) {
-          isOK = (load >> enfSeparator);
+          isOK = static_cast<bool>(load >> enfSeparator);
           if (enfSeparator != "__END_FACELIST__") {
             enfFaceEntryList.insert(enfSeparator);
             MESSAGE(enfSeparator << " was inserted into enfFaceEntryList");
@@ -2294,8 +2898,8 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
   if (hasPreCADFacesPeriodicity){
     LoadPreCADPeriodicity(load, "FACES");
 
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__PRECAD_EDGES_PERIODICITY_BEGIN__")
         hasPreCADEdgesPeriodicity = true;
       else if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
@@ -2304,36 +2908,39 @@ std::istream & BLSURFPlugin_Hypothesis::LoadFrom(std::istream & load) {
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
   if (hasPreCADEdgesPeriodicity){
     LoadPreCADPeriodicity(load, "EDGES");
 
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__FACES_PERIODICITY_BEGIN__")
         hasFacesPeriodicity = true;
       else if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
   if (hasFacesPeriodicity){
       LoadFacesPeriodicity(load);
 
-    isOK = (load >> option_or_sm);
-    if (isOK)
+    isOK = static_cast<bool>(load >> option_or_sm);
+    if (isOK) {
       if (option_or_sm == "__EDGES_PERIODICITY_BEGIN__")
         hasEdgesPeriodicity = true;
       else if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
+    }
   }
 
   if (hasEdgesPeriodicity){
       LoadEdgesPeriodicity(load);
 
-    isOK = (load >> option_or_sm);
+    isOK = static_cast<bool>(load >> option_or_sm);
     if (isOK)
       if (option_or_sm == "__VERTICES_PERIODICITY_BEGIN__")
         hasVerticesPeriodicity = true;
@@ -2356,7 +2963,7 @@ void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
   _facesPeriodicityVector.clear();
 
   while (isOK) {
-    isOK = (load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
+    isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
     MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TFacesPeriodicity *periodicity_i = new TFacesPeriodicity();
     if (periodicitySeparator == "__FACES_PERIODICITY_END__")
@@ -2367,7 +2974,7 @@ void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
     }
 
     while (isOK) {
-      isOK = (load >> periodicitySeparator);
+      isOK = static_cast<bool>(load >> periodicitySeparator);
       MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
@@ -2380,16 +2987,16 @@ void BLSURFPlugin_Hypothesis::LoadFacesPeriodicity(std::istream & load){
       }
 
       if (periodicitySeparator == "__BEGIN_ENTRY1__") {  // __BEGIN_ENTRY1__
-        isOK = (load >> shape1Entry);
-        isOK = (load >> periodicitySeparator); // __END_ENTRY1__
+        isOK = static_cast<bool>(load >> shape1Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
         if (periodicitySeparator != "__END_ENTRY1__")
           throw std::exception();
         MESSAGE("shape1Entry: " <<shape1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
-        isOK = (load >> shape2Entry);
-        isOK = (load >> periodicitySeparator); // __END_ENTRY2__
+        isOK = static_cast<bool>(load >> shape2Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
         if (periodicitySeparator != "__END_ENTRY2__")
           throw std::exception();
         MESSAGE("shape2Entry: " <<shape2Entry);
@@ -2413,7 +3020,7 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
   _edgesPeriodicityVector.clear();
 
   while (isOK) {
-    isOK = (load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
+    isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
     MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TEdgePeriodicity *periodicity_i = new TEdgePeriodicity();
     if (periodicitySeparator == "__EDGES_PERIODICITY_END__")
@@ -2424,7 +3031,7 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
     }
 
     while (isOK) {
-      isOK = (load >> periodicitySeparator);
+      isOK = static_cast<bool>(load >> periodicitySeparator);
       MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
@@ -2440,9 +3047,9 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
       }
 
       if (periodicitySeparator == "__BEGIN_FACE1__") {  // __BEGIN_FACE1__
-        isOK = (load >> theFace1Entry);
+        isOK = static_cast<bool>(load >> theFace1Entry);
         MESSAGE("//" << theFace1Entry << "//");
-        isOK = (load >> periodicitySeparator); // __END_FACE1__
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE1__
         if (periodicitySeparator != "__END_FACE1__"){
           MESSAGE("//" << periodicitySeparator << "//");
           throw std::exception();
@@ -2451,32 +3058,32 @@ void BLSURFPlugin_Hypothesis::LoadEdgesPeriodicity(std::istream & load){
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
-        isOK = (load >> theEdge1Entry);
-        isOK = (load >> periodicitySeparator); // __END_EDGE1__
+        isOK = static_cast<bool>(load >> theEdge1Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
         if (periodicitySeparator != "__END_EDGE1__")
           throw std::exception();
         MESSAGE("theEdge1Entry: " <<theEdge1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_FACE2__") {  // __BEGIN_FACE2__
-        isOK = (load >> theFace2Entry);
-        isOK = (load >> periodicitySeparator); // __END_FACE2__
+        isOK = static_cast<bool>(load >> theFace2Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_FACE2__
         if (periodicitySeparator != "__END_FACE2__")
           throw std::exception();
         MESSAGE("theFace2Entry: " <<theFace2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
-        isOK = (load >> theEdge2Entry);
-        isOK = (load >> periodicitySeparator); // __END_EDGE2__
+        isOK = static_cast<bool>(load >> theEdge2Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
         if (periodicitySeparator != "__END_EDGE2__")
           throw std::exception();
         MESSAGE("theEdge2Entry: " <<theEdge2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE_ORIENTATION__") {  // __BEGIN_EDGE_ORIENTATION__
-        isOK = (load >> edge_orientation);
-        isOK = (load >> periodicitySeparator); // __END_EDGE_ORIENTATION__
+        isOK = static_cast<bool>(load >> edge_orientation);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE_ORIENTATION__
         if (periodicitySeparator != "__END_EDGE_ORIENTATION__")
           throw std::exception();
         MESSAGE("edge_orientation: " <<edge_orientation);
@@ -2498,7 +3105,7 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
   _verticesPeriodicityVector.clear();
 
   while (isOK) {
-    isOK = (load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
+    isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
     MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TVertexPeriodicity *periodicity_i = new TVertexPeriodicity();
     if (periodicitySeparator == "__VERTICES_PERIODICITY_END__")
@@ -2509,7 +3116,7 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
     }
 
     while (isOK) {
-      isOK = (load >> periodicitySeparator);
+      isOK = static_cast<bool>(load >> periodicitySeparator);
       MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
@@ -2524,32 +3131,32 @@ void BLSURFPlugin_Hypothesis::LoadVerticesPeriodicity(std::istream & load){
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE1__") {  // __BEGIN_EDGE1__
-        isOK = (load >> theEdge1Entry);
-        isOK = (load >> periodicitySeparator); // __END_EDGE1__
+        isOK = static_cast<bool>(load >> theEdge1Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE1__
         if (periodicitySeparator != "__END_EDGE1__")
           throw std::exception();
         MESSAGE("theEdge1Entry: " <<theEdge1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_VERTEX1__") {  // __BEGIN_VERTEX1__
-        isOK = (load >> theVertex1Entry);
-        isOK = (load >> periodicitySeparator); // __END_VERTEX1__
+        isOK = static_cast<bool>(load >> theVertex1Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX1__
         if (periodicitySeparator != "__END_VERTEX1__")
           throw std::exception();
         MESSAGE("theVertex1Entry: " <<theVertex1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_EDGE2__") {  // __BEGIN_EDGE2__
-        isOK = (load >> theEdge2Entry);
-        isOK = (load >> periodicitySeparator); // __END_EDGE2__
+        isOK = static_cast<bool>(load >> theEdge2Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_EDGE2__
         if (periodicitySeparator != "__END_EDGE2__")
           throw std::exception();
         MESSAGE("theEdge2Entry: " <<theEdge2Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_VERTEX2__") {  // __BEGIN_VERTEX2__
-        isOK = (load >> theVertex2Entry);
-        isOK = (load >> periodicitySeparator); // __END_VERTEX2__
+        isOK = static_cast<bool>(load >> theVertex2Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_VERTEX2__
         if (periodicitySeparator != "__END_VERTEX2__")
           throw std::exception();
         MESSAGE("theVertex2Entry: " <<theVertex2Entry);
@@ -2571,14 +3178,14 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
   bool hasSourceVertices = false;
   bool hasTargetVertices = false;
 
-  if (shapeType == "FACES")
+  if ( shapeType  &&  strcmp( shapeType, "FACES") == 0 )
     _preCadFacesPeriodicityVector.clear();
   else
     _preCadEdgesPeriodicityVector.clear();
 
 
   while (isOK) {
-    isOK = (load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
+    isOK = static_cast<bool>(load >> periodicitySeparator); // __BEGIN_PERIODICITY_DESCRIPTION__
     MESSAGE("periodicitySeparator 1: " <<periodicitySeparator);
     TPreCadPeriodicity *periodicity_i = new TPreCadPeriodicity();
 //     MESSAGE("periodicitySeparator: " <<periodicitySeparator);
@@ -2592,7 +3199,7 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
     }
 
     while (isOK) {
-      isOK = (load >> periodicitySeparator);
+      isOK = static_cast<bool>(load >> periodicitySeparator);
       MESSAGE("periodicitySeparator 2: " <<periodicitySeparator);
       if (periodicitySeparator == "__END_PERIODICITY_DESCRIPTION__") {
 
@@ -2607,7 +3214,7 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
         if (hasTargetVertices)
           periodicity_i->theTargetVerticesEntries = theTargetVerticesEntries;
 
-        if (shapeType == "FACES")
+        if ( shapeType  &&  strcmp( shapeType, "FACES" ))
           _preCadFacesPeriodicityVector.push_back(*periodicity_i);
         else
           _preCadEdgesPeriodicityVector.push_back(*periodicity_i);
@@ -2620,16 +3227,16 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
       }
 
       if (periodicitySeparator == "__BEGIN_ENTRY1__") {  // __BEGIN_ENTRY1__
-        isOK = (load >> shape1Entry);
-        isOK = (load >> periodicitySeparator); // __END_ENTRY1__
+        isOK = static_cast<bool>(load >> shape1Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY1__
         if (periodicitySeparator != "__END_ENTRY1__")
           throw std::exception();
         MESSAGE("shape1Entry: " <<shape1Entry);
       }
 
       if (periodicitySeparator == "__BEGIN_ENTRY2__") {  // __BEGIN_ENTRY2__
-        isOK = (load >> shape2Entry);
-        isOK = (load >> periodicitySeparator); // __END_ENTRY2__
+        isOK = static_cast<bool>(load >> shape2Entry);
+        isOK = static_cast<bool>(load >> periodicitySeparator); // __END_ENTRY2__
         if (periodicitySeparator != "__END_ENTRY2__")
           throw std::exception();
         MESSAGE("shape2Entry: " <<shape2Entry);
@@ -2638,7 +3245,7 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
       if (periodicitySeparator == "__BEGIN_SOURCE_VERTICES_LIST__") {  // __BEGIN_SOURCE_VERTICES_LIST__
         hasSourceVertices = true;
         while (isOK && (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__")) {
-          isOK = (load >> periodicitySeparator);
+          isOK = static_cast<bool>(load >> periodicitySeparator);
           if (periodicitySeparator != "__END_SOURCE_VERTICES_LIST__") {
             theSourceVerticesEntries.push_back(periodicitySeparator);
             MESSAGE("theSourceVerticesEntries: " <<periodicitySeparator);
@@ -2649,7 +3256,7 @@ void BLSURFPlugin_Hypothesis::LoadPreCADPeriodicity(std::istream & load, const c
       if (periodicitySeparator == "__BEGIN_TARGET_VERTICES_LIST__") {  // __BEGIN_TARGET_VERTICES_LIST__
         hasTargetVertices = true;
         while (isOK && (periodicitySeparator != "__END_TARGET_VERTICES_LIST__")) {
-          isOK = (load >> periodicitySeparator);
+          isOK = static_cast<bool>(load >> periodicitySeparator);
           if (periodicitySeparator != "__END_TARGET_VERTICES_LIST__") {
             theTargetVerticesEntries.push_back(periodicitySeparator);
             MESSAGE("theTargetVerticesEntries: " <<periodicitySeparator);
@@ -2740,6 +3347,18 @@ double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeLength(double diagonal) {
   return undefinedDouble();
 }
 
+//================================================================================
+/*!
+ * \brief Returns default tiny edge optimisation length given a default value of element length ratio
+ */
+//================================================================================
+
+double BLSURFPlugin_Hypothesis::GetDefaultTinyEdgeOptimisationLength(double diagonal) {
+  if (diagonal != 0)
+    return diagonal * 1e-6 ;
+  return undefinedDouble();
+}
+
 //=============================================================================
 /*!
  * \brief Initialize my parameter values by default parameters.
@@ -2752,9 +3371,90 @@ bool BLSURFPlugin_Hypothesis::SetParametersByDefaults(const TDefaults& dflts, co
   _phySize = GetDefaultPhySize(diagonal, _gen->GetBoundaryBoxSegmentation());
   _minSize = GetDefaultMinSize(diagonal);
   _maxSize = GetDefaultMaxSize(diagonal);
-  _chordalError = GetDefaultChordalError(diagonal);
+  _chordalError = 0.5 * _phySize; //GetDefaultChordalError(diagonal); IMP 0023307
   _tinyEdgeLength = GetDefaultTinyEdgeLength(diagonal);
+  _tinyEdgeOptimisationLength = GetDefaultTinyEdgeOptimisationLength(diagonal);
 
   return true;
-//   return bool(_phySize = dflts._elemLength);
 }
+
+//================================================================================
+/*!
+ * \brief Converts a string to a bool
+ */
+//================================================================================
+
+bool BLSURFPlugin_Hypothesis::ToBool(const std::string& str, bool* isOk )
+  throw (std::invalid_argument)
+{
+  std::string s = str;
+  if ( isOk ) *isOk = true;
+
+  for ( size_t i = 0; i <= s.size(); ++i )
+    s[i] = tolower( s[i] );
+
+  if ( s == "1" || s == "true" || s == "active" || s == "yes" )
+    return true;
+
+  if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
+    return false;
+
+  if ( isOk )
+    *isOk = false;
+  else {
+    std::string msg = "Not a Boolean value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return false;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a real value
+ */
+//================================================================================
+
+double BLSURFPlugin_Hypothesis::ToDbl(const std::string& str, bool* isOk )
+  throw (std::invalid_argument)
+{
+  if ( str.empty() ) throw std::invalid_argument("Empty value provided");
+
+  char * endPtr;
+  double val = strtod(&str[0], &endPtr);
+  bool ok = (&str[0] != endPtr);
+
+  if ( isOk ) *isOk = ok;
+
+  if ( !ok )
+  {
+    std::string msg = "Not a real value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return val;
+}
+
+//================================================================================
+/*!
+ * \brief Converts a string to a integer value
+ */
+//================================================================================
+
+int BLSURFPlugin_Hypothesis::ToInt(const std::string& str, bool* isOk )
+  throw (std::invalid_argument)
+{
+  if ( str.empty() ) throw std::invalid_argument("Empty value provided");
+
+  char * endPtr;
+  int val = (int)strtol( &str[0], &endPtr, 10);
+  bool ok = (&str[0] != endPtr);
+
+  if ( isOk ) *isOk = ok;
+
+  if ( !ok )
+  {
+    std::string msg = "Not an integer value:'" + str + "'";
+    throw std::invalid_argument(msg);
+  }
+  return val;
+}
+