From: emv Date: Fri, 27 May 2016 10:33:38 +0000 (+0300) Subject: 0027540: Run-to-run differences in the 3D Offset algorithm X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2FCR27540_V6_9_0p4;p=occt-copy.git 0027540: Run-to-run differences in the 3D Offset algorithm Calculating the offset vertices by the superposition of intersection vertices between pairs of edges (BRepOffset_Inter2d::FuseVertices()). To obtain stable result when calculating the superposition of vertices they are sorted (BOPTools_AlgoTools::MakeVertex()). The support of vertices has been added in nexplode command. --- diff --git a/src/BOPTools/BOPTools_AlgoTools.cxx b/src/BOPTools/BOPTools_AlgoTools.cxx index 1ed5095b27..ae95b307ce 100644 --- a/src/BOPTools/BOPTools_AlgoTools.cxx +++ b/src/BOPTools/BOPTools_AlgoTools.cxx @@ -67,6 +67,9 @@ #include #include // +#include +#include +// static Standard_Real AngleWithRef(const gp_Dir& theD1, @@ -108,6 +111,25 @@ static const BOPTools_ListOfCoupleOfShape& theLCS, const gp_Pnt& aP); +//======================================================================= +// function: BOPTools_AlgoTools_ComparePoints +// purpose: implementation of IsLess() function for two points +//======================================================================= +struct BOPTools_AlgoTools_ComparePoints { + bool operator()(const gp_Pnt& theP1, const gp_Pnt& theP2) + { + for (Standard_Integer i = 1; i <= 3; ++i) { + if (theP1.Coord(i) < theP2.Coord(i)) { + return Standard_True; + } + else if (theP1.Coord(i) > theP2.Coord(i)) { + return Standard_False; + } + } + return Standard_False; + } +}; + //======================================================================= // function: MakeConnexityBlocks // purpose: @@ -1553,27 +1575,37 @@ void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV, }// else if (aNb==2) { // else { // if (aNb>2) - Standard_Real aTi, aDi, aDmax; - gp_Pnt aPi, aP; - gp_XYZ aXYZ(0.,0.,0.), aXYZi; - BOPCol_ListIteratorOfListOfShape aIt; + // compute the point // - aIt.Initialize(aLV); - for (; aIt.More(); aIt.Next()) { - TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value())); - aPi=BRep_Tool::Pnt(aVi); - aXYZi=aPi.XYZ(); - aXYZ=aXYZ+aXYZi; + // issue 0027540 - sum of doubles may depend on the order + // of addition, thus sort the coordinates for stable result + Standard_Integer i; + NCollection_Array1 aPoints(0, aNb-1); + BOPCol_ListIteratorOfListOfShape aIt(aLV); + for (i = 0; aIt.More(); aIt.Next(), ++i) { + const TopoDS_Vertex& aVi = *((TopoDS_Vertex*)(&aIt.Value())); + gp_Pnt aPi = BRep_Tool::Pnt(aVi); + aPoints(i) = aPi; } // + std::sort(aPoints.begin(), aPoints.end(), BOPTools_AlgoTools_ComparePoints()); + // + gp_XYZ aXYZ(0., 0., 0.); + for (i = 0; i < aNb; ++i) { + aXYZ += aPoints(i).XYZ(); + } aXYZ.Divide((Standard_Real)aNb); - aP.SetXYZ(aXYZ); + // + gp_Pnt aP(aXYZ); + // + // compute the tolerance for the new vertex + Standard_Real aTi, aDi, aDmax; // aDmax=-1.; aIt.Initialize(aLV); for (; aIt.More(); aIt.Next()) { TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value())); - aPi=BRep_Tool::Pnt(aVi); + gp_Pnt aPi=BRep_Tool::Pnt(aVi); aTi=BRep_Tool::Tolerance(aVi); aDi=aP.SquareDistance(aPi); aDi=sqrt(aDi); diff --git a/src/BRepAlgo/BRepAlgo_AsDes.cxx b/src/BRepAlgo/BRepAlgo_AsDes.cxx index b367bf6e00..bf0a95229d 100644 --- a/src/BRepAlgo/BRepAlgo_AsDes.cxx +++ b/src/BRepAlgo/BRepAlgo_AsDes.cxx @@ -16,6 +16,7 @@ #include #include +#include //======================================================================= //function : BRepAlgo_AsDes @@ -144,12 +145,18 @@ static void ReplaceInList(const TopoDS_Shape& OldS, const TopoDS_Shape& NewS, TopTools_ListOfShape& L) { + TopTools_MapOfOrientedShape aMS; TopTools_ListIteratorOfListOfShape it(L); - + for (; it.More(); it.Next()) { + aMS.Add(it.Value()); + } + it.Initialize(L); while(it.More()) { if (it.Value().IsSame(OldS)) { TopAbs_Orientation O = it.Value().Orientation(); - L.InsertBefore(NewS.Oriented(O),it); + if (aMS.Add(NewS.Oriented(O))) { + L.InsertBefore(NewS.Oriented(O),it); + } L.Remove(it); } else it.Next(); @@ -230,34 +237,53 @@ void BRepAlgo_AsDes::BackReplace(const TopoDS_Shape& OldS, //function : Replace //purpose : //======================================================================= - void BRepAlgo_AsDes::Replace(const TopoDS_Shape& OldS, - const TopoDS_Shape& NewS) + const TopoDS_Shape& NewS) { - Standard_Boolean InUp; - - if (up.IsBound(OldS)) { - InUp = Standard_False; - BackReplace (OldS,NewS,up(OldS),InUp); - if (up.IsBound(NewS)) { - up(NewS).Append(up(OldS)); + for (Standard_Integer i = 0; i < 2; ++i) { + TopTools_DataMapOfShapeListOfShape& aMap = !i ? up : down; + if (!aMap.IsBound(OldS)) { + continue; } - else { - up.Bind(NewS,up(OldS)); - } - up.UnBind(OldS); - } - - if (down.IsBound(OldS)) { - InUp = Standard_True; - BackReplace(OldS,NewS,down (OldS),InUp); - if (down.IsBound(NewS)) { - down(NewS).Append(down(OldS)); + // + TopTools_ListOfShape& aLSOld = aMap.ChangeFind(OldS); + // + Standard_Boolean InUp = !i ? Standard_False : Standard_True; + BackReplace(OldS, NewS, aLSOld, InUp); + // + if (!aMap.IsBound(NewS)) { + // filter the list + TopTools_MapOfOrientedShape aMS; + TopTools_ListIteratorOfListOfShape aIt(aLSOld); + for (; aIt.More(); ) { + if (!aMS.Add(aIt.Value())) { + aLSOld.Remove(aIt); + } + else { + aIt.Next(); + } + } + aMap.Bind(NewS, aLSOld); } else { - down.Bind(NewS,down(OldS)); + // avoid duplicates + TopTools_MapOfOrientedShape aMS; + TopTools_ListOfShape& aLSNew = aMap.ChangeFind(NewS); + TopTools_ListIteratorOfListOfShape aIt(aLSNew); + for (; aIt.More(); aIt.Next()) { + aMS.Add(aIt.Value()); + } + // + aIt.Initialize(aLSOld); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Shape& aS = aIt.Value(); + if (aMS.Add(aS)) { + aLSNew.Append(aS); + } + } } - down.UnBind(OldS); + // + aMap.UnBind(OldS); } } diff --git a/src/BRepOffset/BRepOffset_Inter2d.cdl b/src/BRepOffset/BRepOffset_Inter2d.cdl index 1b11fc7188..93594f71fc 100644 --- a/src/BRepOffset/BRepOffset_Inter2d.cdl +++ b/src/BRepOffset/BRepOffset_Inter2d.cdl @@ -27,6 +27,7 @@ uses Face from TopoDS, Edge from TopoDS, IndexedMapOfShape from TopTools, + IndexedDataMapOfShapeListOfShape from TopTools, DataMapOfShapeShape from TopTools, Real from Standard @@ -34,12 +35,15 @@ is Compute(myclass ; AsDes : AsDes from BRepAlgo; F : Face from TopoDS; NewEdges : IndexedMapOfShape from TopTools; - Tol : Real from Standard); + Tol : Real from Standard; + theDMVV : out IndexedDataMapOfShapeListOfShape from TopTools); ---Purpose: Computes the intersections between the edges stored -- is AsDes as descendants of . Intersections is computed -- between two edges if one of them is bound in NewEdges. - + -- When all faces of the shape are treated the intersection + -- vertices have to be fused using the FuseVertices method. + -- theDMVV contains the vertices that should be fused -- Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 Begin -- Add another parameter: offset value. @@ -51,8 +55,24 @@ is AsDes : AsDes from BRepAlgo; AsDes2d : AsDes from BRepAlgo; Offset : Real from Standard; - Tol : Real from Standard); + Tol : Real from Standard; + theDMVV : out IndexedDataMapOfShapeListOfShape from TopTools); -- Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 End + ---Purpose: Computes the intersection between the offset edges + -- stored in AsDes as descendatnds on . All intersection + -- vertices will be stored in AsDes2d. When all faces of the + -- shape are treated the intersection vertices have to be fused + -- using the FuseVertices method. + -- theDMVV contains the vertices that should be fused. + + + FuseVertices(myclass; + theDMVV : IndexedDataMapOfShapeListOfShape from TopTools; + theAsDes : AsDes from BRepAlgo); + ---Purpose: Fuses the chains of vertices in the theDMVV + -- and updates AsDes by replacing the old vertices + -- with the new ones. + ExtentEdge(myclass ; E : Edge from TopoDS; diff --git a/src/BRepOffset/BRepOffset_Inter2d.cxx b/src/BRepOffset/BRepOffset_Inter2d.cxx index a67719c0be..957e8bc92b 100644 --- a/src/BRepOffset/BRepOffset_Inter2d.cxx +++ b/src/BRepOffset/BRepOffset_Inter2d.cxx @@ -80,6 +80,10 @@ #include #include #include +// +#include +#include + #ifdef DRAW #include @@ -116,146 +120,83 @@ static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1, //======================================================================= //function : Store -//purpose : +//purpose : The vertices are added despite of the coincidence with +// already added vertices. When all vertices for all edges +// are added the coinciding chains of vertices should be fused +// using FuseVertices() method. //======================================================================= - -static void Store (const TopoDS_Edge& E1, - const TopoDS_Edge& E2, - TopTools_ListOfShape& LV1, - TopTools_ListOfShape& LV2, - Handle(BRepAlgo_AsDes) AsDes, - Standard_Real Tol) +static void Store (const TopoDS_Edge& E1, + const TopoDS_Edge& E2, + const TopTools_ListOfShape& LV1, + const TopTools_ListOfShape& LV2, + Handle(BRepAlgo_AsDes) AsDes, + Standard_Real Tol, + TopTools_IndexedDataMapOfShapeListOfShape& aDMVV) { - //------------------------------------------------------------- - // Test if the points of intersection correspond to existing - // vertices. Otherwise add edges in the descendants. - // Note: at this stage only vertices of intersection are in the descendants. - //------------------------------------------------------------- - const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1); - const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2); - TopTools_ListOfShape NewVOnE1; - TopTools_ListOfShape NewVOnE2; - gp_Pnt P,P1,P2; - TopoDS_Vertex V1,V2; - TopTools_ListIteratorOfListOfShape it, itLV1, itLV2; - BRep_Builder B; - TopAbs_Orientation O1,O2; - Standard_Real U1,U2; - Standard_Boolean OnE1,OnE2; - - for (itLV1.Initialize(LV1),itLV2.Initialize(LV2); - itLV1.More(); - itLV1.Next() ,itLV2.Next()) { - - TopoDS_Vertex V = TopoDS::Vertex(itLV1.Value()); - - U1 = (BRep_Tool::Degenerated(E1))? - BRep_Tool::Parameter(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), E1) : - BRep_Tool::Parameter(V, E1); - U2 = (BRep_Tool::Degenerated(E2))? - BRep_Tool::Parameter(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), E2) : - BRep_Tool::Parameter(V, E2); - O1 = V.Orientation(); - O2 = itLV2.Value().Orientation(); - P = BRep_Tool::Pnt(V); - OnE1 = OnE2 = Standard_False; - - if (!VOnE1.IsEmpty()) { - //----------------------------------------------------------------- - // Find if the point of intersection corresponds to a vertex of E1. - //----------------------------------------------------------------- - for (it.Initialize(VOnE1); it.More(); it.Next()) { - P1 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); - if (P.IsEqual(P1,Tol)) { - V = TopoDS::Vertex(it.Value()); - V1 = V; - OnE1 = Standard_True; - break; - } - } + BRep_Builder aBB; + for (Standard_Integer i = 0; i < 2; ++i) { + const TopoDS_Edge& aE = !i ? E1 : E2; + const TopTools_ListOfShape& aLV = !i ? LV1 : LV2; + const TopTools_ListOfShape& aLVEx = AsDes->Descendant(aE); + if (aLVEx.IsEmpty()) { + if (aLV.Extent()) AsDes->Add(aE, aLV); + continue; } - if (!VOnE2.IsEmpty()) { - if (OnE1) { - //----------------------------------------------------------------- - // Find if the vertex found on E1 is not already on E2. - //----------------------------------------------------------------- - for (it.Initialize(VOnE2); it.More(); it.Next()) { - if (it.Value().IsSame(V)) { - OnE2 = Standard_True; - V2 = V; - break; - } - } + // + TopTools_MapOfShape aMV; + TopTools_ListIteratorOfListOfShape aIt(aLV); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value()); + if (!aMV.Add(aV)) { + continue; } - for (it.Initialize(VOnE2); it.More(); it.Next()) { - //----------------------------------------------------------------- - // Find if the point of intersection corresponds to a vertex of E2. - //----------------------------------------------------------------- - P2 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); - if (P.IsEqual(P2,Tol)) { - V = TopoDS::Vertex(it.Value()); - V2 = V; - OnE2 = Standard_True; + gp_Pnt aP = BRep_Tool::Pnt(aV); + // + TopTools_ListOfShape aLVC; + TopTools_ListIteratorOfListOfShape aItEx(aLVEx); + for (; aItEx.More(); aItEx.Next()) { + const TopoDS_Vertex& aVEx = TopoDS::Vertex(aItEx.Value()); + if (aV.IsSame(aVEx)) { break; } - } - } - if (OnE1 && OnE2) { - if (!V1.IsSame(V2)) { - //--------------------------------------------------------------- - // Two vertices are actually the same. - // V2 will be replaced by V1. - // update the parameters of vertex on edges. - //--------------------------------------------------------------- - Standard_Real UV2; - TopoDS_Edge EWE2; - const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2); - - for (it.Initialize(EdgeWithV2); it.More(); it.Next()) { - EWE2 = TopoDS::Edge(it.Value()); - TopoDS_Shape aLocalShape =V2.Oriented(TopAbs_INTERNAL); - UV2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2); -// UV2 = -// BRep_Tool::Parameter(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),EWE2); - aLocalShape = V1.Oriented(TopAbs_INTERNAL); - B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol); -// B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)), -// UV2,EWE2,Tol); + gp_Pnt aPEx = BRep_Tool::Pnt(aVEx); + // + if (aP.IsEqual(aPEx, Tol)) { + aLVC.Append(aVEx); } - AsDes->Replace(V2,V1); } - } - if (!OnE1) { - if (OnE2) { - TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL); - B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol); -// B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), -// U1,E1,Tol); + // + if (aItEx.More()) { + continue; } - NewVOnE1.Append(V.Oriented(O1)); - } - if (!OnE2) { - if (OnE1) { - TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL); - B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol); -// B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), -// U2,E2,Tol); + // + if (aLVC.Extent()) { + TopTools_ListOfShape aLVN; + aLVN.Append(aV); + // + TopTools_ListIteratorOfListOfShape aItLV(aLVC); + for (; aItLV.More(); aItLV.Next()) { + const TopoDS_Shape& aVC = aItLV.Value(); + if (!aDMVV.Contains(aVC)) { + aDMVV.Add(aVC, aLVN); + } + else { + aDMVV.ChangeFromKey(aVC).Append(aV); + } + } + // + if (!aDMVV.Contains(aV)) { + aDMVV.Add(aV, aLVC); + } + else { + aDMVV.ChangeFromKey(aV).Append(aLVC); + } } - NewVOnE2.Append(V.Oriented(O2)); + // + aBB.UpdateVertex(aV, Tol); + AsDes->Add(aE, aV); } - -#ifdef DRAW - if (Inter2dAffichInt2d) { - if (!OnE1 && !OnE2) { - char name[256]; - sprintf(name,"VV_%d",NbNewVertices++); - DBRep::Set(name,V); - } - } -#endif } - if (!NewVOnE1.IsEmpty()) AsDes->Add(E1,NewVOnE1); - if (!NewVOnE2.IsEmpty()) AsDes->Add(E2,NewVOnE2); } @@ -270,7 +211,8 @@ static void EdgeInter(const TopoDS_Face& F, const TopoDS_Edge& E2, const Handle(BRepAlgo_AsDes)& AsDes, Standard_Real Tol, - Standard_Boolean WithOri) + Standard_Boolean WithOri, + TopTools_IndexedDataMapOfShapeListOfShape& aDMVV) { #ifdef DRAW if (Inter2dAffichInt2d) { @@ -442,32 +384,26 @@ static void EdgeInter(const TopoDS_Face& F, if (V1[j].IsNull()) continue; for (Standard_Integer k = 0; k < 2; k++) { if (V2[k].IsNull()) continue; + if (V1[j].IsSame(V2[k])) { + if (AsDes->HasAscendant(V1[j])) { + continue; + } + } + // gp_Pnt P1 = BRep_Tool::Pnt(V1[j]); gp_Pnt P2 = BRep_Tool::Pnt(V2[k]); Standard_Real Dist = P1.Distance(P2); if (Dist < TolConf) { + Standard_Real aTol = + Max(BRep_Tool::Tolerance(V1[j]), BRep_Tool::Tolerance(V2[k])); TopoDS_Vertex V = BRepLib_MakeVertex(P1); U1 = (j == 0) ? f[1] : l[1]; U2 = (k == 0) ? f[2] : l[2]; + // TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL); -// Modified by skv - Thu Jan 22 18:16:01 2004 OCC4455 Begin - Standard_Real aTol = BRep_Tool::Tolerance(V1[j]); - - if (!V1[j].IsSame(V2[k])) { - Standard_Real aTol2 = BRep_Tool::Tolerance(V2[k]); - - aTol = Max(aTol, aTol2); - } - B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,aTol); B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,aTol); -// B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol); -// B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol); -// B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), -// U1,E1,Tol); -// B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), -// U2,E2,Tol); -// Modified by skv - Thu Jan 22 18:16:01 2004 OCC4455 End + // LV1.Prepend(V.Oriented(V1[j].Orientation())); LV2.Prepend(V.Oriented(V2[k].Orientation())); } @@ -519,15 +455,9 @@ static void EdgeInter(const TopoDS_Face& F, //--------------------------------- // Vertex storage in DS. //--------------------------------- -// Modified by skv - Tue Jan 13 15:14:30 2004 Begin Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); - TolStore = Max(TolStore, 10.*Tol); - - Store (E1,E2,LV1,LV2,AsDes,TolStore); -// Store (E1,E2,LV1,LV2,AsDes,10.*Tol); -// Store (E1,E2,LV1,LV2,AsDes,Tol); -// Modified by skv - Tue Jan 13 15:14:30 2004 End + Store (E1,E2,LV1,LV2,AsDes,TolStore, aDMVV); } } //======================================================================= @@ -542,7 +472,8 @@ static void RefEdgeInter(const TopoDS_Face& F, const Handle(BRepAlgo_AsDes)& AsDes, Standard_Real Tol, Standard_Boolean WithOri, - gp_Pnt& Pref) + gp_Pnt& Pref, + TopTools_IndexedDataMapOfShapeListOfShape& aDMVV) { #ifdef DRAW if (Inter2dAffichInt2d) { @@ -710,6 +641,12 @@ static void RefEdgeInter(const TopoDS_Face& F, if (V1[j].IsNull()) continue; for (Standard_Integer k = 0; k < 2; k++) { if (V2[k].IsNull()) continue; + if (V1[j].IsSame(V2[k])) { + if (AsDes->HasAscendant(V1[j])) { + continue; + } + } + // gp_Pnt P1 = BRep_Tool::Pnt(V1[j]); gp_Pnt P2 = BRep_Tool::Pnt(V2[k]); Standard_Real Dist = P1.Distance(P2); @@ -720,10 +657,6 @@ static void RefEdgeInter(const TopoDS_Face& F, TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol); B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol); -// B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), -// U1,E1,Tol); -// B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), -// U2,E2,Tol); LV1.Prepend(V.Oriented(V1[j].Orientation())); LV2.Prepend(V.Oriented(V2[k].Orientation())); } @@ -792,16 +725,9 @@ static void RefEdgeInter(const TopoDS_Face& F, } ////----------------------------------------------------- - -// Modified by skv - Tue Jan 13 15:14:30 2004 Begin Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); - TolStore = Max(TolStore, 10.*Tol); - - Store (E1,E2,LV1,LV2,AsDes,TolStore); -// Store (E1,E2,LV1,LV2,AsDes,10.*Tol); -// Store (E1,E2,LV1,LV2,AsDes,Tol); -// Modified by skv - Tue Jan 13 15:14:30 2004 End + Store (E1,E2,LV1,LV2,AsDes,TolStore, aDMVV); } } @@ -1400,7 +1326,8 @@ static Standard_Boolean UpdateVertex(TopoDS_Vertex V, void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)& AsDes, const TopoDS_Face& F, const TopTools_IndexedMapOfShape& NewEdges, - const Standard_Real Tol) + const Standard_Real Tol, + TopTools_IndexedDataMapOfShapeListOfShape& theDMVV) { #ifdef DRAW NbF2d++; @@ -1442,7 +1369,7 @@ void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)& AsDes, if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) && (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) { TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD); - EdgeInter(TopoDS::Face(aLocalShape),BAsurf,E1,E2,AsDes,Tol,Standard_True); + EdgeInter(TopoDS::Face(aLocalShape),BAsurf,E1,E2,AsDes,Tol,Standard_True, theDMVV); // EdgeInter(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),E1,E2,AsDes,Tol,Standard_True); } it2LE.Next(); @@ -1467,7 +1394,8 @@ void BRepOffset_Inter2d::ConnexIntByInt const Handle(BRepAlgo_AsDes)& AsDes, const Handle(BRepAlgo_AsDes)& AsDes2d, const Standard_Real Offset, - const Standard_Real Tol) + const Standard_Real Tol, + TopTools_IndexedDataMapOfShapeListOfShape& theDMVV) // Modified by skv - Fri Dec 26 16:53:18 2003 OCC4455 End { @@ -1588,7 +1516,7 @@ void BRepOffset_Inter2d::ConnexIntByInt for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) { for (Exp2.Init(NE2,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) { RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),TopoDS::Edge(Exp2.Current()), - AsDes2d,Tol,Standard_True/*Standard_False*/, Pref); + AsDes2d,Tol,Standard_True/*Standard_False*/, Pref, theDMVV); } } // @@ -1603,12 +1531,12 @@ void BRepOffset_Inter2d::ConnexIntByInt // for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) { RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),aE3, - AsDes2d,Tol,Standard_True/*Standard_False*/, Pref); + AsDes2d,Tol,Standard_True/*Standard_False*/, Pref, theDMVV); } // for (Exp1.Init(NE2,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) { RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),aE3, - AsDes2d,Tol,Standard_True/*Standard_False*/, Pref); + AsDes2d,Tol,Standard_True/*Standard_False*/, Pref, theDMVV); } } } @@ -1629,3 +1557,72 @@ void BRepOffset_Inter2d::ConnexIntByInt } } } + + +//======================================================================= +//function : MakeChain +//purpose : +//======================================================================= +static void MakeChain(const TopoDS_Shape& theV, + const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, + TopTools_MapOfShape& theMDone, + BOPCol_ListOfShape& theChain) +{ + if (theMDone.Add(theV)) { + theChain.Append(theV); + if (theDMVV.Contains(theV)) { + const TopTools_ListOfShape& aLV = theDMVV.FindFromKey(theV); + TopTools_ListIteratorOfListOfShape aIt(aLV); + for (; aIt.More(); aIt.Next()) { + MakeChain(aIt.Value(), theDMVV, theMDone, theChain); + } + } + } +} + +//======================================================================= +//function : FuseVertices +//purpose : +//======================================================================= +void BRepOffset_Inter2d::FuseVertices(const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, + const Handle(BRepAlgo_AsDes)& theAsDes) +{ + BRep_Builder aBB; + TopTools_MapOfShape aMVDone; + Standard_Integer i, aNb = theDMVV.Extent(); + for (i = 1; i <= aNb; ++i) { + const TopoDS_Vertex& aV = TopoDS::Vertex(theDMVV.FindKey(i)); + // + // find chain of vertices + BOPCol_ListOfShape aLVChain; + MakeChain(aV, theDMVV, aMVDone, aLVChain); + // + if (aLVChain.Extent() < 2) { + continue; + } + // + // make new vertex + TopoDS_Vertex aVNew; + BOPTools_AlgoTools::MakeVertex(aLVChain, aVNew); + // + TopoDS_Vertex aVNewInt = TopoDS::Vertex(aVNew.Oriented(TopAbs_INTERNAL)); + // + BOPCol_ListIteratorOfListOfShape aIt(aLVChain); + for (; aIt.More(); aIt.Next()) { + const TopoDS_Shape& aVOld = aIt.Value(); + // update the parameters on edges + TopoDS_Vertex aVOldInt = TopoDS::Vertex(aVOld.Oriented(TopAbs_INTERNAL)); + const TopTools_ListOfShape& aLE = theAsDes->Ascendant(aVOld); + // + TopTools_ListIteratorOfListOfShape aItLE(aLE); + for (; aItLE.More(); aItLE.Next()) { + const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value()); + Standard_Real aTolE = BRep_Tool::Tolerance(aE); + Standard_Real aT = BRep_Tool::Parameter(aVOldInt, aE); + aBB.UpdateVertex(aVNewInt, aT, aE, aTolE); + } + // and replace the vertex + theAsDes->Replace(aVOld, aVNew); + } + } +} diff --git a/src/BRepOffset/BRepOffset_MakeOffset.cxx b/src/BRepOffset/BRepOffset_MakeOffset.cxx index bf85a20ddd..a821c3e2b0 100644 --- a/src/BRepOffset/BRepOffset_MakeOffset.cxx +++ b/src/BRepOffset/BRepOffset_MakeOffset.cxx @@ -1610,6 +1610,7 @@ void BRepOffset_MakeOffset::BuildOffsetByInter() //--------------------------------- // Intersection 2D on // //--------------------------------- + TopTools_IndexedDataMapOfShapeListOfShape aDMVV; TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face TopTools_ListOfShape LFE; BRepAlgo_Image IMOE; @@ -1620,7 +1621,7 @@ void BRepOffset_MakeOffset::BuildOffsetByInter() { const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value()); Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF); - BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol); + BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, aDMVV); } //---------------------------------------------- // Intersections 2d on caps. @@ -1630,9 +1631,11 @@ void BRepOffset_MakeOffset::BuildOffsetByInter() { const TopoDS_Face& Cork = TopoDS::Face(myFaces(i)); Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork); - BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol); + BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, aDMVV); } - + // + // + BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes); //------------------------------- // Unwinding of extended Faces. //------------------------------- @@ -2735,12 +2738,15 @@ void BRepOffset_MakeOffset::Intersection2D(const TopTools_IndexedMapOfShape& Mod //----------------------------------------------- // Intersection of edges 2 by 2. //----------------------------------------------- + TopTools_IndexedDataMapOfShapeListOfShape aDMVV; Standard_Integer i; for (i = 1; i <= Modif.Extent(); i++) { const TopoDS_Face& F = TopoDS::Face(Modif(i)); - BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol); + BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,myTol, aDMVV); } - + // + BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes); + // #ifdef OCCT_DEBUG if (AffichInt2d) { DEBVerticesControl (NewEdges,myAsDes); @@ -3946,6 +3952,7 @@ void BRepOffset_MakeOffset::IntersectEdges(const TopoDS_Shape& theShape, Handle(BRepAlgo_AsDes)& theAsDes2d) { Standard_Real aTolF; + TopTools_IndexedDataMapOfShapeListOfShape aDMVV; TopExp_Explorer aExp(theShape, TopAbs_FACE); // for (; aExp.More(); aExp.Next()) { @@ -3953,8 +3960,11 @@ void BRepOffset_MakeOffset::IntersectEdges(const TopoDS_Shape& theShape, aTolF = BRep_Tool::Tolerance(aF); // BRepOffset_Inter2d::ConnexIntByInt - (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, myOffset, aTolF); + (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, myOffset, aTolF, aDMVV); } + // + // fuse vertices on edges + BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d); } //======================================================================= diff --git a/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx b/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx index 33cfcce3b0..81fcdd4003 100644 --- a/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx +++ b/src/BRepOffset/BRepOffset_MakeOffsetOld.cxx @@ -803,13 +803,17 @@ void BRepOffset_MakeOffsetOld::BuildOffsetByInter() //--------------------------------------------------------------------------------- // Extension of neighbor edges of new edges and intersection between neighbors. //-------------------------------------------------------------------------------- + TopTools_IndexedDataMapOfShapeListOfShape aDMVV; Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes(); for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) { const TopoDS_Face& FI = TopoDS::Face(Exp.Current()); Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(FI); BRepOffset_Inter2d::ConnexIntByInt (FI, MapSF(FI), MES, Build, - AsDes, AsDes2d, myOffset, aCurrFaceTol); + AsDes, AsDes2d, myOffset, aCurrFaceTol, aDMVV); } + // + // fuse vertices on edges + BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes2d); //----------------------------------------------------------- // Great restriction of new edges and update of AsDes. //------------------------------------------ ---------------- @@ -939,11 +943,12 @@ void BRepOffset_MakeOffsetOld::BuildOffsetByInter() } } + aDMVV.Clear(); TopTools_ListIteratorOfListOfShape itLFE(LFE); for (; itLFE.More(); itLFE.Next()) { const TopoDS_Face& NEF = TopoDS::Face(itLFE.Value()); Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(NEF); - BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol); + BRepOffset_Inter2d::Compute(AsDes, NEF, NewEdges, aCurrFaceTol, aDMVV); } //---------------------------------------------- // Intersections 2d on caps. @@ -952,9 +957,10 @@ void BRepOffset_MakeOffsetOld::BuildOffsetByInter() for (i = 1; i <= myFaces.Extent(); i++) { const TopoDS_Face& Cork = TopoDS::Face(myFaces(i)); Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(Cork); - BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol); + BRepOffset_Inter2d::Compute(AsDes, Cork, NewEdges, aCurrFaceTol, aDMVV); } - + // + BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes); //------------------------------- // Unwinding of extended Faces. //------------------------------- @@ -2407,13 +2413,16 @@ void BRepOffset_MakeOffsetOld::Intersection2D(const TopTools_IndexedMapOfShape& //----------------------------------------------- // Intersection of edges 2 by 2. //----------------------------------------------- + TopTools_IndexedDataMapOfShapeListOfShape aDMVV; Standard_Integer i; for (i = 1; i <= Modif.Extent(); i++) { const TopoDS_Face& F = TopoDS::Face(Modif(i)); Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(F); - BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,aCurrFaceTol); + BRepOffset_Inter2d::Compute(myAsDes,F,NewEdges,aCurrFaceTol, aDMVV); } - + // + BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes); + // #ifdef OCCT_DEBUG if (AffichInt2dOld) { DEBVerticesControlOld (NewEdges,myAsDes); diff --git a/src/BiTgte/BiTgte_Blend.cxx b/src/BiTgte/BiTgte_Blend.cxx index e32cef73a0..01d36a92bd 100644 --- a/src/BiTgte/BiTgte_Blend.cxx +++ b/src/BiTgte/BiTgte_Blend.cxx @@ -1725,7 +1725,7 @@ void BiTgte_Blend::ComputeCenters() // ------------------------------------------------------------------- // Proceed with MakeLoops - + TopTools_IndexedDataMapOfShapeListOfShape aDMVV; BRepOffset_Type OT = BRepOffset_Concave; if (myRadius < 0.) OT = BRepOffset_Convex; @@ -1778,7 +1778,8 @@ void BiTgte_Blend::ComputeCenters() BRepOffset_Inter2d::Compute(myAsDes, CurOF, myEdges, - myTol); + myTol, + aDMVV); } } @@ -1810,8 +1811,12 @@ void BiTgte_Blend::ComputeCenters() BRepOffset_Inter2d::Compute(myAsDes, CurOF, myEdges, - myTol); + myTol, + aDMVV); } + // + // fuse vertices on edges stored in AsDes + BRepOffset_Inter2d::FuseVertices(aDMVV, myAsDes); // ------------ // unwinding // ------------ diff --git a/src/DBRep/DBRep.cxx b/src/DBRep/DBRep.cxx index 9ab0aadbf8..8b19ffc385 100644 --- a/src/DBRep/DBRep.cxx +++ b/src/DBRep/DBRep.cxx @@ -583,6 +583,11 @@ static Standard_Integer nexplode(Draw_Interpretor& di, typ = TopAbs_EDGE; break; + case 'V' : + case 'v' : + typ = TopAbs_VERTEX; + break; + default : return 1; } @@ -603,20 +608,26 @@ static Standard_Integer nexplode(Draw_Interpretor& di, } Exp.Next(); } - + // TColStd_Array1OfInteger OrderInd(1,MaxShapes); -// gp_Pnt GPoint; + gp_Pnt GPoint; GProp_GProps GPr; -// Standard_Integer InOfminX = 1,aTemp; Standard_Integer aTemp; TColStd_Array1OfReal MidXYZ(1,MaxShapes); //X,Y,Z; Standard_Boolean NoSort = Standard_True; - - // Computing of CentreOfMass + // + // Computing of CentreOfMass for edge and face + // and for vertex use its point for (Index=1; Index <= MaxShapes; Index++) { OrderInd.SetValue(Index,Index); - BRepGProp::LinearProperties(aShapes(Index),GPr); - gp_Pnt GPoint = GPr.CentreOfMass(); + const TopoDS_Shape& aS = aShapes(Index); + if (aS.ShapeType() != TopAbs_VERTEX) { + BRepGProp::LinearProperties(aS, GPr); + GPoint = GPr.CentreOfMass(); + } + else { + GPoint = BRep_Tool::Pnt(TopoDS::Vertex(aS)); + } MidXYZ.SetValue(Index, GPoint.X()*999 + GPoint.Y()*99 + GPoint.Z()*0.9); } @@ -1285,7 +1296,7 @@ void DBRep::BasicCommands(Draw_Interpretor& theCommands) theCommands.Add("compound","compound [name1 name2 ..] compound",__FILE__,compound,g); theCommands.Add("add","add name1 name2",__FILE__,add,g); theCommands.Add("explode","explode name [Cd/C/So/Sh/F/W/E/V]",__FILE__,explode,g); - theCommands.Add("nexplode","stable numbered explode for edge and face: nexplode name [F/E]",__FILE__,nexplode,g); + theCommands.Add("nexplode","stable numbered explode for vertex, edge and face: nexplode name [F/E/V]",__FILE__,nexplode,g); theCommands.Add("exwire","exwire wirename",__FILE__,exwire,g); theCommands.Add("emptycopy","emptycopy [copyshape] originalshape",__FILE__,emptycopy,g); theCommands.Add("check","check shape1 shape2 ...",__FILE__,check,g); diff --git a/tests/bugs/modalg_6/bug27540_1 b/tests/bugs/modalg_6/bug27540_1 new file mode 100644 index 0000000000..bfbfef8372 --- /dev/null +++ b/tests/bugs/modalg_6/bug27540_1 @@ -0,0 +1,67 @@ +puts "==========================================================" +puts "0027540: Run-to-run differences in the 3D Offset algorithm" +puts "==========================================================" +puts "" + +pload MODELING + +restore [locate_data_file bug27540_shapes1.brep] s +explode s + +# make offset operations on two shapes +# first shape +offsetparameter 1e-7 c i +# set offset 10 for top faces (normal direction 0 0 1), 0 for all other faces +offsetload s_1 0 +set faces [explode s_1 f] +foreach f $faces { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs($z - 1) < 1.e-7} { + offsetonface $f 10 + } +} +offsetperform result1 +set square 3.26459e+006 +set volume 1.067e+008 +checknbshapes result1 -vertex 28 -edge 44 -wire 20 -face 19 -shell 1 -solid 1 + + +# second shape +offsetparameter 1e-7 c i +# set offset 10 for top faces (normal direction 0 0 1), 0 for all other faces +offsetload s_2 0 +set faces [explode s_2 f] +foreach f $faces { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs($z - 1) < 1.e-7} { + offsetonface $f 10 + } +} +offsetperform result2 +set square 3.26459e+006 +set volume 1.067e+008 +checknbshapes result2 -vertex 28 -edge 44 -wire 20 -face 19 -shell 1 -solid 1 + + +# compare the results +set vertices1 [nexplode result1 v] +set vertices2 [nexplode result2 v] + +set nbv1 [llength $vertices1] + +for {set i 0} {$i < $nbv1} {incr i} { + set v1 [lindex $vertices1 $i] + set v2 [lindex $vertices2 $i] + + mkpoint px $v1 + set dump_v1 [dump px] + + mkpoint px $v2 + set dump_v2 [dump px] + + if {$dump_v1 != $dump_v2} { + puts "Error: the results are not the same - $v1 and $v2" + } +} diff --git a/tests/bugs/modalg_6/bug27540_2 b/tests/bugs/modalg_6/bug27540_2 new file mode 100644 index 0000000000..b1ee905b7a --- /dev/null +++ b/tests/bugs/modalg_6/bug27540_2 @@ -0,0 +1,67 @@ +puts "==========================================================" +puts "0027540: Run-to-run differences in the 3D Offset algorithm" +puts "==========================================================" +puts "" + +pload MODELING + +restore [locate_data_file bug27540_shapes2.brep] s +explode s + +# make offset operations on two shapes +# first shape +offsetparameter 1e-7 c i +# set offset 30 for top faces (normal direction 0 0 1), 10 for all other faces +offsetload s_1 10 +set faces [explode s_1 f] +foreach f $faces { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs($z - 1) < 1.e-7} { + offsetonface $f 30 + } +} +offsetperform result1 +set square 3.76166e+006 +set volume 1.74521e+008 +checknbshapes result1 -vertex 36 -edge 56 -wire 24 -face 23 -shell 1 -solid 1 + + +# second shape +offsetparameter 1e-7 c i +# set offset 30 for top faces (normal direction 0 0 1), 10 for all other faces +offsetload s_2 10 +set faces [explode s_2 f] +foreach f $faces { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs($z - 1) < 1.e-7} { + offsetonface $f 30 + } +} +offsetperform result2 +set square 3.76166e+006 +set volume 1.74521e+008 +checknbshapes result2 -vertex 36 -edge 56 -wire 24 -face 23 -shell 1 -solid 1 + + +# compare the results +set vertices1 [nexplode result1 v] +set vertices2 [nexplode result2 v] + +set nbv1 [llength $vertices1] + +for {set i 0} {$i < $nbv1} {incr i} { + set v1 [lindex $vertices1 $i] + set v2 [lindex $vertices2 $i] + + mkpoint px $v1 + set dump_v1 [dump px] + + mkpoint px $v2 + set dump_v2 [dump px] + + if {$dump_v1 != $dump_v2} { + puts "Error: the results are not the same - $v1 and $v2" + } +} diff --git a/tests/bugs/modalg_6/bug27540_3 b/tests/bugs/modalg_6/bug27540_3 new file mode 100644 index 0000000000..6331750284 --- /dev/null +++ b/tests/bugs/modalg_6/bug27540_3 @@ -0,0 +1,67 @@ +puts "==========================================================" +puts "0027540: Run-to-run differences in the 3D Offset algorithm" +puts "==========================================================" +puts "" + +pload MODELING + +restore [locate_data_file bug27540_shapes3.brep] s +explode s + +# make offset operations on two shapes +# first shape +offsetparameter 1e-7 c i +# set offset 20 for top faces (normal direction 0 0 1), 0 for all other faces +offsetload s_1 0 +set faces [explode s_1 f] +foreach f $faces { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs($z - 1) < 1.e-7} { + offsetonface $f 20 + } +} +offsetperform result1 +set square 464088 +set volume 1.29909e+007 +checknbshapes result1 -vertex 48 -edge 74 -wire 32 -face 30 -shell 1 -solid 1 + + +# second shape +offsetparameter 1e-7 c i +# set offset 20 for top faces (normal direction 0 0 1), 0 for all other faces +offsetload s_2 0 +set faces [explode s_2 f] +foreach f $faces { + mksurface surf $f + set found [regexp {Axis :([-0-9.+eE]*), ([-0-9.+eE]*), ([-0-9.+eE]*)} [dump surf] full x y z] + if {$found && abs($z - 1) < 1.e-7} { + offsetonface $f 20 + } +} +offsetperform result2 +set square 464088 +set volume 1.29909e+007 +checknbshapes result2 -vertex 48 -edge 74 -wire 32 -face 30 -shell 1 -solid 1 + + +# compare the results +set vertices1 [nexplode result1 v] +set vertices2 [nexplode result2 v] + +set nbv1 [llength $vertices1] + +for {set i 0} {$i < $nbv1} {incr i} { + set v1 [lindex $vertices1 $i] + set v2 [lindex $vertices2 $i] + + mkpoint px $v1 + set dump_v1 [dump px] + + mkpoint px $v2 + set dump_v2 [dump px] + + if {$dump_v1 != $dump_v2} { + puts "Error: the results are not the same - $v1 and $v2" + } +}