From 12872f82439aff0915f9a8a0841a776cecd96dc1 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Fri, 27 Oct 2017 08:27:27 +0200
Subject: [PATCH] - create compounds when doing transformations (translate,
 rotate, ...) so that we don't duplicate internal boundaries - reset STL
 parameters to previous values

---
 Geo/GModelIO_OCC.cpp | 90 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 69 insertions(+), 21 deletions(-)

diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp
index 721f93e868..b7787b4b20 100644
--- a/Geo/GModelIO_OCC.cpp
+++ b/Geo/GModelIO_OCC.cpp
@@ -2380,40 +2380,88 @@ bool OCC_Internals::booleanFragments(int tag,
                          outDimTags, outDimTagsMap, removeObject, removeTool);
 }
 
+void _addSimpleShapes(TopoDS_Shape shape, std::vector<TopoDS_Shape> &simple)
+{
+  if(shape.ShapeType() != TopAbs_COMPOUND &&
+     shape.ShapeType() != TopAbs_COMPSOLID) {
+    simple.push_back(shape);
+    return;
+  }
+
+  TopTools_MapOfShape mapShape;
+  TopoDS_Iterator It(shape, Standard_True, Standard_True);
+
+  for(; It.More(); It.Next()) {
+    TopoDS_Shape s = It.Value();
+    if(mapShape.Add(s)) {
+      if(s.ShapeType() == TopAbs_COMPOUND ||
+         s.ShapeType() == TopAbs_COMPSOLID) {
+        _addSimpleShapes(s, simple);
+      }
+      else {
+        simple.push_back(s);
+      }
+    }
+  }
+}
+
 bool OCC_Internals::_transform(const std::vector<std::pair<int, int> > &inDimTags,
                                BRepBuilderAPI_Transform *tfo,
                                BRepBuilderAPI_GTransform *gtfo)
 {
+  // build a single compound shape, so that we won't duplicate internal
+  // boundaries
+  BRep_Builder b;
+  TopoDS_Compound c;
+  b.MakeCompound(c);
   for(unsigned int i = 0; i < inDimTags.size(); i++){
     int dim = inDimTags[i].first;
     int tag = inDimTags[i].second;
     if(!_isBound(dim, tag)){
-      Msg::Error("Unknown OpenCASCADE entity of dimension %d with tag %d",
-                 dim, tag);
+      Msg::Error("Unknown OpenCASCADE entity of dimension %d with tag %d", dim, tag);
       return false;
     }
-    TopoDS_Shape object = _find(dim, tag), result;
-    if(tfo){
-      tfo->Perform(object, Standard_False);
-      if(!tfo->IsDone()){
-        Msg::Error("Could not apply transformation");
-        return false;
-      }
-      result = tfo->Shape();
+    TopoDS_Shape shape = _find(dim, tag);
+    b.Add(c, shape);
+  }
+
+  std::vector<TopoDS_Shape> inShapes;
+  _addSimpleShapes(c, inShapes);
+
+  TopoDS_Shape result;
+  if(tfo){
+    tfo->Perform(c, Standard_False);
+    if(!tfo->IsDone()){
+      Msg::Error("Could not apply transformation");
+      return false;
     }
-    else if(gtfo){
-      gtfo->Perform(object, Standard_False);
-      if(!gtfo->IsDone()){
-        Msg::Error("Could not apply transformation");
-        return false;
-      }
-      result = gtfo->Shape();
+    result = tfo->Shape();
+  }
+  else if(gtfo){
+    gtfo->Perform(c, Standard_False);
+    if(!gtfo->IsDone()){
+      Msg::Error("Could not apply transformation");
+      return false;
     }
+    result = gtfo->Shape();
+  }
+
+  std::vector<TopoDS_Shape> outShapes;
+  _addSimpleShapes(result, outShapes);
+
+  if(inShapes.size() != inDimTags.size() || inShapes.size() != outShapes.size()){
+    Msg::Error("OpenCASCADE transform changed the number of shapes");
+    return false;
+  }
+  for(unsigned int i = 0; i < inDimTags.size(); i++){
     // FIXME we should implement rebind(object, result, dim) which would
     // unbind/bind all subshapes to the same tags
-    unbind(object, dim, tag, true);
-    bind(result, dim, tag, true);
+    int dim = inDimTags[i].first;
+    int tag = inDimTags[i].second;
+    unbind(inShapes[i], dim, tag, true);
+    bind(outShapes[i], dim, tag, true);
   }
+
   return true;
 }
 
@@ -3350,8 +3398,8 @@ bool OCC_Internals::_makeFaceSTL(TopoDS_Face s,
 #if (OCC_VERSION_MAJOR >= 7)
   BRepMesh_FastDiscret::Parameters parameters;
   parameters.Deflection = 0.1;
-  parameters.Angle = 0.1;
-  //  parameters.InternalVerticesMode = Standard_False;
+  parameters.Angle = 0.35;
+  // parameters.InternalVerticesMode = Standard_False;
   parameters.Relative = Standard_False;
   BRepMesh_FastDiscret aMesher(aBox, parameters);
 #else
-- 
GitLab