0027082: UnifySameDomain must add internal edges where appropriate to resolve self...
authormsv <msv@opencascade.com>
Tue, 22 Mar 2016 12:23:00 +0000 (15:23 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 8 Apr 2016 08:42:26 +0000 (11:42 +0300)
The new option AllowInternalEdges has been added in the class ShapeUpgrade_UnifySameDomain. It determines how the algorithm treats the situation when two faces can be merged together but they have connection with another face via the common edge.

With this option turned on, merging of such faces is not stopped, but the multiconnected edges are added to the merged face as INTERNAL edges.

By default it is false. In this mode such merging is forbidden, so the result shape will not contain any new INTERNAL edges.

The behavior of the algorithm has been changed so that it does not merge faces from different shells.

samples/tcl/snowflake.tcl
src/SWDRAW/SWDRAW_ShapeUpgrade.cxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx
tests/bugs/modalg_6/bug27082_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug27082_1i [new file with mode: 0644]
tests/bugs/modalg_6/bug27082_2 [new file with mode: 0644]
tests/bugs/modalg_6/bug27082_2i [new file with mode: 0644]
tests/bugs/modalg_6/bug27082_3 [new file with mode: 0644]
tests/bugs/modalg_6/bug27082_3i [new file with mode: 0644]

index d749e5e..a99bff5 100644 (file)
@@ -65,9 +65,6 @@ tcopy w w1
 tmirror w1 -6 0 0 0 1 0
 wire w w w1
 mkface w p w
-shape wsh Sh
-add w wsh
-renamevar wsh w
 donly w
 
 # construct complete snowflake
@@ -86,6 +83,10 @@ bfuse w w w2
 bfuse w w w3
 bfuse w w w4
 bfuse w w w5
+shape wsh Sh
+foreach f [explode w f] {add $f wsh}
+renamevar wsh w
+save w w.brep
 unifysamedom r w
 
 # keep only wires in compound
@@ -137,7 +138,7 @@ vfit
 
 # add dimension
 explode snowflake v
-vdimension length -length -shapes snowflake_64 snowflake_140 -plane xoy -value 0.001 -dispunits mm -showunits -flyout 70 -label above -color black -text 5 3d sh
+vdimension length -length -shapes snowflake_89 snowflake_15 -plane xoy -value 0.001 -dispunits mm -showunits -flyout 70 -label above -color black -text 5 3d sh
 
 if { [regexp HAVE_GL2PS [dversion]] } {
     puts "You can use command vexport to generate PDF: vexport your_file_path.pdf"
index c7a7e5a..a6fd1a9 100644 (file)
@@ -69,7 +69,7 @@
 #include <TopoDS_Shell.hxx>
 #include <TopoDS_Wire.hxx>
 
-#include <stdio.h>
+#include <stdio.h> 
 //#include <SWDRAW_ShapeUpgrade.hxx>
 //#include <ShapeUpgrade_SupportModification.hxx>
 //#include <ShapeExtend_WireData.hxx>
@@ -1285,11 +1285,12 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c
 {
   if (n < 3 || n > 6)
   {
-    di << "Use unifysamedom result shape [-f] [-e] [+b]\n";
-    di << "where [-f]. [-e], [+b] is available options\n";
+    di << "Use unifysamedom result shape [-f] [-e] [+b] [-i]\n";
+    di << "options:\n";
     di << "[-f] to switch off 'unify-faces' mode \n";
     di << "[-e] to switch off 'unify-edges' mode\n";
-    di << "[+b] to switch on a 'concat bspline' mode\n";
+    di << "[+b] to switch on 'concat bspline' mode\n";
+    di << "[+i] to switch on 'allow internal edges' mode\n";
     di << "'unify-faces' and 'unify-edges' modes are switched on by default";
     return 1;
   }
@@ -1302,6 +1303,7 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c
   Standard_Boolean anUFaces = Standard_True;
   Standard_Boolean anUEdges = Standard_True;
   Standard_Boolean anConBS = Standard_False;
+  Standard_Boolean isAllowInternal = Standard_False;
 
   if (n > 3)
     for ( int i = 3; i < n; i++ ) 
@@ -1312,9 +1314,12 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c
         anUEdges = Standard_False;
       else if (!strcmp(a[i], "+b"))
         anConBS = Standard_True;
+      else if (!strcmp(a[i], "+i"))
+        isAllowInternal = Standard_True;
     }
 
   Unifier().Initialize(aShape, anUEdges, anUFaces, anConBS);
+  Unifier().AllowInternalEdges(isAllowInternal);
   Unifier().Build();
   TopoDS_Shape Result = Unifier().Shape();
 
@@ -1470,7 +1475,7 @@ static Standard_Integer copytranslate(Draw_Interpretor& di,
   
   theCommands.Add ("unifysamedom",
                    "unifysamedom result shape [-f] [-e] [+b]", __FILE__,unifysamedom,g);
-
+  
   theCommands.Add ("unifysamedomgen",
                    "unifysamedomgen newshape oldshape : get new shape generated "
                    "by unifysamedom command from the old one",
index 51e6f55..7181894 100644 (file)
@@ -641,11 +641,11 @@ static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& aChain, Topo
       }
       if (Abs(FP) < Precision::PConfusion())
       {
-        B.MakeEdge (E,Cir, Precision::Confusion());
-        B.Add(E,V1);
-        B.Add(E,V2);
-        E.Orientation(FE.Orientation());
-      }
+      B.MakeEdge (E,Cir,Precision::Confusion());
+      B.Add(E,V1);
+      B.Add(E,V2);
+      E.Orientation(FE.Orientation());
+    }
       else
       {
         GC_MakeCircle MC1 (adef.Value(FP), adef.Value((FP + LP) * 0.5), adef.Value(LP));
@@ -988,11 +988,11 @@ static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges,
 //=======================================================================
 
 ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain()
+  : myUnifyFaces (Standard_True),
+    myUnifyEdges (Standard_True),
+    myConcatBSplines (Standard_False),
+    myAllowInternal (Standard_False)
 {
-  myUnifyEdges = Standard_True;
-  myUnifyFaces = Standard_True;
-  myConcatBSplines = Standard_False;
-
   myContext = new ShapeBuild_ReShape;
 }
 
@@ -1005,13 +1005,13 @@ ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& a
                                                            const Standard_Boolean UnifyEdges,
                                                            const Standard_Boolean UnifyFaces,
                                                            const Standard_Boolean ConcatBSplines)
+  : myInitShape (aShape),
+    myUnifyFaces (UnifyFaces),
+    myUnifyEdges (UnifyEdges),
+    myConcatBSplines (ConcatBSplines),
+    myAllowInternal (Standard_False),
+    myShape (aShape)
 {
-  myInitShape = aShape;
-  myShape = aShape;
-  myUnifyEdges = UnifyEdges;
-  myUnifyFaces = UnifyFaces;
-  myConcatBSplines = ConcatBSplines;
-
   myContext = new ShapeBuild_ReShape;
 }
 
@@ -1033,7 +1033,16 @@ void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape,
 
   myContext->Clear();
   myOldShapes.Clear();
-  //myGenerated.Clear();
+}
+
+//=======================================================================
+//function : AllowInternalEdges
+//purpose  : 
+//=======================================================================
+
+void ShapeUpgrade_UnifySameDomain::AllowInternalEdges (const Standard_Boolean theValue)
+{
+  myAllowInternal = theValue;
 }
 
 //=======================================================================
@@ -1074,14 +1083,19 @@ static void putIntWires(TopoDS_Shape& theFace, TopTools_SequenceOfShape& theWire
 
 void ShapeUpgrade_UnifySameDomain::UnifyFaces()
 {
-  // creating map of edge faces
-  TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
-  TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
+  // creating map of edge faces for the whole shape
+  TopTools_IndexedDataMapOfShapeListOfShape aGMapEdgeFaces;
+  TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces);
+
   // processing each shell
   TopExp_Explorer exps;
   for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) {
     TopoDS_Shell aShell = TopoDS::Shell(exps.Current());
 
+    // creating map of edge faces for the shell
+    TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
+    TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);
+
     // map of processed shapes
     TopTools_MapOfShape aProcessed;
 
@@ -1125,6 +1139,13 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
         if (BRep_Tool::Degenerated(edge))
           continue;
 
+        // get connectivity of the edge in the global shape
+        const TopTools_ListOfShape& aGList = aGMapEdgeFaces.FindFromKey(edge);
+        if (!myAllowInternal && aGList.Extent() != 2) {
+          // non mainfold case is not processed unless myAllowInternal
+          continue;
+        }
+        // process faces connected through the edge in the current shell
         const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
         TopTools_ListIteratorOfListOfShape anIter(aList);
         for (; anIter.More(); anIter.Next()) {
@@ -1137,11 +1158,6 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
 
           if (IsSameDomain(aFace,anCheckedFace)) {
 
-            if (aList.Extent() != 2) {
-              // non mainfold case is not processed
-              continue;
-            }
-
             // replacing pcurves
             TopoDS_Face aMockUpFace;
             BRep_Builder B;
@@ -1160,6 +1176,55 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
         }
       }
 
+      if (faces.Length() > 1) {
+        // fill in the connectivity map for selected faces
+        TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+        for (i = 1; i <= faces.Length(); i++) {
+          TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
+        }
+
+        // Collect multiconnected edges, i.e. edges that are internal to
+        // the set of selected faces and have connections to other faces.
+        TopTools_ListOfShape aMultEdges;
+        for (i = 1; i <= aMapEF.Extent(); i++) {
+          const TopTools_ListOfShape& aLF = aMapEF(i);
+          if (aLF.Extent() == 2) {
+            const TopoDS_Shape& aE = aMapEF.FindKey(i);
+            const TopTools_ListOfShape& aGLF = aGMapEdgeFaces.FindFromKey(aE);
+            if (aGLF.Extent() > 2) {
+              aMultEdges.Append(aE);
+            }
+          }
+        }
+        if (!aMultEdges.IsEmpty()) {
+          if (!myAllowInternal) {
+            // Remove from the selection the faces containing multiconnected edges
+            TopTools_MapOfShape anAvoidFaces;
+            TopTools_ListIteratorOfListOfShape it(aMultEdges);
+            for (; it.More(); it.Next()) {
+              const TopoDS_Shape& aE = it.Value();
+              const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE);
+              anAvoidFaces.Add(aLF.First());
+              anAvoidFaces.Add(aLF.Last());
+            }
+            for (i = 1; i <= faces.Length(); ) {
+              if (anAvoidFaces.Contains(faces(i)))
+                faces.Remove(i);
+              else
+                i++;
+            }
+          }
+          else {
+            // add multiconnected edges as internal in new face
+            TopTools_ListIteratorOfListOfShape it(aMultEdges);
+            for (; it.More(); it.Next()) {
+              const TopoDS_Shape& aE = it.Value();
+              edges.Append(aE.Oriented(TopAbs_INTERNAL));
+            }
+          }
+        }
+      }
+
       // all faces collected in the sequence. Perform union of faces
       if (faces.Length() > 1) {
         NbModif++;
@@ -1359,11 +1424,11 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
             }
             else
             {
-            Handle(ShapeExtend_WireData) sbwd =
+              Handle(ShapeExtend_WireData) sbwd =
                 new ShapeExtend_WireData (aWire);
-            ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
-            wires.Append(seg);
-          }
+              ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
+              wires.Append(seg);
+            }
           }
 
           CompShell.DispatchWires ( parts,wires );
index 4fe4176..452a727 100644 (file)
@@ -56,6 +56,12 @@ public:
   //! Initializes with a shape
   Standard_EXPORT void Initialize (const TopoDS_Shape& aShape, const Standard_Boolean UnifyEdges = Standard_True, const Standard_Boolean UnifyFaces = Standard_True, const Standard_Boolean ConcatBSplines = Standard_False);
   
+  //! Sets the flag defining whether it is allowed to create
+  //! internal edges inside merged faces in the case of non-manifold
+  //! topology. Without this flag merging through multi connected edge
+  //! is forbidden. Default value is false.
+  Standard_EXPORT void AllowInternalEdges (const Standard_Boolean theValue);
+  
   //! Builds the resulting shape
   Standard_EXPORT void Build();
   
@@ -93,6 +99,7 @@ private:
   Standard_Boolean myUnifyFaces;
   Standard_Boolean myUnifyEdges;
   Standard_Boolean myConcatBSplines;
+  Standard_Boolean myAllowInternal;
   TopoDS_Shape myShape;
   Handle(ShapeBuild_ReShape) myContext;
   TopTools_DataMapOfShapeShape myOldShapes; 
diff --git a/tests/bugs/modalg_6/bug27082_1 b/tests/bugs/modalg_6/bug27082_1
new file mode 100644 (file)
index 0000000..a58a1a2
--- /dev/null
@@ -0,0 +1,18 @@
+puts "============"
+puts "OCC27082"
+puts "============"
+puts ""
+###############################
+## UnifySameDomain must add internal edges where appropriate to resolve self-intersections
+###############################
+
+restore [locate_data_file bug27082_shapes1.brep] a
+explode a
+bcut r1 a_1 a_3
+bfuse r2 r1 a_2
+unifysamedom result r2
+
+don result
+smallview; l; fit
+bopcheck result
+checknbshapes result -m UnifySameDomain -face 22 -edge 40
diff --git a/tests/bugs/modalg_6/bug27082_1i b/tests/bugs/modalg_6/bug27082_1i
new file mode 100644 (file)
index 0000000..0a0ff3b
--- /dev/null
@@ -0,0 +1,18 @@
+puts "============"
+puts "OCC27082"
+puts "============"
+puts ""
+###############################
+## UnifySameDomain must add internal edges where appropriate to resolve self-intersections
+###############################
+
+restore [locate_data_file bug27082_shapes1.brep] a
+explode a
+bcut r1 a_1 a_3
+bfuse r2 r1 a_2
+unifysamedom result r2 +i
+
+don result
+smallview; l; fit
+bopcheck result
+checknbshapes result -m UnifySameDomain -face 14 -edge 28
diff --git a/tests/bugs/modalg_6/bug27082_2 b/tests/bugs/modalg_6/bug27082_2
new file mode 100644 (file)
index 0000000..cbe7bc5
--- /dev/null
@@ -0,0 +1,17 @@
+puts "============"
+puts "OCC27082"
+puts "============"
+puts ""
+###############################
+## UnifySameDomain must add internal edges where appropriate to resolve self-intersections
+###############################
+
+restore [locate_data_file bug27082_shapes2.brep] a
+explode a
+bfuse r a_1 a_2
+unifysamedom result r
+
+don result
+smallview; l; fit
+bopcheck result
+checknbshapes result -m UnifySameDomain -face 37 -edge 94
diff --git a/tests/bugs/modalg_6/bug27082_2i b/tests/bugs/modalg_6/bug27082_2i
new file mode 100644 (file)
index 0000000..82ee825
--- /dev/null
@@ -0,0 +1,17 @@
+puts "============"
+puts "OCC27082"
+puts "============"
+puts ""
+###############################
+## UnifySameDomain must add internal edges where appropriate to resolve self-intersections
+###############################
+
+restore [locate_data_file bug27082_shapes2.brep] a
+explode a
+bfuse r a_1 a_2
+unifysamedom result r +i
+
+don result
+smallview; l; fit
+bopcheck result
+checknbshapes result -m UnifySameDomain -face 33 -edge 86
diff --git a/tests/bugs/modalg_6/bug27082_3 b/tests/bugs/modalg_6/bug27082_3
new file mode 100644 (file)
index 0000000..4728c05
--- /dev/null
@@ -0,0 +1,15 @@
+puts "============"
+puts "OCC27082"
+puts "============"
+puts ""
+###############################
+## UnifySameDomain must add internal edges where appropriate to resolve self-intersections
+###############################
+
+restore [locate_data_file bug27082_shapes3.brep] a
+unifysamedom result a
+
+don result
+smallview; l; fit
+bopcheck result
+checknbshapes result -m UnifySameDomain -face 249 -edge 600
diff --git a/tests/bugs/modalg_6/bug27082_3i b/tests/bugs/modalg_6/bug27082_3i
new file mode 100644 (file)
index 0000000..49d91b0
--- /dev/null
@@ -0,0 +1,15 @@
+puts "============"
+puts "OCC27082"
+puts "============"
+puts ""
+###############################
+## UnifySameDomain must add internal edges where appropriate to resolve self-intersections
+###############################
+
+restore [locate_data_file bug27082_shapes3.brep] a
+unifysamedom result a +i
+
+don result
+smallview; l; fit
+bopcheck result
+checknbshapes result -m UnifySameDomain -face 225 -edge 576