diff --git a/samples/tcl/snowflake.tcl b/samples/tcl/snowflake.tcl index d749e5edbc..a99bff5984 100644 --- a/samples/tcl/snowflake.tcl +++ b/samples/tcl/snowflake.tcl @@ -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" diff --git a/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx b/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx index c7a7e5a227..a6fd1a973b 100644 --- a/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx +++ b/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx @@ -69,7 +69,7 @@ #include #include -#include +#include //#include //#include //#include @@ -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", diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx index 51e6f55e6a..718189492a 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx @@ -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 ); diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx index 4fe417684c..452a727883 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx @@ -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 index 0000000000..a58a1a23ac --- /dev/null +++ b/tests/bugs/modalg_6/bug27082_1 @@ -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 index 0000000000..0a0ff3b888 --- /dev/null +++ b/tests/bugs/modalg_6/bug27082_1i @@ -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 index 0000000000..cbe7bc5d5a --- /dev/null +++ b/tests/bugs/modalg_6/bug27082_2 @@ -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 index 0000000000..82ee825b22 --- /dev/null +++ b/tests/bugs/modalg_6/bug27082_2i @@ -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 index 0000000000..4728c05a2e --- /dev/null +++ b/tests/bugs/modalg_6/bug27082_3 @@ -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 index 0000000000..49d91b0e32 --- /dev/null +++ b/tests/bugs/modalg_6/bug27082_3i @@ -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