From 8ca2808293632ed84472fbe15419baf1e1269e03 Mon Sep 17 00:00:00 2001
From: Jonathan Lambrechts <jonathan.lambrechts@uclouvain.be>
Date: Thu, 24 Apr 2014 16:22:18 +0000
Subject: [PATCH] add GModel::healGeometry (broken for open cascade factory)

---
 Geo/GModel.cpp        |  5 +++++
 Geo/GModel.h          |  3 +++
 Geo/GModelFactory.cpp | 28 ++++++++++++++++++++++++++++
 Geo/GModelFactory.h   |  5 +++++
 Geo/Geo.cpp           | 15 ++++++++++++---
 Geo/Geo.h             |  1 +
 6 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index c52b708871..87efec18ee 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -2840,6 +2840,11 @@ GEntity *GModel::addCone(std::vector<double> p1, std::vector<double> p2,
   return 0;
 }
 
+void GModel::healGeometry(double tolerance)
+{
+  if(_factory) _factory->healGeometry(this, tolerance);
+}
+
 GModel *GModel::computeBooleanUnion(GModel *tool, int createNewModel)
 {
   if(_factory)
diff --git a/Geo/GModel.h b/Geo/GModel.h
index ccd36d4a60..18d7d44760 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -524,6 +524,9 @@ class GModel
   GEntity *addCone(std::vector<double> p1, std::vector<double> p2, double radius1,
                    double radius2);
 
+  // heal geometry using the factory
+  void healGeometry(double tolerance = -1);
+
   // boolean operators acting on 2 models
   GModel *computeBooleanUnion(GModel *tool, int createNewModel=0);
   GModel *computeBooleanIntersection(GModel *tool, int createNewModel=0);
diff --git a/Geo/GModelFactory.cpp b/Geo/GModelFactory.cpp
index 1582088708..6bf5b36578 100644
--- a/Geo/GModelFactory.cpp
+++ b/Geo/GModelFactory.cpp
@@ -427,6 +427,16 @@ std::vector<GEntity*> GeoFactory::extrudeBoundaryLayer(GModel *gm, GEntity *e,
 
 };
 
+void GeoFactory::healGeometry(GModel *gm, double tolerance)
+{
+  GModel *current = GModel::current();
+  GModel::setCurrent(gm);
+  ReplaceAllDuplicatesNew(tolerance);
+  gm->destroy();
+  gm->importGEOInternals();
+  GModel::setCurrent(current);
+}
+
 #if defined(HAVE_OCC)
 #include "OCCIncludes.h"
 #include "GModelIO_OCC.h"
@@ -1571,6 +1581,18 @@ GEntity *OCCFactory::addPipe(GModel *gm, GEntity *base, std::vector<GEdge *> wir
   return ret;
 }
 
+void OCCFactory::healGeometry(GModel *gm, double tolerance)
+{
+  if (tolerance < 0.)
+    tolerance = CTX::instance()->geom.tolerance;
+  if (!gm || !gm->_occ_internals)
+    return;
+  //gm->_occ_internals->healGeometry(tolerance, false, false, false, true, false, false);
+  gm->_occ_internals->healGeometry(tolerance, true, true, true, true, true, true);
+  gm->_occ_internals->buildLists();
+  gm->_occ_internals->buildGModel(gm);
+}
+
 //Prepare SGEOM integration
 #if defined(HAVE_SGEOM) && defined(HAVE_OCC)
 
@@ -1610,6 +1632,12 @@ GRegion* SGEOMFactory::addVolume(GModel *gm, std::vector<std::vector<GFace *> >
   return 0;
 }
 
+void SGEOMFactory::healGeometry(GModel *gm, double tolerance)
+{
+  Msg::Error("healGeometry not implemented yet for SGEOMFactory");
+  return 0;
+}
+
 #endif
 
 #endif
diff --git a/Geo/GModelFactory.h b/Geo/GModelFactory.h
index ba9aa2b6a4..ffab382cc8 100644
--- a/Geo/GModelFactory.h
+++ b/Geo/GModelFactory.h
@@ -217,6 +217,8 @@ class GModelFactory {
     Msg::Error("setPhysicalNumToEntitiesInBox not implemented yet");
   }
 
+  virtual void healGeometry(GModel *gm, double tolerance = -1.) = 0;
+
 };
 
 class GeoFactory : public GModelFactory {
@@ -230,6 +232,7 @@ class GeoFactory : public GModelFactory {
   std::vector<GFace *> addRuledFaces(GModel *gm, std::vector<std::vector<GEdge *> > edges);
   std::vector<GEntity*> extrudeBoundaryLayer(GModel *gm, GEntity *e, int nbLayers,
                                              double hLayers, int dir, int view);
+  void healGeometry(GModel *gm, double tolerance = -1.);
 };
 
 #if defined(HAVE_OCC)
@@ -288,6 +291,7 @@ class OCCFactory : public GModelFactory {
                                      std::vector<double> p1, std::vector<double> p2);
 
   void fillet(GModel *gm, std::vector<int> edges, double radius);
+  void healGeometry(GModel *gm, double tolerance = -1.);
 };
 
 #endif
@@ -301,6 +305,7 @@ class SGEOMFactory : public GModelFactory {
   GEdge *addLine(GModel *gm,GVertex *v1, GVertex *v2);
   GFace *addPlanarFace(GModel *gm, std::vector<std::vector<GEdge *> > edges);
   GRegion *addVolume(GModel *gm, std::vector<std::vector<GFace *> > faces);
+  void healGeometry(GModel *gm, double tolerance = -1.);
 };
 
 #endif
diff --git a/Geo/Geo.cpp b/Geo/Geo.cpp
index 54d6c7a611..ee81b72af3 100644
--- a/Geo/Geo.cpp
+++ b/Geo/Geo.cpp
@@ -2356,11 +2356,11 @@ static void MaxNumSurface(void *a, void *b)
     std::max(GModel::current()->getGEOInternals()->MaxSurfaceNum, s->Num);
 }
 
-static void ReplaceDuplicatePointsNew()
+static void ReplaceDuplicatePointsNew(double tol = -1.)
 {
   Msg::Info("New Coherence...");
-
-  double tol = CTX::instance()->geom.tolerance * CTX::instance()->lc;
+  if (tol < 0) 
+    tol = CTX::instance()->geom.tolerance * CTX::instance()->lc;
 
   // create kdtree
   std::map<MVertex*, Vertex*> v2V;
@@ -2927,6 +2927,15 @@ void ReplaceAllDuplicates()
   ReplaceAllDuplicates(report);
 }
 
+void ReplaceAllDuplicatesNew(double tol)
+{
+  if (tol < 0) 
+    tol = CTX::instance()->geom.tolerance * CTX::instance()->lc;
+  ReplaceDuplicatePointsNew(tol);
+  ReplaceDuplicateCurves(NULL);
+  ReplaceDuplicateSurfaces(NULL);
+}
+
 // Extrusion routines
 
 void ProtudeXYZ(double &x, double &y, double &z, ExtrudeParams *e)
diff --git a/Geo/Geo.h b/Geo/Geo.h
index 4097c296c0..f11a0edfd0 100644
--- a/Geo/Geo.h
+++ b/Geo/Geo.h
@@ -392,6 +392,7 @@ int Extrude_ProtudeSurface(int type, int is,
 void ProtudeXYZ(double &x, double &y, double &z, ExtrudeParams *e);
 
 void ReplaceAllDuplicates();
+void ReplaceAllDuplicatesNew(double tol = -1.);
 
 bool ProjectPointOnSurface(Surface *s, Vertex &p, double uv[2]);
 
-- 
GitLab