diff --git a/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx b/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx index 9dbbb7ea9a..22cf8959fc 100644 --- a/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx +++ b/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx @@ -1288,8 +1288,9 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c { if (n < 3) { - di << "Use unifysamedom result shape [-f] [-e] [+b] [-i] [-t val] [-a val]\n"; + di << "Use unifysamedom result shape [s1 s2 ...] [-f] [-e] [+b] [+i] [-t val] [-a val]\n"; di << "options:\n"; + di << "s1 s2 ... to keep the given edges during unification of faces\n"; di << "-f to switch off 'unify-faces' mode \n"; di << "-e to switch off 'unify-edges' mode\n"; di << "+b to switch on 'concat bspline' mode\n"; @@ -1311,33 +1312,42 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c Standard_Boolean isAllowInternal = Standard_False; Standard_Real aLinTol = Precision::Confusion(); Standard_Real aAngTol = Precision::Angular(); + TopoDS_Shape aKeepShape; + TopTools_MapOfShape aMapOfShapes; if (n > 3) for ( int i = 3; i < n; i++ ) { - if ( !strcmp(a[i], "-f")) - anUFaces = Standard_False; - else if (!strcmp(a[i], "-e")) - anUEdges = Standard_False; - else if (!strcmp(a[i], "+b")) - anConBS = Standard_True; - else if (!strcmp(a[i], "+i")) - isAllowInternal = Standard_True; - else if (!strcmp(a[i], "-t") || !strcmp(a[i], "-a")) - { - if (++i < n) + aKeepShape = DBRep::Get(a[i]); + if (!aKeepShape.IsNull()) { + aMapOfShapes.Add(aKeepShape); + } + else { + if ( !strcmp(a[i], "-f")) + anUFaces = Standard_False; + else if (!strcmp(a[i], "-e")) + anUEdges = Standard_False; + else if (!strcmp(a[i], "+b")) + anConBS = Standard_True; + else if (!strcmp(a[i], "+i")) + isAllowInternal = Standard_True; + else if (!strcmp(a[i], "-t") || !strcmp(a[i], "-a")) { - (a[i-1][1] == 't' ? aLinTol : aAngTol) = Draw::Atof(a[i]); - } - else - { - di << "value expected after " << a[i-1]; - return 1; + if (++i < n) + { + (a[i-1][1] == 't' ? aLinTol : aAngTol) = Draw::Atof(a[i]); + } + else + { + di << "value expected after " << a[i-1]; + return 1; + } } } } Unifier().Initialize(aShape, anUEdges, anUFaces, anConBS); + Unifier().KeepShapes(aMapOfShapes); Unifier().AllowInternalEdges(isAllowInternal); Unifier().SetLinearTolerance(aLinTol); Unifier().SetAngularTolerance(aAngTol); @@ -1576,7 +1586,7 @@ Standard_Integer reshape(Draw_Interpretor& di, theCommands.Add ("removeloc","result shape [remove_level(see ShapeEnum)]",__FILE__,removeloc,g); theCommands.Add ("unifysamedom", - "unifysamedom result shape [-f] [-e] [+b] [-i] [-t val] [-a val]", __FILE__,unifysamedom,g); + "unifysamedom result shape [s1 s2 ...] [-f] [-e] [+b] [+i] [-t val] [-a val]", __FILE__,unifysamedom,g); theCommands.Add ("unifysamedomgen", "unifysamedomgen newshape oldshape : get new shape generated " diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx index adb252ff42..18f2c61ce4 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx @@ -221,7 +221,7 @@ static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges, } } - //add edges to the sequemce + //add edges to the sequence for (i = 1; i <= aNewEdges.Extent(); i++) edges.Append(aNewEdges(i)); @@ -857,10 +857,10 @@ static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& aChain, Topo //======================================================================= static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, - double Tol, const TopTools_MapOfShape& DegEdgeVrt) + double Tol, const TopTools_MapOfShape& AvoidEdgeVrt) { TopoDS_Vertex CV = TopExp::LastVertex(edge1, Standard_True); - if (CV.IsNull() || DegEdgeVrt.Contains(CV)) + if (CV.IsNull() || AvoidEdgeVrt.Contains(CV)) return Standard_False; BRepAdaptor_Curve ade1(edge1); @@ -911,7 +911,7 @@ static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq, NCollection_Sequence& SeqOfSubSeqOfEdges, - Standard_Boolean IsClosed, double Tol, const TopTools_MapOfShape& DegEdgeVrt ) + Standard_Boolean IsClosed, double Tol, const TopTools_MapOfShape& AvoidEdgeVrt) { Standard_Boolean isOk = Standard_False; TopoDS_Edge edge1, edge2; @@ -924,7 +924,7 @@ static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq, { edge1 = TopoDS::Edge(anInpEdgeSeq(i)); edge2 = TopoDS::Edge(anInpEdgeSeq(i+1)); - isOk = IsMergingPossible(edge1, edge2, Tol, DegEdgeVrt); + isOk = IsMergingPossible(edge1, edge2, Tol, AvoidEdgeVrt); if (!isOk) { SubSequenceOfEdges aSubSeq; @@ -939,7 +939,7 @@ static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq, { edge1 = TopoDS::Edge(anInpEdgeSeq.Last()); edge2 = TopoDS::Edge(anInpEdgeSeq.First()); - if (IsMergingPossible(edge1, edge2, Tol, DegEdgeVrt)) + if (IsMergingPossible(edge1, edge2, Tol, AvoidEdgeVrt)) { SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(SeqOfSubSeqOfEdges.ChangeFirst().SeqsEdges); SeqOfSubSeqOfEdges.Remove(1); @@ -947,7 +947,6 @@ static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq, } } - //======================================================================= //function : MergeEdges //purpose : auxilary @@ -956,7 +955,7 @@ static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges, const Standard_Real Tol, const Standard_Boolean ConcatBSplines, NCollection_Sequence& SeqOfSubSeqOfEdges, - const TopTools_MapOfShape& NonMergVrt ) + const TopTools_MapOfShape& NonMergVrt) { // skip degenerated edges, and forbid merging through them TopTools_IndexedDataMapOfShapeListOfShape aMapVE; @@ -1086,7 +1085,6 @@ static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges, const TopTools_DataMapOfShapeShape& NewEdges2OldEdges) { NCollection_Sequence SeqOfSubsSeqOfEdges; - int k = 1; if ( MergeEdges(SeqEdges, Tol, ConcatBSplines, SeqOfSubsSeqOfEdges, nonMergVert) ) { for (Standard_Integer i = 1; i <= SeqOfSubsSeqOfEdges.Length(); i++ ) @@ -1094,7 +1092,6 @@ static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges, if (SeqOfSubsSeqOfEdges(i).UnionEdges.IsNull()) continue; theContext->Replace(SeqOfSubsSeqOfEdges(i).SeqsEdges(1), SeqOfSubsSeqOfEdges(i).UnionEdges); - k++; for (Standard_Integer j = 2; j <= SeqOfSubsSeqOfEdges(i).SeqsEdges.Length(); j++) { const TopoDS_Shape& anOldEdge = SeqOfSubsSeqOfEdges(i).SeqsEdges(j); @@ -1118,6 +1115,7 @@ static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges, static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, const TopTools_IndexedDataMapOfShapeListOfShape& theMapEdgesVertex, + const TopTools_MapOfShape& theMapKeepShape, TopTools_MapOfShape& theShareVertMap) { ShapeAnalysis_Edge sae; @@ -1140,7 +1138,7 @@ static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, TopTools_ListIteratorOfListOfShape iter(ListEdgesV1); for (; iter.More(); iter.Next()) aMapOfEdges.Add(iter.Value()); - if (aMapOfEdges.Extent() > 2) + if (aMapOfEdges.Extent() > 2 || theMapKeepShape.Contains(SeqVertexes(k))) theShareVertMap.Add(SeqVertexes(k)); } //return theShareVertMap.IsEmpty() ? false : true; @@ -1201,6 +1199,7 @@ void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape, myContext->Clear(); myOldShapes.Clear(); + myKeepShapes.Clear(); } //======================================================================= @@ -1213,6 +1212,30 @@ void ShapeUpgrade_UnifySameDomain::AllowInternalEdges (const Standard_Boolean th myAllowInternal = theValue; } +//======================================================================= +//function : KeepShape +//purpose : +//======================================================================= + +void ShapeUpgrade_UnifySameDomain::KeepShape(const TopoDS_Shape& theShape) +{ + if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_VERTEX) + myKeepShapes.Add(theShape); +} + +//======================================================================= +//function : KeepShapes +//purpose : +//======================================================================= + +void ShapeUpgrade_UnifySameDomain::KeepShapes(const TopTools_MapOfShape& theShapes) +{ + for (TopTools_MapIteratorOfMapOfShape it(theShapes); it.More(); it.Next()) { + if (it.Value().ShapeType() == TopAbs_EDGE || it.Value().ShapeType() == TopAbs_VERTEX) + myKeepShapes.Add(it.Value()); + } +} + //======================================================================= //function : putIntWires //purpose : Add internal wires that are classified inside the face as a subshape, @@ -1329,7 +1352,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape // get connectivity of the edge in the global shape const TopTools_ListOfShape& aGList = theGMapEdgeFaces.FindFromKey(edge); - if (!myAllowInternal && aGList.Extent() != 2) { + if (!myAllowInternal && (aGList.Extent() != 2 || myKeepShapes.Contains(edge))) { // non mainfold case is not processed unless myAllowInternal continue; } @@ -1402,57 +1425,84 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF); } - // Collect multiconnected edges, i.e. edges that are internal to + // Collect keep edges and multiconnected edges, i.e. edges that are internal to // the set of selected faces and have connections to other faces. - TopTools_ListOfShape aMultEdges; + TopTools_ListOfShape aKeepEdges; 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 = theGMapEdgeFaces.FindFromKey(aE); - if (aGLF.Extent() > 2) { - aMultEdges.Append(aE); + if (aGLF.Extent() > 2 || myKeepShapes.Contains(aE)) { + aKeepEdges.Append(aE); } } - } - if (!aMultEdges.IsEmpty()) { - if (!myAllowInternal) { - // Remove from the selection the faces containing multiconnected edges + } + if (!aKeepEdges.IsEmpty()) { + if (!myAllowInternal) { + // Remove from the selection the faces which have no other connect edges + // and contain multiconnected edges and/or keep edges. TopTools_MapOfShape anAvoidFaces; - TopTools_ListIteratorOfListOfShape it(aMultEdges); + TopTools_ListIteratorOfListOfShape it(aKeepEdges); 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(); ) { + for (i = 1; i <= faces.Length(); i++) { if (anAvoidFaces.Contains(faces(i))) { // update the boundaries of merged area, for that // remove from 'edges' the edges of this face and add to 'edges' // the edges of this face that were not present in 'edges' before + Standard_Boolean hasConnectAnotherFaces = Standard_False; TopExp_Explorer ex(faces(i), TopAbs_EDGE); - for (; ex.More(); ex.Next()) { + for (; ex.More() && !hasConnectAnotherFaces; ex.Next()) { TopoDS_Shape aE = ex.Current(); - Standard_Integer j; - for (j = 1; j <= edges.Length(); j++) { - if (edges(j).IsSame(aE)) - break; + const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); + if (aLF.Extent() > 1) { + for (it.Init(aLF); it.More() && !hasConnectAnotherFaces; it.Next()) { + if (!anAvoidFaces.Contains(it.Value())) + hasConnectAnotherFaces = Standard_True; + } + } + } + if (!hasConnectAnotherFaces) { + AddOrdinaryEdges(edges, faces(i), dummy); + faces.Remove(i); + i--; + } + } + } + // check if the faces with keep edges contained in + // already updated the boundaries of merged area + if (!faces.IsEmpty()) { + TopTools_MapOfShape aMapFaces; + for (i = 1; i <= faces.Length(); i++) { + aMapFaces.Add(faces(i)); + } + for (it.Init(aKeepEdges); it.More(); it.Next()) { + const TopoDS_Shape& aE = it.Value(); + const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); + if (aLF.Extent() < 2) + continue; + if (aMapFaces.Contains(aLF.First()) && + aMapFaces.Contains(aLF.Last())) { + for (i = 1; i <= faces.Length(); i++) { + if (faces(i).IsEqual(aLF.First()) || + faces(i).IsEqual(aLF.Last())) { + AddOrdinaryEdges(edges, faces(i), dummy); + faces.Remove(i); + i--; + } } - if (j <= edges.Length()) - edges.Remove(j); - else - edges.Append(aE); } - faces.Remove(i); } - else - i++; } } else { - // add multiconnected edges as internal in new face - TopTools_ListIteratorOfListOfShape it(aMultEdges); + // add multiconnected and keep edges as internal in new face + TopTools_ListIteratorOfListOfShape it(aKeepEdges); for (; it.More(); it.Next()) { const TopoDS_Shape& aE = it.Value(); edges.Append(aE.Oriented(TopAbs_INTERNAL)); @@ -1812,8 +1862,9 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges() for (; expE.More(); expE.Next()) SeqEdges.Append(expE.Current()); SharedVert.Clear(); - CheckSharedVertices(SeqEdges, aMapEdgesVertex, SharedVert); - MergeSeq(SeqEdges, Tol, myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges); + CheckSharedVertices(SeqEdges, aMapEdgesVertex, myKeepShapes, SharedVert); + MergeSeq(SeqEdges, Tol, myConcatBSplines, myContext, + myOldShapes, SharedVert, NewEdges2OldEdges); } TopTools_DataMapOfShapeShape oldFaces2NewFaces; @@ -1870,10 +1921,11 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges() continue; SharedVert.Clear(); - CheckSharedVertices(SeqEdges, aMapEdgesVertex, SharedVert); + CheckSharedVertices(SeqEdges, aMapEdgesVertex, myKeepShapes, SharedVert); //if (!SharedVert.IsEmpty()) // continue; - if ( MergeSeq(SeqEdges,Tol,myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges) ) + if ( MergeSeq(SeqEdges, Tol, myConcatBSplines, myContext, + myOldShapes, SharedVert, NewEdges2OldEdges) ) { //for history /* @@ -1902,8 +1954,9 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges() if ( aNonSharedEdges.Length() > 1 ) { SharedVert.Clear(); - CheckSharedVertices(aNonSharedEdges, aMapEdgesVertex, SharedVert); - if ( MergeSeq(aNonSharedEdges, Tol, myConcatBSplines, myContext, myOldShapes, SharedVert, NewEdges2OldEdges) ) + CheckSharedVertices(aNonSharedEdges, aMapEdgesVertex, myKeepShapes, SharedVert); + if ( MergeSeq(aNonSharedEdges, Tol, myConcatBSplines, myContext, + myOldShapes, SharedVert, NewEdges2OldEdges) ) { TopoDS_Face tmpF = TopoDS::Face(exp.Current()); if ( !ChangedFaces.Contains(tmpF) ) diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx index 8286e9215d..0206b467fc 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx @@ -25,6 +25,7 @@ #include #include #include +#include class ShapeBuild_ReShape; class TopoDS_Shape; @@ -63,6 +64,18 @@ public: //! is forbidden. Default value is false. Standard_EXPORT void AllowInternalEdges (const Standard_Boolean theValue); + //! Sets the shape for avoid merging of the faces in given places. + //! This shape can be vertex or edge. + //! If shape is vertex it forbids merging of connected edges. + //! If shape is edge it forbids merging of connected faces. + Standard_EXPORT void KeepShape(const TopoDS_Shape& theShape); + + //! Sets the map of shapes for avoid merging of the faces in given places + //! These shapes can be vertexes or edges. + //! If shape is vertex it forbids merging of connected edges. + //! If shape is edge it forbids merging of connected faces. + Standard_EXPORT void KeepShapes(const TopTools_MapOfShape& theShapes); + //! Sets the linear tolerance. Default value is Precision::Confusion(). void SetLinearTolerance(const Standard_Real theValue) { @@ -120,7 +133,8 @@ private: Standard_Boolean myAllowInternal; TopoDS_Shape myShape; Handle(ShapeBuild_ReShape) myContext; - TopTools_DataMapOfShapeShape myOldShapes; + TopTools_DataMapOfShapeShape myOldShapes; + TopTools_MapOfShape myKeepShapes; }; diff --git a/tests/heal/grids.list b/tests/heal/grids.list index 70e7179bc5..929f032428 100644 --- a/tests/heal/grids.list +++ b/tests/heal/grids.list @@ -20,3 +20,4 @@ 020 wire_tails_composed 021 wire_tails_real 022 reshape +023 unify_same_domain diff --git a/tests/heal/unify_same_domain/A1 b/tests/heal/unify_same_domain/A1 new file mode 100644 index 0000000000..f09b116f60 --- /dev/null +++ b/tests/heal/unify_same_domain/A1 @@ -0,0 +1,33 @@ +puts "==========" +puts "OCC28228" +puts "==========" +puts "" +###################################################################################################################### +# Provide possibility to keep the given edges during unification of faces in ShapeUpgrade_UnifySameDomain algorithm +###################################################################################################################### + +restore [locate_data_file bug28228_face.brep] a + +explode a f +explode a_1 v +explode a e + +unifysamedom result1 a a_1_3 a_1_5 +checknbshapes result1 -face 1 -edge 10 -vertex 10 + +unifysamedom result2 a a_3 a_9 +checknbshapes result2 -face 3 -edge 14 -vertex 12 + +unifysamedom result3 a a_3 a_9 a_1_9 a_1_10 +checknbshapes result3 -face 3 -edge 15 -vertex 13 + +unifysamedom result4 a a_3 a_1_3 a_1_4 +checknbshapes result4 -face 2 -edge 12 -vertex 11 + +unifysamedom result5 a a_3 a_1_3 +checknbshapes result5 -face 2 -edge 11 -vertex 10 + +unifysamedom result a a_3 a_9 +i +checknbshapes result -face 1 -edge 12 -vertex 12 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/heal/unify_same_domain/A2 b/tests/heal/unify_same_domain/A2 new file mode 100644 index 0000000000..6b8b3ee8e4 --- /dev/null +++ b/tests/heal/unify_same_domain/A2 @@ -0,0 +1,19 @@ +puts "==========" +puts "OCC28228" +puts "==========" +puts "" +###################################################################################################################### +# Provide possibility to keep the given edges during unification of faces in ShapeUpgrade_UnifySameDomain algorithm +###################################################################################################################### + +restore [locate_data_file bug28228_face_circle.brep] a + +explode a e + +unifysamedom result1 a a_5 +checknbshapes result1 -face 3 -edge 9 -vertex 6 + +unifysamedom result a +checknbshapes result -face 1 -edge 2 -vertex 2 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/heal/unify_same_domain/A3 b/tests/heal/unify_same_domain/A3 new file mode 100644 index 0000000000..492ee61a14 --- /dev/null +++ b/tests/heal/unify_same_domain/A3 @@ -0,0 +1,16 @@ +puts "==========" +puts "OCC28228" +puts "==========" +puts "" +###################################################################################################################### +# Provide possibility to keep the given edges during unification of faces in ShapeUpgrade_UnifySameDomain algorithm +###################################################################################################################### + +restore [locate_data_file bug28228_unify_with_keep.brep] a + +explode a e + +unifysamedom result a a_13 +checknbshapes result -face 4 -edge 19 -vertex 16 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file