From 46e68e02e33eab5783ec38fa2a8d509896169ddc Mon Sep 17 00:00:00 2001 From: skv Date: Fri, 21 Dec 2012 16:16:21 +0400 Subject: [PATCH] 0023606: Invalid result of pipe operation --- src/BRepFill/BRepFill_Pipe.cdl | 10 ++ src/BRepFill/BRepFill_Pipe.cxx | 307 ++++++++++++++++++++++++++++++++- tests/bugs/modalg/bug23606 | 19 ++ 3 files changed, 334 insertions(+), 2 deletions(-) create mode 100755 tests/bugs/modalg/bug23606 diff --git a/src/BRepFill/BRepFill_Pipe.cdl b/src/BRepFill/BRepFill_Pipe.cdl index 8d409e9b5b..a8a6da8626 100755 --- a/src/BRepFill/BRepFill_Pipe.cdl +++ b/src/BRepFill/BRepFill_Pipe.cdl @@ -150,6 +150,16 @@ is DefineRealSegmax(me : in out) is static private; + ShareFaces(me: in out; theShape: Shape from TopoDS; + theInitialFacesLen: Integer; + theInitialEdgesLen: Integer; + theInitialSectionsLen: Integer) + ---Purpose: Performs sharing coincident faces in theShape. Also modifies + -- myFaces, mySections and myEdges to contain shared shapes. + -- Returns the shared shape. If theShape is not modified this + -- method returns it. + returns Shape from TopoDS + is static private; fields mySpine : Wire from TopoDS; diff --git a/src/BRepFill/BRepFill_Pipe.cxx b/src/BRepFill/BRepFill_Pipe.cxx index 79859789e5..0016db44a5 100755 --- a/src/BRepFill/BRepFill_Pipe.cxx +++ b/src/BRepFill/BRepFill_Pipe.cxx @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,9 @@ #include #include #include +#include +#include +#include #include #include @@ -510,6 +514,9 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S, Handle(TopTools_HArray2OfShape) Aux, Somme; Standard_Integer length; Standard_Integer ii, jj, kk; + const Standard_Integer aNbFaces = myFaces->ColLength(); + const Standard_Integer aNbEdges = myEdges->ColLength(); + const Standard_Integer aNbSections = mySections->ColLength(); Aux = MkSw.SubShape(); length = Aux->ColLength() + myFaces->ColLength(); @@ -524,7 +531,6 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S, Somme->SetValue(ii, jj, Aux->Value(kk, jj)); } myFaces = Somme; - Aux = MkSw.Sections(); length = Aux->ColLength() + mySections->ColLength(); @@ -552,7 +558,11 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S, kk <=Aux->ColLength(); kk++, ii++) Somme->SetValue(ii, jj, Aux->Value(kk, jj)); } - myEdges = Somme; + + myEdges = Somme; + + // Perform sharing faces + result = ShareFaces(result, aNbFaces, aNbEdges, aNbSections); } } } @@ -765,3 +775,296 @@ void BRepFill_Pipe::DefineRealSegmax() if (mySegmax < RealSegmax) mySegmax = RealSegmax; } + +//======================================================================= +//function : ShareFaces +//purpose : +//======================================================================= + +TopoDS_Shape BRepFill_Pipe::ShareFaces + (const TopoDS_Shape &theShape, + const Standard_Integer theInitialFacesLen, + const Standard_Integer theInitialEdgesLen, + const Standard_Integer theInitialSectionsLen) +{ + TopoDS_Shape aResult = theShape; + // Check if there are shapes to be shared. + TopTools_DataMapOfShapeInteger aMapBndEdgeIndex; + TColStd_DataMapOfIntegerInteger aMapNewOldFIndex; + TColStd_DataMapOfIntegerInteger aMapNewOldEIndex; + TopTools_MapOfShape aMapUsedVtx; + TopExp_Explorer anExp; + Standard_Integer i; + Standard_Integer ii; + Standard_Integer jj; + BRep_Builder aBuilder; + + // Check the first and last J index of myFaces. + for (i = 1; i <= 2; i++) { + // Compute jj index of faces. + if (i == 1) { + jj = 1; + } else { + jj == myFaces->RowLength(); + + if (jj == 1) { + break; + } + } + + // Fill the map of boundary edges on initial faces. + for (ii = 1; ii <= theInitialFacesLen; ii++) { + anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE); + + for (; anExp.More(); anExp.Next()) { + if (aMapBndEdgeIndex.IsBound(anExp.Current())) { + // This is not boundary edge. Remove it. + aMapBndEdgeIndex.UnBind(anExp.Current()); + } else { + // Add boundary edge. + aMapBndEdgeIndex.Bind(anExp.Current(), ii); + } + } + } + + // Check if edges of newly created faces are shared with old ones. + for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) { + anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE); + + for (; anExp.More(); anExp.Next()) { + if (aMapBndEdgeIndex.IsBound(anExp.Current())) { + // This row should be replaced. + Standard_Integer anOldIndex = aMapBndEdgeIndex.Find(anExp.Current()); + + aMapNewOldFIndex.Bind(ii, anOldIndex); + + // Find corresponding new and old edges indices. + TopoDS_Vertex aV[2]; + TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV[0], aV[1]); + Standard_Integer ie; + Standard_Integer je; + Standard_Integer indV; + + // Compute jj index of edges. + if (i == 1) { + je = 1; + } else { + je == myEdges->RowLength(); + } + + Standard_Integer j; + + for (j = 0; j < 2; j++) { + if (aMapUsedVtx.Contains(aV[j])) { + // This vertex is treated. + continue; + } + + // Find old index. + Standard_Integer iEOld = -1; + TopoDS_Vertex aVE[2]; + + for (ie = 1; ie <= theInitialEdgesLen; ie++) { + const TopoDS_Shape &anEdge = myEdges->Value(ie, je); + + TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]); + + if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) { + iEOld = ie; + break; + } + } + + if (iEOld > 0) { + // Find new index. + for (ie = theInitialEdgesLen+1; ie <= myEdges->ColLength(); ie++) { + const TopoDS_Shape &anEdge = myEdges->Value(ie, je); + + TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]); + + if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) { + // This row should be replaced. + aMapNewOldEIndex.Bind(ie, iEOld); + aMapUsedVtx.Add(aV[j]); + break; + } + } + } + } + + break; + } + } + } + } + + if (!aMapNewOldFIndex.IsEmpty()) { + TColStd_DataMapIteratorOfDataMapOfIntegerInteger anIter(aMapNewOldFIndex); + TopTools_ListOfShape aListShape; + BRepTools_Substitution aSubstitute; + + for (; anIter.More(); anIter.Next()) { + const Standard_Integer aNewIndex = anIter.Key(); + const Standard_Integer anOldIndex = anIter.Value(); + + // Change new faces by old ones. + for (jj = 1; jj <= myFaces->RowLength(); jj++) { + const TopoDS_Shape &aNewFace = myFaces->Value(aNewIndex, jj); + const TopoDS_Shape &anOldFace = myFaces->Value(anOldIndex, jj); + + if (!aSubstitute.IsCopied(aNewFace)) { + aListShape.Append(anOldFace.Oriented(TopAbs_REVERSED)); + aSubstitute.Substitute(aNewFace, aListShape); + aListShape.Clear(); + } + } + } + + // Change new edges by old ones. + for (anIter.Initialize(aMapNewOldEIndex); anIter.More(); anIter.Next()) { + const Standard_Integer aNewIndex = anIter.Key(); + const Standard_Integer anOldIndex = anIter.Value(); + + for (jj = 1; jj <= myEdges->RowLength(); jj++) { + const TopoDS_Shape &aNewEdge = myEdges->Value(aNewIndex, jj); + const TopoDS_Shape &anOldEdge = myEdges->Value(anOldIndex, jj); + + if (!aSubstitute.IsCopied(aNewEdge)) { + aListShape.Append(anOldEdge.Oriented(TopAbs_FORWARD)); + aSubstitute.Substitute(aNewEdge, aListShape); + aListShape.Clear(); + + // Change new vertices by old ones. + TopoDS_Iterator aNewIt(aNewEdge); + TopoDS_Iterator anOldIt(anOldEdge); + + for (; aNewIt.More() && anOldIt.More(); + aNewIt.Next(), anOldIt.Next()) { + if (!aNewIt.Value().IsSame(anOldIt.Value())) { + if (!aSubstitute.IsCopied(aNewIt.Value())) { + aListShape.Append(anOldIt.Value().Oriented(TopAbs_FORWARD)); + aSubstitute.Substitute(aNewIt.Value(), aListShape); + aListShape.Clear(); + } + } + } + } + } + } + + // Perform substitution. + aSubstitute.Build(aResult); + + if (aSubstitute.IsCopied(aResult)) { + // Get copied shape. + const TopTools_ListOfShape& listSh = aSubstitute.Copy(aResult); + + aResult = listSh.First(); + + // Update original faces with copied ones. + for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) { + for (jj = 1; jj <= myFaces->RowLength(); jj++) { + TopoDS_Shape anOldFace = myFaces->Value(ii, jj); // Copy + + if (aSubstitute.IsCopied(anOldFace)) { + const TopTools_ListOfShape& aList = aSubstitute.Copy(anOldFace); + + if(!aList.IsEmpty()) { + // Store copied face. + const TopoDS_Shape &aCopyFace = aList.First(); + TopAbs_Orientation anOri = anOldFace.Orientation(); + const Standard_Boolean isShared = aMapNewOldFIndex.IsBound(ii); + + if (isShared) { + // Reverse the orientation for shared face. + anOri = TopAbs::Reverse(anOri); + } + + myFaces->SetValue(ii, jj, aCopyFace.Oriented(anOri)); + + // Check if it is necessary to update PCurves on this face. + if (!isShared) { + TopoDS_Face anOldF = TopoDS::Face(anOldFace); + TopoDS_Face aCopyF = TopoDS::Face(aCopyFace); + + anOldF.Orientation(TopAbs_FORWARD); + anExp.Init(anOldF, TopAbs_EDGE); + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &anOldEdge = anExp.Current(); + + if (aSubstitute.IsCopied(anOldEdge)) { + const TopTools_ListOfShape& aListE = + aSubstitute.Copy(anOldEdge); + + if(!aListE.IsEmpty()) { + // This edge is copied. Check if there is a PCurve + // on the face. + TopoDS_Edge aCopyE = TopoDS::Edge(aListE.First()); + Standard_Real aFirst; + Standard_Real aLast; + Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface + (aCopyE, aCopyF, aFirst, aLast); + + if (aPCurve.IsNull()) { + // There is no pcurve copy it from the old edge. + TopoDS_Edge anOldE = TopoDS::Edge(anOldEdge); + + aPCurve = BRep_Tool::CurveOnSurface + (anOldE, anOldF, aFirst, aLast); + + if (aPCurve.IsNull() == Standard_False) { + // Update the shared edge with PCurve from new Face. + Standard_Real aTol = Max(BRep_Tool::Tolerance(anOldE), + BRep_Tool::Tolerance(aCopyE)); + + aBuilder.UpdateEdge(aCopyE, aPCurve, aCopyF, aTol); + } + } + } + } + } + } + } + } + } + } + + // Update new edges with shared ones. + for (ii = theInitialEdgesLen + 1; ii <= myEdges->ColLength(); ii++) { + for (jj = 1; jj <= myEdges->RowLength(); jj++) { + const TopoDS_Shape &aLocalShape = myEdges->Value(ii, jj); + + if (aSubstitute.IsCopied(aLocalShape)) { + const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape); + + if(!aList.IsEmpty()) { + const TopAbs_Orientation anOri = TopAbs_FORWARD; + + myEdges->SetValue(ii, jj, aList.First().Oriented(anOri)); + } + } + } + } + + // Update new sections with shared ones. + for (ii = theInitialSectionsLen+1; ii <= mySections->ColLength(); ii++) { + for (jj = 1; jj <= mySections->RowLength(); jj++) { + const TopoDS_Shape &aLocalShape = mySections->Value(ii, jj); + + if (aSubstitute.IsCopied(aLocalShape)) { + const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape); + + if(!aList.IsEmpty()) { + const TopAbs_Orientation anOri = TopAbs_FORWARD; + + mySections->SetValue(ii, jj, aList.First().Oriented(anOri)); + } + } + } + } + } + } + + return aResult; +} diff --git a/tests/bugs/modalg/bug23606 b/tests/bugs/modalg/bug23606 new file mode 100755 index 0000000000..2df9c9f47a --- /dev/null +++ b/tests/bugs/modalg/bug23606 @@ -0,0 +1,19 @@ +puts "============" +puts "OCC23606" +puts "============" +puts "" +####################################################################### +# Invalid result of pipe operation +####################################################################### + +restore [locate_data_file bug23606_base.brep] sh +restore [locate_data_file bug23606_path.brep] w +pipe result w sh +set n [llength [explode result f]] +if { ${n} != 10 } { + puts "Error : bad number of faces" +} + +# Service parameters +set mass -0.1 +set m -0.1 -- 2.20.1