From 833e75611fbce55045cc671b73857d016607e6ab Mon Sep 17 00:00:00 2001 From: jgv Date: Wed, 18 Oct 2017 17:35:58 +0300 Subject: [PATCH] 0029204: BRepOffsetAPI_MakePipeShell produces invalid result and raises exception in Draw 1.The algorithm searching the section in the corner (ChooseSection) is modified to be able to find simple cases with rather big tolerance. 2. The constructor of BRepFill_Section is modified: now it removes locations in the shape of section like it was done in BRepFill_Pipe. 3. Correction of U-edges by Same Parameter has been added to the method BRepFill_Sweep::Build. --- src/BRepFill/BRepFill_Pipe.cxx | 37 -- src/BRepFill/BRepFill_PipeShell.cxx | 51 +- src/BRepFill/BRepFill_Section.cxx | 73 ++- src/BRepFill/BRepFill_Section.hxx | 5 + src/BRepFill/BRepFill_Section.lxx | 5 + src/BRepFill/BRepFill_Sweep.cxx | 140 +++- src/BRepFill/BRepFill_TrimShellCorner.cxx | 751 +++++++++++++++------- src/BRepFill/BRepFill_TrimShellCorner.hxx | 37 +- tests/bugs/modalg_7/bug29204 | 26 + 9 files changed, 789 insertions(+), 336 deletions(-) create mode 100644 tests/bugs/modalg_7/bug29204 diff --git a/src/BRepFill/BRepFill_Pipe.cxx b/src/BRepFill/BRepFill_Pipe.cxx index c514052544..db46764d7a 100644 --- a/src/BRepFill/BRepFill_Pipe.cxx +++ b/src/BRepFill/BRepFill_Pipe.cxx @@ -102,40 +102,6 @@ static Standard_Boolean UpdateMap(const TopoDS_Shape& theKey, return !found; } -static void ReverseModifiedEdges(TopoDS_Shape& aShape, - TopTools_MapOfShape& Emap) -{ - TopExp_Explorer Explo(aShape, TopAbs_FACE); - BRep_Builder BB; - - for (; Explo.More(); Explo.Next()) - { - TopoDS_Shape aFace = Explo.Current(); - TopoDS_Iterator itf(aFace); - for (; itf.More(); itf.Next()) - { - TopoDS_Shape aWire = itf.Value(); - TopTools_ListOfShape Ledges; - TopoDS_Iterator itw(aWire); - for (; itw.More(); itw.Next()) - Ledges.Append(itw.Value()); - - aWire.Free(Standard_True); - TopTools_ListIteratorOfListOfShape itl(Ledges); - for (; itl.More(); itl.Next()) - BB.Remove(aWire, itl.Value()); - - for (itl.Initialize(Ledges); itl.More(); itl.Next()) - { - TopoDS_Shape anEdge = itl.Value(); - if (Emap.Contains(anEdge)) - anEdge.Reverse(); - BB.Add(aWire, anEdge); - } - } - } -} - static void UpdateTolFromTopOrBottomPCurve(const TopoDS_Face& aFace, TopoDS_Edge& anEdge) { @@ -739,9 +705,6 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S, result = MkSw.Shape(); UpdateMap(TheS.Located(myProfile.Location()), result, myGenMap); myErrorOnSurf = MkSw.ErrorOnSurface(); - //Correct and - ReverseModifiedEdges(myFirst, myReversedEdges); - ReverseModifiedEdges(myLast, myReversedEdges); // Labeling of elements if (mySections.IsNull()) { diff --git a/src/BRepFill/BRepFill_PipeShell.cxx b/src/BRepFill/BRepFill_PipeShell.cxx index 519c6b5d0b..65ff2b28a0 100644 --- a/src/BRepFill/BRepFill_PipeShell.cxx +++ b/src/BRepFill/BRepFill_PipeShell.cxx @@ -583,28 +583,15 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1) //======================================================================= void BRepFill_PipeShell::DeleteProfile(const TopoDS_Shape& Profile) { - Standard_Boolean isVertex = (Profile.ShapeType() == TopAbs_VERTEX); - Standard_Boolean Trouve=Standard_False; Standard_Integer ii; for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) { - Standard_Boolean found = Standard_False; - const TopoDS_Wire& aWire = mySeq.Value(ii).Wire(); - if (isVertex) - { - TopExp_Explorer Explo(aWire, TopAbs_VERTEX); - for (; Explo.More(); Explo.Next()) - if (Profile.IsSame(Explo.Current())) - found = Standard_True; - } - else if (Profile.IsSame(aWire)) - found = Standard_True; - - if (found) - { - Trouve = Standard_True; - mySeq.Remove(ii); - } + const TopoDS_Shape& aSection = mySeq.Value(ii).OriginalShape(); + if (Profile.IsSame(aSection)) + { + Trouve = Standard_True; + mySeq.Remove(ii); + } } if (Trouve) mySection.Nullify(); @@ -914,13 +901,9 @@ const TopoDS_Shape& BRepFill_PipeShell::LastShape() const //function : Generated //purpose : //======================================================================= -// void BRepFill_PipeShell::Generated(const TopoDS_Shape& , -// TopTools_ListOfShape& ) void BRepFill_PipeShell::Generated(const TopoDS_Shape& theShape, TopTools_ListOfShape& theList) { - // throw Standard_NotImplemented("Generated:Pas Fait"); - theList.Clear(); if(myGenMap.IsBound(theShape)) { @@ -1197,9 +1180,6 @@ void BRepFill_PipeShell::Place(const BRepFill_Section& Sec, Sec.WithCorrection()); TopoDS_Wire TmpWire = Sec.Wire(); aTrsf = Place.Transformation(); - //TopLoc_Location Loc2(Place.Transformation()), Loc1; - //Loc1 = TmpWire.Location(); - //W.Location(Loc2.Multiplied(Loc1)); //Transform the copy W = TopoDS::Wire(BRepBuilderAPI_Transform(TmpWire, aTrsf, Standard_True)); //////////////////////////////////// @@ -1240,37 +1220,40 @@ void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep) TopoDS_Iterator itw; for (indw = 1; indw <= mySeq.Length(); indw++) { - const TopoDS_Wire& aSection = mySeq(indw).Wire(); + const TopoDS_Shape& Section = mySeq(indw).OriginalShape(); + TopoDS_Wire aSection; Standard_Boolean IsPunctual = mySeq(indw).IsPunctual(); if (IsPunctual) { //for punctual sections (first or last) //we take all the wires generated along the path - TopExp_Explorer Explo(aSection, TopAbs_VERTEX); - const TopoDS_Shape& VerSection = Explo.Current(); + TopTools_ListOfShape Elist; for (Standard_Integer i = 1; i <= anUEdges->UpperRow(); i++) for (Standard_Integer j = 1; j <= anUEdges->UpperCol(); j++) Elist.Append(anUEdges->Value(i,j)); - myGenMap.Bind(VerSection, Elist); + myGenMap.Bind(Section, Elist); continue; } + else + aSection = TopoDS::Wire(Section); //Take the real index of section on the path Standard_Integer IndOfW = myIndOfSec(indw); const TopoDS_Wire& theWire = TopoDS::Wire(WSeq(IndOfW)); BRepTools_WireExplorer wexp_sec(aSection); for (inde = 1; wexp_sec.More(); wexp_sec.Next()) { - const TopoDS_Edge& anEdge = TopoDS::Edge(wexp_sec.Current()); + const TopoDS_Edge& anOriginalEdge = TopoDS::Edge(wexp_sec.Current()); + TopoDS_Edge anEdge = TopoDS::Edge(mySeq(indw).ModifiedShape(anOriginalEdge)); if (BRep_Tool::Degenerated(anEdge)) continue; TopoDS_Shell aShell; BB.MakeShell(aShell); TopoDS_Vertex aVertex [2]; - TopExp::Vertices(anEdge, aVertex[0], aVertex[1]); + TopExp::Vertices(anOriginalEdge, aVertex[0], aVertex[1]); Standard_Integer SignOfAnEdge = - (anEdge.Orientation() == TopAbs_FORWARD)? 1 : -1; + (anOriginalEdge.Orientation() == TopAbs_FORWARD)? 1 : -1; //For each non-degenerated inde-th edge of //we find inde-th edge in @@ -1422,7 +1405,7 @@ void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep) TopTools_ListOfShape ListShell; ListShell.Append(aShell); - myGenMap.Bind(anEdge, ListShell); + myGenMap.Bind(anOriginalEdge, ListShell); //////////////////////// inde++; diff --git a/src/BRepFill/BRepFill_Section.cxx b/src/BRepFill/BRepFill_Section.cxx index b65b5f85c1..09e5d6f8a7 100644 --- a/src/BRepFill/BRepFill_Section.cxx +++ b/src/BRepFill/BRepFill_Section.cxx @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include BRepFill_Section::BRepFill_Section() :islaw(0), ispunctual(0), @@ -41,12 +44,19 @@ BRepFill_Section::BRepFill_Section(const TopoDS_Shape& Profile, contact(WithContact), correction(WithCorrection) { - if (Profile.ShapeType() == TopAbs_WIRE) - wire = TopoDS::Wire(Profile); - else if (Profile.ShapeType() == TopAbs_VERTEX) + myOriginalShape = Profile; + + ShapeUpgrade_RemoveLocations RemLoc; + RemLoc.SetRemoveLevel(TopAbs_COMPOUND); + RemLoc.Remove(Profile); + TopoDS_Shape aProfile = RemLoc.GetResult(); + + if (aProfile.ShapeType() == TopAbs_WIRE) + wire = TopoDS::Wire(aProfile); + else if (aProfile.ShapeType() == TopAbs_VERTEX) { ispunctual = Standard_True; - TopoDS_Vertex aVertex = TopoDS::Vertex(Profile); + TopoDS_Vertex aVertex = TopoDS::Vertex(aProfile); BRep_Builder BB; TopoDS_Edge DegEdge; @@ -67,3 +77,58 @@ void BRepFill_Section::Set(const Standard_Boolean IsLaw) { islaw = IsLaw; } + +TopoDS_Shape BRepFill_Section::ModifiedShape(const TopoDS_Shape& theShape) const +{ + TopoDS_Shape aModifiedShape; + + switch (theShape.ShapeType()) + { + case TopAbs_WIRE: + if (theShape.IsSame(myOriginalShape)) + aModifiedShape = wire; + break; + case TopAbs_EDGE: + { + TopoDS_Iterator itor(myOriginalShape); + TopoDS_Iterator itw(wire); + for (; itor.More(); itor.Next(),itw.Next()) + { + const TopoDS_Shape& anOriginalEdge = itor.Value(); + const TopoDS_Shape& anEdge = itw.Value(); + if (anOriginalEdge.IsSame(theShape)) + { + aModifiedShape = anEdge; + break; + } + } + } + break; + case TopAbs_VERTEX: + if (theShape.IsSame(myOriginalShape)) + { + TopExp_Explorer Explo(wire, TopAbs_VERTEX); + aModifiedShape = Explo.Current(); + } + else + { + TopExp_Explorer ExpOrig(myOriginalShape, TopAbs_VERTEX); + TopExp_Explorer ExpWire(wire, TopAbs_VERTEX); + for (; ExpOrig.More(); ExpOrig.Next(),ExpWire.Next()) + { + const TopoDS_Shape& anOriginalVertex = ExpOrig.Current(); + const TopoDS_Shape& aVertex = ExpWire.Current(); + if (anOriginalVertex.IsSame(theShape)) + { + aModifiedShape = aVertex; + break; + } + } + } + break; + default: + break; + } + + return aModifiedShape; +} diff --git a/src/BRepFill/BRepFill_Section.hxx b/src/BRepFill/BRepFill_Section.hxx index ede9091f05..10acf1decc 100644 --- a/src/BRepFill/BRepFill_Section.hxx +++ b/src/BRepFill/BRepFill_Section.hxx @@ -43,10 +43,14 @@ public: Standard_EXPORT void Set (const Standard_Boolean IsLaw); + const TopoDS_Shape& OriginalShape() const; + const TopoDS_Wire& Wire() const; const TopoDS_Vertex& Vertex() const; + Standard_EXPORT TopoDS_Shape ModifiedShape(const TopoDS_Shape& theShape) const; + Standard_Boolean IsLaw() const; Standard_Boolean IsPunctual() const; @@ -68,6 +72,7 @@ private: + TopoDS_Shape myOriginalShape; TopoDS_Wire wire; TopoDS_Vertex vertex; Standard_Boolean islaw; diff --git a/src/BRepFill/BRepFill_Section.lxx b/src/BRepFill/BRepFill_Section.lxx index 5b80bc996e..c96eaec01f 100644 --- a/src/BRepFill/BRepFill_Section.lxx +++ b/src/BRepFill/BRepFill_Section.lxx @@ -14,6 +14,11 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. +inline const TopoDS_Shape& BRepFill_Section::OriginalShape() const +{ + return myOriginalShape; +} + inline const TopoDS_Wire& BRepFill_Section::Wire() const { return wire; diff --git a/src/BRepFill/BRepFill_Sweep.cxx b/src/BRepFill/BRepFill_Sweep.cxx index 9e35334bbb..8b628e1518 100644 --- a/src/BRepFill/BRepFill_Sweep.cxx +++ b/src/BRepFill/BRepFill_Sweep.cxx @@ -366,6 +366,56 @@ static Standard_Boolean SameParameter(TopoDS_Edge& E, return Standard_True; } +static void CorrectSameParameter(TopoDS_Edge& theEdge, + const TopoDS_Face& theFace1, + const TopoDS_Face& theFace2) +{ + if (BRep_Tool::Degenerated(theEdge)) + return; + + Standard_Real fpar, lpar; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, fpar, lpar); + + Standard_Boolean PCurveExists [2] = {Standard_False, Standard_False}; + BRepAdaptor_Curve BAcurve [2]; + + if (!theFace1.IsNull()) + { + PCurveExists[0] = Standard_True; + BAcurve[0].Initialize(theEdge, theFace1); + } + if (!theFace1.IsNull() && + theFace1.IsSame(theFace2)) + theEdge.Reverse(); + if (!theFace2.IsNull()) + { + PCurveExists[1] = Standard_True; + BAcurve[1].Initialize(theEdge, theFace2); + } + + Standard_Real MaxSqDist = 0.; + const Standard_Integer NCONTROL = 23; + Standard_Real delta = (lpar - fpar)/NCONTROL; + + for (Standard_Integer i = 0; i <= NCONTROL; i++) + { + Standard_Real aParam = fpar + i*delta; + gp_Pnt aPnt = aCurve->Value(aParam); + for (Standard_Integer j = 0; j < 2; j++) + if (PCurveExists[j]) + { + gp_Pnt aPntFromFace = BAcurve[j].Value(aParam); + Standard_Real aSqDist = aPnt.SquareDistance(aPntFromFace); + if (aSqDist > MaxSqDist) + MaxSqDist = aSqDist; + } + } + + Standard_Real aTol = sqrt(MaxSqDist); + BRep_Builder BB; + BB.UpdateEdge(theEdge, aTol); +} + //======================================================================= //Objet : Orientate an edge of natural restriction // : General @@ -1661,6 +1711,60 @@ static Standard_Boolean IsDegen(const Handle(Geom_Surface)& S, return B; } +static void ReverseEdgeInFirstOrLastWire(TopoDS_Shape& theWire, + const TopoDS_Shape& theEdge) +{ + TopoDS_Shape EdgeToReverse; + TopoDS_Iterator itw(theWire); + + for (; itw.More(); itw.Next()) + { + const TopoDS_Shape& anEdge = itw.Value(); + if (anEdge.IsSame(theEdge)) + { + EdgeToReverse = anEdge; + break; + } + } + + if (!EdgeToReverse.IsNull()) + { + BRep_Builder BB; + theWire.Free(Standard_True); + BB.Remove(theWire, EdgeToReverse); + EdgeToReverse.Reverse(); + BB.Add(theWire, EdgeToReverse); + } +} + +static void ReverseModifiedEdges(TopoDS_Wire& theWire, + const TopTools_MapOfShape& theEmap) +{ + if (theEmap.IsEmpty()) + return; + + TopoDS_Iterator itw(theWire); + BRep_Builder BB; + + TopTools_ListOfShape Ledges; + for (; itw.More(); itw.Next()) + Ledges.Append(itw.Value()); + + theWire.Free(Standard_True); + TopTools_ListIteratorOfListOfShape itl(Ledges); + for (; itl.More(); itl.Next()) + BB.Remove(theWire, itl.Value()); + + for (itl.Initialize(Ledges); itl.More(); itl.Next()) + { + TopoDS_Shape anEdge = itl.Value(); + if (theEmap.Contains(anEdge)) + anEdge.Reverse(); + BB.Add(theWire, anEdge); + } +} + + //======================================================================= //function : Constructeur //purpose : @@ -2064,6 +2168,10 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, Standard_Boolean exuv, singu, singv; Handle(Geom_Surface) S; + //Correct and : reverse modified edges + ReverseModifiedEdges(FirstShape, ReversedEdges); + ReverseModifiedEdges(LastShape, ReversedEdges); + // (2.0) return preexisting Edges and vertices TopoDS_Edge E; TColStd_Array1OfBoolean IsBuilt(1, NbLaw); @@ -2293,7 +2401,6 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, // ---------- Creation of Vertex and edge ------------ - ReversedEdges.Clear(); for (ipath=1, IPath=IFirst; ipath<=NbPath; ipath++, IPath++) { for (isec=1; isec <=NbLaw; isec++) { @@ -2496,7 +2603,10 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, TopoDS::Edge(VEdge(isec, ipath)), ReversedEdges); if (ReversedEdges.Contains(VEdge(isec, ipath))) + { + ReverseEdgeInFirstOrLastWire(FirstShape, VEdge(isec, ipath)); StartEdges(isec).Reverse(); + } } } @@ -2536,6 +2646,8 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, RebuildTopOrBottomEdge(aNewLastEdge, TopoDS::Edge(VEdge(isec, ipath+1)), ReversedEdges); + if (ReversedEdges.Contains(VEdge(isec, ipath+1))) + ReverseEdgeInFirstOrLastWire(LastShape, VEdge(isec, ipath+1)); } } } @@ -2877,6 +2989,30 @@ void BRepFill_Sweep::Build(TopTools_MapOfShape& ReversedEdges, } } + //Ensure Same Parameter on U-edges + for (ii = myUEdges->LowerRow(); ii <= myUEdges->UpperRow(); ii++) + { + if (mySec->IsUClosed() && ii == myUEdges->UpperRow()) + continue; + for (jj = myUEdges->LowerCol(); jj <= myUEdges->UpperCol(); jj++) + { + TopoDS_Edge anEdge = TopoDS::Edge(myUEdges->Value(ii, jj)); + if (anEdge.IsNull()) + continue; + TopoDS_Face Face1, Face2; + Standard_Integer i1 = ii-1, i2 = ii; + if (i1 == 0 && mySec->IsUClosed()) + i1 = myFaces->UpperRow(); + if (i2 > myFaces->UpperRow()) + i2 = 0; + if (i1 != 0) + Face1 = TopoDS::Face(myFaces->Value(i1, jj)); + if (i2 != 0) + Face2 = TopoDS::Face(myFaces->Value(i2, jj)); + CorrectSameParameter(anEdge, Face1, Face2); + } + } + for (ii = 1; ii <= NbLaw; ii++) for (jj = 1; jj <= NbPath; jj++) { @@ -3083,7 +3219,7 @@ TopoDS_Shape BRepFill_Sweep::Tape(const Standard_Integer Index) const } } - BRepFill_TrimShellCorner aTrim(aFaces, AxeOfBisPlane, aPlaneF); + BRepFill_TrimShellCorner aTrim(aFaces, Transition, AxeOfBisPlane); aTrim.AddBounds(Bounds); aTrim.AddUEdges(aUEdges); aTrim.Perform(); diff --git a/src/BRepFill/BRepFill_TrimShellCorner.cxx b/src/BRepFill/BRepFill_TrimShellCorner.cxx index 9d3e925ca6..0083bf8e23 100644 --- a/src/BRepFill/BRepFill_TrimShellCorner.cxx +++ b/src/BRepFill/BRepFill_TrimShellCorner.cxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,23 @@ #include #include #include +#include + +static TopoDS_Edge FindEdgeCloseToBisectorPlane(const TopoDS_Vertex& theVertex, + TopoDS_Compound& theComp, + const gp_Ax1& theAxis); + +static Standard_Boolean FindMiddleEdges(const TopoDS_Vertex& theVertex1, + const TopoDS_Vertex& theVertex2, + const gp_Ax1& theAxis, + TopoDS_Compound& theComp, + TopTools_ListOfShape& theElist); + +static Standard_Boolean FindCommonVertex(const TopoDS_Edge& theFirstEdge, + const TopoDS_Edge& theLastEdge, + const TopoDS_Vertex& theFirstVertex, + const TopoDS_Vertex& theLastVertex, + TopoDS_Vertex& theCommonVertex); static Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS, const Standard_Integer theEIndex1, @@ -71,24 +89,6 @@ static Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS, Standard_Real& theParamOnE1, Standard_Real& theParamOnE2); -static Standard_Boolean MakeFacesNonSec(const Standard_Integer theIndex, - const Handle(TopTools_HArray2OfShape)& theUEdges, - const Handle(TopTools_HArray2OfShape)& theBounds, - const BOPDS_PDS& theDS, - const Standard_Integer theFaceIndex1, - const Standard_Integer theFaceIndex2, - TopTools_DataMapOfShapeListOfShape& theHistMap); - -static Standard_Boolean MakeFacesSec(const Standard_Integer theIndex, - const Handle(TopTools_HArray2OfShape)& theUEdges, - const Handle(TopTools_HArray2OfShape)& theBounds, - const BOPDS_PDS& theDS, - const Standard_Integer theFaceIndex1, - const Standard_Integer theFaceIndex2, - const Standard_Integer theSSInterfIndex, - const gp_Ax2& AxeOfBisPlane, - TopTools_DataMapOfShapeListOfShape& theHistMap); - static Standard_Boolean SplitUEdges(const Handle(TopTools_HArray2OfShape)& theUEdges, const BOPDS_PDS& theDS, TopTools_DataMapOfShapeListOfShape& theHistMap); @@ -186,55 +186,27 @@ static Standard_Real ComputeAveragePlaneAndMaxDeviation(const TopoDS_Shape& aWir gp_Pln& thePlane, Standard_Boolean& IsSingular); -static Standard_Boolean ChooseSection(const TopoDS_Shape& Comp, - const gp_Ax2& bis, - TopoDS_Shape& resWire, - gp_Pln& resPlane, - Standard_Boolean& IsSingular); +static void UpdateSectionEdge(TopoDS_Edge& theEdge, + const TopoDS_Vertex& theConstVertex, + TopoDS_Vertex& theVertex, + const Standard_Real theParam); + // =========================================================================================== // function: Constructor // purpose: // =========================================================================================== BRepFill_TrimShellCorner::BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, - const gp_Ax2& theAxeOfBisPlane, - const TopoDS_Face& theSecPlane) : -myAxeOfBisPlane(theAxeOfBisPlane), -myDone(Standard_False), -myHasSection(Standard_False) + const BRepFill_TransitionStyle theTransition, + const gp_Ax2& theAxeOfBisPlane) : + myTransition(theTransition), + myAxeOfBisPlane(theAxeOfBisPlane), + myDone(Standard_False), + myHasSection(Standard_False) { myFaces = new TopTools_HArray2OfShape(theFaces->LowerRow(), theFaces->UpperRow(), theFaces->LowerCol(), theFaces->UpperCol()); myFaces->ChangeArray2() = theFaces->Array2(); - mySecPln = theSecPlane; -} - -// =========================================================================================== -// function: Constructor -// purpose: -// =========================================================================================== -BRepFill_TrimShellCorner::BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, - const gp_Ax2& theAxeOfBisPlane, - const TopoDS_Wire& theSpine, - const TopoDS_Face& theSecPlane): -myAxeOfBisPlane(theAxeOfBisPlane), -myDone(Standard_False), -myHasSection(Standard_False) -{ - myFaces = new TopTools_HArray2OfShape(theFaces->LowerRow(), theFaces->UpperRow(), - theFaces->LowerCol(), theFaces->UpperCol()); - myFaces->ChangeArray2() = theFaces->Array2(); - mySpine = theSpine; - mySecPln = theSecPlane; -} - -// =========================================================================================== -// function: SetSpine -// purpose: -// =========================================================================================== -void BRepFill_TrimShellCorner::SetSpine(const TopoDS_Wire& theSpine) -{ - mySpine = theSpine; } // =========================================================================================== @@ -351,14 +323,13 @@ void BRepFill_TrimShellCorner::Perform() } if(!bhassec) { - if(!MakeFacesNonSec(ii, myUEdges, myBounds, theDS, anIndex1, anIndex2, myHistMap)) { + if(!MakeFacesNonSec(ii, theDS, anIndex1, anIndex2)) { myHistMap.Clear(); return; } } else { - if(!MakeFacesSec(ii, myUEdges, myBounds, theDS, anIndex1, anIndex2, - i, myAxeOfBisPlane, myHistMap)) { + if(!MakeFacesSec(ii, theDS, anIndex1, anIndex2, i)) { myHistMap.Clear(); return; } @@ -403,23 +374,21 @@ void BRepFill_TrimShellCorner::Modified(const TopoDS_Shape& theShape, } // ---------------------------------------------------------------------------------------------------- -// static function: MakeFacesNonSec -// purpose: +// function: MakeFacesNonSec +// purpose: Updates by new faces in the case when old faces do not intersect // ---------------------------------------------------------------------------------------------------- -Standard_Boolean MakeFacesNonSec(const Standard_Integer theIndex, - const Handle(TopTools_HArray2OfShape)& theUEdges, - const Handle(TopTools_HArray2OfShape)& theBounds, - const BOPDS_PDS& theDS, - const Standard_Integer theFaceIndex1, - const Standard_Integer theFaceIndex2, - TopTools_DataMapOfShapeListOfShape& theHistMap) +Standard_Boolean +BRepFill_TrimShellCorner::MakeFacesNonSec(const Standard_Integer theIndex, + const BOPDS_PDS& theDS, + const Standard_Integer theFaceIndex1, + const Standard_Integer theFaceIndex2) { Standard_Boolean bHasNewEdge = Standard_False; TopoDS_Edge aNewEdge; BRep_Builder aBB; - const TopoDS_Shape& aE1 = theBounds->Value(theIndex, 1); - const TopoDS_Shape& aE2 = theBounds->Value(theIndex, 2); + const TopoDS_Shape& aE1 = myBounds->Value(theIndex, 1); + const TopoDS_Shape& aE2 = myBounds->Value(theIndex, 2); // search common vertex between bounds. begin TopoDS_Vertex aCommonVertex; @@ -439,20 +408,20 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI Standard_Integer ueit = 0, eindex = 0; for(ueit = 1, eindex = theIndex; ueit <= 2; ueit++, eindex++) { - const TopoDS_Shape& aShape1 = theUEdges->Value(eindex, theUEdges->LowerCol()); - const TopoDS_Shape& aShape2 = theUEdges->Value(eindex, theUEdges->UpperCol()); + const TopoDS_Shape& aShape1 = myUEdges->Value(eindex, myUEdges->LowerCol()); + const TopoDS_Shape& aShape2 = myUEdges->Value(eindex, myUEdges->UpperCol()); TopoDS_Edge aUE1 = TopoDS::Edge(aShape1); TopoDS_Edge aUE2 = TopoDS::Edge(aShape2); - if(theHistMap.IsBound(aShape1)) { - const TopTools_ListOfShape& lst = theHistMap.Find(aShape1); + if (myHistMap.IsBound(aShape1)) { + const TopTools_ListOfShape& lst = myHistMap.Find(aShape1); if(!lst.IsEmpty()) aUE1 = TopoDS::Edge(lst.First()); } - if(theHistMap.IsBound(aShape2)) { - const TopTools_ListOfShape& lst = theHistMap.Find(aShape2); + if (myHistMap.IsBound(aShape2)) { + const TopTools_ListOfShape& lst = myHistMap.Find(aShape2); if(!lst.IsEmpty()) aUE2 = TopoDS::Edge(lst.First()); @@ -499,11 +468,11 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI aBB.MakeCompound(aComp); for(ueit = 1, eindex = theIndex; ueit <= 2; ueit++, eindex++) { - const TopoDS_Shape& aShape = theUEdges->Value(eindex, theUEdges->LowerCol() + fit - 1); + const TopoDS_Shape& aShape = myUEdges->Value(eindex, myUEdges->LowerCol() + fit - 1); TopoDS_Shape aUE = aShape; - if(theHistMap.IsBound(aShape)) { - const TopTools_ListOfShape& lst = theHistMap.Find(aShape); + if(myHistMap.IsBound(aShape)) { + const TopTools_ListOfShape& lst = myHistMap.Find(aShape); if(!lst.IsEmpty()) aUE = TopoDS::Edge(lst.First()); @@ -638,7 +607,7 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI aNewFace.Orientation(aFaceOri); TopTools_ListOfShape atmpList; atmpList.Append(aNewFace); - theHistMap.Bind(aFace, atmpList); + myHistMap.Bind(aFace, atmpList); anExpE.Init(aFace, TopAbs_EDGE); @@ -648,7 +617,7 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI if(aNewValue.IsNull() || aNewValue.IsSame(anExpE.Current())) continue; - if(theHistMap.IsBound(anExpE.Current())) + if (myHistMap.IsBound(anExpE.Current())) continue; TopTools_ListOfShape aListOfNewEdge; TopExp_Explorer anExpE2(aNewValue, TopAbs_EDGE); @@ -656,7 +625,7 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI for(; anExpE2.More(); anExpE2.Next()) { aListOfNewEdge.Append(anExpE2.Current()); } - theHistMap.Bind(anExpE.Current(), aListOfNewEdge); + myHistMap.Bind(anExpE.Current(), aListOfNewEdge); } } @@ -664,18 +633,15 @@ Standard_Boolean MakeFacesNonSec(const Standard_Integer theI } // ---------------------------------------------------------------------------------------------------- -// static function: MakeFacesSec -// purpose: +// function: MakeFacesSec +// purpose: Updates by new faces in the case when old faces intersect each other // ---------------------------------------------------------------------------------------------------- -Standard_Boolean MakeFacesSec(const Standard_Integer theIndex, - const Handle(TopTools_HArray2OfShape)& theUEdges, - const Handle(TopTools_HArray2OfShape)& theBounds, - const BOPDS_PDS& theDS, - const Standard_Integer theFaceIndex1, - const Standard_Integer theFaceIndex2, - const Standard_Integer theSSInterfIndex, - const gp_Ax2& AxeOfBisPlane, - TopTools_DataMapOfShapeListOfShape& theHistMap) +Standard_Boolean +BRepFill_TrimShellCorner::MakeFacesSec(const Standard_Integer theIndex, + const BOPDS_PDS& theDS, + const Standard_Integer theFaceIndex1, + const Standard_Integer theFaceIndex2, + const Standard_Integer theSSInterfIndex) { const BOPDS_VectorOfInterfFF& aFFs = theDS->InterfFF(); const BOPDS_InterfFF& aFFi = aFFs(theSSInterfIndex); @@ -687,10 +653,30 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde if(!FilterSectionEdges(aBCurves, aSecPlane, theDS, aSecEdges)) return Standard_False; + //Extract vertices on the intersection of correspondent U-edges + const TopoDS_Shape& LeftE1 = myUEdges->Value(theIndex, 1); + const TopoDS_Shape& LeftE2 = myUEdges->Value(theIndex, 2); + const TopoDS_Shape& RightE1 = myUEdges->Value(theIndex+1, 1); + const TopoDS_Shape& RightE2 = myUEdges->Value(theIndex+1, 2); + + Standard_Integer IndexOfLeftE1 = theDS->Index(LeftE1); + Standard_Integer IndexOfLeftE2 = theDS->Index(LeftE2); + Standard_Integer IndexOfRightE1 = theDS->Index(RightE1); + Standard_Integer IndexOfRightE2 = theDS->Index(RightE2); + + TopoDS_Vertex FirstVertex, LastVertex; + Standard_Real ParamOnLeftE1, ParamOnLeftE2, ParamOnRightE1, ParamOnRightE2; + FindCommonVertex(theDS, IndexOfLeftE1, IndexOfLeftE2, + FirstVertex, ParamOnLeftE1, ParamOnLeftE2); + FindCommonVertex(theDS, IndexOfRightE1, IndexOfRightE2, + LastVertex, ParamOnRightE1, ParamOnRightE2); + TopoDS_Shape SecWire; gp_Pln SecPlane; Standard_Boolean IsSingular; - Standard_Boolean WireFound = ChooseSection( aSecEdges, AxeOfBisPlane, SecWire, SecPlane, IsSingular ); + Standard_Boolean WireFound = ChooseSection(aSecEdges, + FirstVertex, LastVertex, + SecWire, SecPlane, IsSingular ); if(WireFound) { //aSecEdges = SecWire; @@ -715,19 +701,19 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde TopAbs_Orientation aFaceOri = aFace.Orientation(); TopoDS_Face aFaceF = aFace; aFaceF.Orientation(TopAbs_FORWARD); - TopoDS_Edge aBoundEdge = TopoDS::Edge(theBounds->Value(theIndex, theBounds->LowerCol() +fit)); + TopoDS_Edge aBoundEdge = TopoDS::Edge(myBounds->Value(theIndex, myBounds->LowerCol() +fit)); Standard_Integer aBoundEdgeIndex = theDS->Index(aBoundEdge); TopoDS_Edge aUE1; TopoDS_Edge aUE2; - if(!GetUEdges(theIndex, fit, theUEdges, aBoundEdge, aFaceF, aUE1, aUE2)) + if(!GetUEdges(theIndex, fit, myUEdges, aBoundEdge, aFaceF, aUE1, aUE2)) return Standard_False; TopoDS_Edge aUE1old = aUE1; TopoDS_Edge aUE2old = aUE2; - if(theHistMap.IsBound(aUE1)) { - const TopTools_ListOfShape& lst = theHistMap.Find(aUE1); + if (myHistMap.IsBound(aUE1)) { + const TopTools_ListOfShape& lst = myHistMap.Find(aUE1); if(!lst.IsEmpty()) { const TopoDS_Shape& anEdge = lst.First().Oriented(aUE1.Orientation()); @@ -738,8 +724,8 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde } } - if(theHistMap.IsBound(aUE2)) { - const TopTools_ListOfShape& lst = theHistMap.Find(aUE2); + if (myHistMap.IsBound(aUE2)) { + const TopTools_ListOfShape& lst = myHistMap.Find(aUE2); if(!lst.IsEmpty()) { const TopoDS_Shape& anEdge = lst.First().Oriented(aUE2.Orientation()); @@ -757,12 +743,12 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde Standard_Boolean isPave1OnUEdge = Standard_True; if(FindFromUEdge(aUE1old, aUE2old, aUE1, aUE2, aFace, aSecEdges, fit, aBoundEdge, aBoundEdgeIndex, - theDS, theHistMap, aCompOfSecEdges, aListOfWireEdges, aPave1, isPave1OnUEdge)) { + theDS, myHistMap, aCompOfSecEdges, aListOfWireEdges, aPave1, isPave1OnUEdge)) { TopTools_ListOfShape aSecondListOfEdges; Standard_Boolean bisSectionFound = Standard_False; if(!FindFromVEdge(aPave1, isPave1OnUEdge, aUE1old, aUE2old, aFace, aCompOfSecEdges, fit, aBoundEdge, - aBoundEdgeIndex, theDS, theHistMap, aSecondListOfEdges, bisSectionFound)) { + aBoundEdgeIndex, theDS, myHistMap, aSecondListOfEdges, bisSectionFound)) { return Standard_False; } @@ -792,7 +778,7 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde aNewFace.Orientation(aFaceOri); TopTools_ListOfShape atmpList; atmpList.Append(aNewFace); - theHistMap.Bind(aFace, atmpList); + myHistMap.Bind(aFace, atmpList); TopExp_Explorer anExpE(aFace, TopAbs_EDGE); @@ -802,7 +788,7 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde if(aNewValue.IsNull() || aNewValue.IsSame(anExpE.Current())) continue; - if(theHistMap.IsBound(anExpE.Current())) + if (myHistMap.IsBound(anExpE.Current())) continue; TopTools_ListOfShape aListOfNewEdge; TopExp_Explorer anExpE2(aNewValue, TopAbs_EDGE); @@ -810,12 +796,240 @@ Standard_Boolean MakeFacesSec(const Standard_Integer theInde for(; anExpE2.More(); anExpE2.Next()) { aListOfNewEdge.Append(anExpE2.Current()); } - theHistMap.Bind(anExpE.Current(), aListOfNewEdge); + myHistMap.Bind(anExpE.Current(), aListOfNewEdge); } } return Standard_True; } +//======================================================================= +//function : ChooseSection +//purpose : +//======================================================================= +Standard_Boolean BRepFill_TrimShellCorner::ChooseSection(const TopoDS_Shape& Comp, + const TopoDS_Vertex& theFirstVertex, + const TopoDS_Vertex& theLastVertex, + TopoDS_Shape& resWire, + gp_Pln& resPlane, + Standard_Boolean& IsSingular) +{ + IsSingular = Standard_False; + + Standard_Integer ind, i, j; + BRep_Builder BB; + + if (myTransition == BRepFill_Right && + !theFirstVertex.IsNull() && + !theLastVertex.IsNull()) //the case where section wire goes from + //its known first vertex to its known last vertex + { + TopoDS_Wire NewWire; + BB.MakeWire(NewWire); + + TopoDS_Compound OldComp; + BB.MakeCompound( OldComp ); + TopoDS_Iterator iter( Comp ); + for (; iter.More(); iter.Next()) + BB.Add( OldComp, iter.Value() ); + + TopoDS_Edge FirstEdge = FindEdgeCloseToBisectorPlane(theFirstVertex, + OldComp, + myAxeOfBisPlane.Axis()); + iter.Initialize(OldComp); + if (!iter.More()) + { + iter.Initialize(Comp); + BB.Add( OldComp, iter.Value() ); + } + TopoDS_Edge LastEdge = FindEdgeCloseToBisectorPlane(theLastVertex, + OldComp, + myAxeOfBisPlane.Axis()); + + BB.Add(NewWire, FirstEdge); + + if (!FirstEdge.IsSame(LastEdge)) + { + TopoDS_Vertex aCommonVertex; + Standard_Boolean CommonVertexExists = FindCommonVertex(FirstEdge, LastEdge, + theFirstVertex, theLastVertex, + aCommonVertex); + if (CommonVertexExists) + BB.Add(NewWire, LastEdge); + else + { + TopoDS_Vertex Vertex1, Vertex2, V1, V2; + TopExp::Vertices(FirstEdge, V1, V2); + Vertex1 = (theFirstVertex.IsSame(V1))? V2 : V1; + TopExp::Vertices(LastEdge, V1, V2); + Vertex2 = (theLastVertex.IsSame(V1))? V2 : V1; + + TopTools_ListOfShape MiddleEdges; + if (FindMiddleEdges(Vertex1, Vertex2, myAxeOfBisPlane.Axis(), OldComp, MiddleEdges)) + { + TopTools_ListIteratorOfListOfShape itl(MiddleEdges); + for (; itl.More(); itl.Next()) + BB.Add(NewWire, itl.Value()); + BB.Add(NewWire, LastEdge); + } + else + { + //trim and in the points of extrema + //these points become new vertex with centre between them + BRepExtrema_ExtCC Extrema(FirstEdge, LastEdge); + if (Extrema.IsDone() && Extrema.NbExt() > 0) + { + Standard_Integer imin = 1; + for (i = 2; i <= Extrema.NbExt(); i++) + if (Extrema.SquareDistance(i) < Extrema.SquareDistance(imin)) + imin = i; + + Standard_Real aMinDist = sqrt(Extrema.SquareDistance(imin)); + Standard_Real ParamOnFirstEdge = Extrema.ParameterOnE1(imin); + Standard_Real ParamOnLastEdge = Extrema.ParameterOnE2(imin); + gp_Pnt PointOnFirstEdge = Extrema.PointOnE1(imin); + gp_Pnt PointOnLastEdge = Extrema.PointOnE2(imin); + gp_Pnt MidPnt((PointOnFirstEdge.XYZ() + PointOnLastEdge.XYZ())/2); + aCommonVertex = BRepLib_MakeVertex(MidPnt); + BB.UpdateVertex(aCommonVertex, 1.001*aMinDist/2); + + UpdateSectionEdge(FirstEdge, theFirstVertex, aCommonVertex, ParamOnFirstEdge); + UpdateSectionEdge(LastEdge, theLastVertex, aCommonVertex, ParamOnLastEdge); + + BB.Add(NewWire, LastEdge); + } + } + } + } + + resWire = NewWire; + resPlane = gp_Pln(myAxeOfBisPlane); + return Standard_True; + } + + //General case: try to find continuous section closest to bisector plane + TopoDS_Compound OldComp; + BRep_Builder B; + B.MakeCompound( OldComp ); + TopoDS_Iterator iter( Comp ); + for (; iter.More(); iter.Next()) + B.Add( OldComp, iter.Value() ); + + Standard_Boolean anError = Standard_False; + //TopoDS_Wire NewWire [2]; + TopTools_SequenceOfShape Wseq; + for (;;) + { + TopExp_Explorer explo( OldComp, TopAbs_EDGE ); + if (!explo.More()) + break; + TopoDS_Edge FirstEdge = TopoDS::Edge( explo.Current() ); + TopoDS_Wire NewWire = BRepLib_MakeWire( FirstEdge ); + B.Remove( OldComp, FirstEdge ); + if (NewWire.Closed()) + { + Wseq.Append(NewWire); + continue; + } + + for (;;) + { + TopoDS_Vertex Extremity [2]; + TopExp::Vertices( NewWire, Extremity[0], Extremity[1] ); + if (Extremity[0].IsNull() || Extremity[1].IsNull()) + { + anError = Standard_True; + break; + } + TopTools_IndexedDataMapOfShapeListOfShape VEmap; + TopExp::MapShapesAndAncestors( OldComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); + TopTools_ListOfShape Vedges [2]; + for (j = 0; j < 2; j++) + if (VEmap.Contains( Extremity[j] )) + Vedges[j] = VEmap.FindFromKey( Extremity[j] ); + if (Vedges[0].IsEmpty() && Vedges[1].IsEmpty()) + //no more edges in OldComp to continue NewWire + break; + Standard_Boolean Modified = Standard_False; + for (j = 0; j < 2; j++) + { + if (Vedges[j].Extent() == 1) + { + const TopoDS_Edge& anEdge = TopoDS::Edge( Vedges[j].First() ); + NewWire = BRepLib_MakeWire( NewWire, anEdge ); + B.Remove( OldComp, anEdge ); + Modified = Standard_True; + } + } + if (!Modified) //only multiple connections + { + ind = (Vedges[0].IsEmpty())? 1 : 0; + TopTools_SequenceOfShape Edges; + TopTools_ListIteratorOfListOfShape itl( Vedges[ind] ); + for (; itl.More(); itl.Next()) + Edges.Append( itl.Value() ); + Standard_Integer theind=0; + Standard_Real MinDeviation = RealLast(); + for (j = 1; j <= Edges.Length(); j++) + { + TopoDS_Wire aWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(j)) ); + gp_Pln aPlane; + Standard_Boolean issing; + Standard_Real Deviation = ComputeAveragePlaneAndMaxDeviation( aWire, aPlane, issing ); + if (Deviation < MinDeviation) + { + MinDeviation = Deviation; + theind = j; + } + } + NewWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(theind)) ); + B.Remove( OldComp, Edges(theind) ); + } + if (NewWire.Closed()) + break; + } + Wseq.Append(NewWire); + if (anError) + break; + } + + Standard_Real MinAngle = RealLast(); + TopExp_Explorer Explo( OldComp, TopAbs_EDGE ); + if (!anError && !Explo.More()) //wires are built successfully and compound is empty + { + if (Wseq.Length() == 1) //only one wire => it becomes result + { + resWire = Wseq.First(); + ComputeAveragePlaneAndMaxDeviation( resWire, resPlane, IsSingular ); + return Standard_True; + } + else //we must choose the wire which average plane is closest to bisector plane + { //(check angle between axes) + for (i = 1; i <= Wseq.Length(); i++) + { + TopoDS_Wire aWire = TopoDS::Wire( Wseq(i) ); + gp_Pln aPln; + Standard_Boolean issing; + ComputeAveragePlaneAndMaxDeviation( aWire, aPln, issing ); + if (issing) + continue; + + Standard_Real Angle = aPln.Axis().Angle( myAxeOfBisPlane.Axis() ); + if (Angle > M_PI/2) + Angle = M_PI - Angle; + + if (Angle < MinAngle) + { + MinAngle = Angle; + resWire = aWire; + resPlane = aPln; + } + } + return Standard_True; + } + } + return Standard_False; +} + // ------------------------------------------------------------------------------------------ // static function: SplitUEdges @@ -966,13 +1180,15 @@ Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS, continue; IntTools_CommonPrt aCP = aEE.CommonPart(); - if(aCP.Type() == TopAbs_VERTEX) { + if(aCP.Type() == TopAbs_VERTEX) + { theCommonVertex = *(TopoDS_Vertex*)&theDS->Shape(aEE.IndexNew()); - if (theEIndex1 == aEE.Index1()) { + + if (theEIndex1 == aEE.Index1()) IntTools_Tools::VertexParameters(aCP, theParamOnE1, theParamOnE2); - } else { + else IntTools_Tools::VertexParameters(aCP, theParamOnE2, theParamOnE1); - } + // bvertexfound = Standard_True; break; @@ -2004,147 +2220,182 @@ static Standard_Real ComputeAveragePlaneAndMaxDeviation(const TopoDS_Shape& aWir return MaxDeviation; } -//======================================================================= -//function : ChooseSection -//purpose : -//======================================================================= -static Standard_Boolean ChooseSection(const TopoDS_Shape& Comp, - const gp_Ax2& bis, - TopoDS_Shape& resWire, - gp_Pln& resPlane, - Standard_Boolean& IsSingular) + +static void UpdateSectionEdge(TopoDS_Edge& theEdge, + const TopoDS_Vertex& theConstVertex, + TopoDS_Vertex& theVertex, + const Standard_Real theParam) { - IsSingular = Standard_False; - Standard_Real TolDeviation = 0.01; //, TolConf = 1.e-4, TolAng = 1.e-5; + TopoDS_Edge F_Edge = theEdge; + F_Edge.Orientation(TopAbs_FORWARD); + + TopAbs_Orientation OrOfVertex; + TopoDS_Vertex V1, V2, AnotherVertex; + TopExp::Vertices(F_Edge, V1, V2); + if (theConstVertex.IsSame(V1)) + { + //OrOfConst = TopAbs_FORWARD; + OrOfVertex = TopAbs_REVERSED; + AnotherVertex = V2; + } + else + { + //OrOfConst = TopAbs_REVERSED; + OrOfVertex = TopAbs_FORWARD; + AnotherVertex = V1; + } -// Standard_Integer N = 100; - Standard_Integer ind, i, j; + BRep_Builder BB; + Standard_Real fpar, lpar; + BRep_Tool::Range(F_Edge, fpar, lpar); + if (OrOfVertex == TopAbs_FORWARD) + fpar = theParam; + else + lpar = theParam; + BB.Range(F_Edge, fpar, lpar); - //Simplest case - TopoDS_Compound OldComp; - BRep_Builder B; - B.MakeCompound( OldComp ); - TopoDS_Iterator iter( Comp ); - for (; iter.More(); iter.Next()) - B.Add( OldComp, iter.Value() ); - - Standard_Boolean anError = Standard_False; - //TopoDS_Wire NewWire [2]; - TopTools_SequenceOfShape Wseq; - for (;;) - { - TopExp_Explorer explo( OldComp, TopAbs_EDGE ); - if (!explo.More()) - break; - TopoDS_Edge FirstEdge = TopoDS::Edge( explo.Current() ); - TopoDS_Wire NewWire = BRepLib_MakeWire( FirstEdge ); - B.Remove( OldComp, FirstEdge ); - if (NewWire.Closed()) - { - Wseq.Append(NewWire); - continue; - } - - for (;;) - { - TopoDS_Vertex Extremity [2]; - TopExp::Vertices( NewWire, Extremity[0], Extremity[1] ); - if (Extremity[0].IsNull() || Extremity[1].IsNull()) - { - anError = Standard_True; - break; - } - TopTools_IndexedDataMapOfShapeListOfShape VEmap; - TopExp::MapShapesAndAncestors( OldComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); - TopTools_ListOfShape Vedges [2]; - for (j = 0; j < 2; j++) - if (VEmap.Contains( Extremity[j] )) - Vedges[j] = VEmap.FindFromKey( Extremity[j] ); - if (Vedges[0].IsEmpty() && Vedges[1].IsEmpty()) - //no more edges in OldComp to continue NewWire - break; - Standard_Boolean Modified = Standard_False; - for (j = 0; j < 2; j++) - { - if (Vedges[j].Extent() == 1) - { - const TopoDS_Edge& anEdge = TopoDS::Edge( Vedges[j].First() ); - NewWire = BRepLib_MakeWire( NewWire, anEdge ); - B.Remove( OldComp, anEdge ); - Modified = Standard_True; - } - } - if (!Modified) //only multiple connections - { - ind = (Vedges[0].IsEmpty())? 1 : 0; - TopTools_SequenceOfShape Edges; - TopTools_ListIteratorOfListOfShape itl( Vedges[ind] ); - for (; itl.More(); itl.Next()) - Edges.Append( itl.Value() ); - Standard_Integer theind=0; - Standard_Real MinDeviation = RealLast(); - for (j = 1; j <= Edges.Length(); j++) - { - TopoDS_Wire aWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(j)) ); - gp_Pln aPlane; - Standard_Boolean issing; - Standard_Real Deviation = ComputeAveragePlaneAndMaxDeviation( aWire, aPlane, issing ); - if (Deviation < MinDeviation) - { - MinDeviation = Deviation; - theind = j; - } - } - NewWire = BRepLib_MakeWire( NewWire, TopoDS::Edge(Edges(theind)) ); - B.Remove( OldComp, Edges(theind) ); - } - if (NewWire.Closed()) - break; - } - Wseq.Append(NewWire); - if (anError) - break; - } - - Standard_Real Deviation=0.; - Standard_Real MinAngle = RealLast(); - TopExp_Explorer Explo( OldComp, TopAbs_EDGE ); - if (!anError && !Explo.More()) - { - if (Wseq.Length() == 1) - { - resWire = Wseq.First(); - Deviation = ComputeAveragePlaneAndMaxDeviation( resWire, resPlane, IsSingular ); - return Standard_True; - } - else - { - for (i = 1; i <= Wseq.Length(); i++) - { - TopoDS_Wire aWire = TopoDS::Wire( Wseq(i) ); - gp_Pln aPln; - Standard_Boolean issing; - Standard_Real aDeviation = - ComputeAveragePlaneAndMaxDeviation( aWire, aPln, issing ); - if (issing) - continue; - - Standard_Real Angle = aPln.Axis().Angle( bis.Axis() ); - if (Angle > M_PI/2) - Angle = M_PI - Angle; - - if (Angle < MinAngle) - { - MinAngle = Angle; - resWire = aWire; - resPlane = aPln; - Deviation = aDeviation; - } - } - if (Deviation <= TolDeviation) - return Standard_True; - } - } - return Standard_False; - //end of simplest case + F_Edge.Free(Standard_True); + BB.Remove(F_Edge, AnotherVertex); + theVertex.Orientation(OrOfVertex); + BB.Add(F_Edge, theVertex); +} + +//Finds the edge connected to in the compound +//that is closest to bisector plane angularly. +//Removes found edge from +// is the axis of bisector plane +static TopoDS_Edge FindEdgeCloseToBisectorPlane(const TopoDS_Vertex& theVertex, + TopoDS_Compound& theComp, + const gp_Ax1& theAxis) +{ + TopTools_IndexedDataMapOfShapeListOfShape VEmap; + TopExp::MapShapesAndAncestors( theComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); + + TopoDS_Edge MinEdge; + if (!VEmap.Contains(theVertex)) + return MinEdge; + + BRep_Builder BB; + + const TopTools_ListOfShape& Edges = VEmap.FindFromKey(theVertex); + if (Edges.Extent() == 1) + MinEdge = TopoDS::Edge(Edges.First()); + else + { + TopTools_ListIteratorOfListOfShape itl(Edges); + Standard_Real MinAngle = RealLast(); + for (; itl.More(); itl.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); + TopoDS_Wire aWire; + BB.MakeWire(aWire); + BB.Add(aWire, anEdge); + gp_Pln aPln; + Standard_Boolean issing; + ComputeAveragePlaneAndMaxDeviation( aWire, aPln, issing ); + Standard_Real anAngle; + if (issing) //edge is a segment of line + { + // is angle between and its projection on bisector plane + BRepAdaptor_Curve BAcurve(anEdge); + gp_Pnt FirstPnt = BAcurve.Value(BAcurve.FirstParameter()); + gp_Pnt LastPnt = BAcurve.Value(BAcurve.LastParameter()); + gp_Vec EdgeVec(FirstPnt, LastPnt); + gp_Ax1 EdgeAxis(FirstPnt, EdgeVec); + anAngle = EdgeAxis.Direction().Angle(theAxis.Direction()); + if (anAngle > M_PI/2) + anAngle = M_PI - anAngle; + anAngle = M_PI/2 - anAngle; + } + else + { + anAngle = aPln.Axis().Angle( theAxis ); + if (anAngle > M_PI/2) + anAngle = M_PI - anAngle; + } + + if (anAngle < MinAngle) + { + MinAngle = anAngle; + MinEdge = anEdge; + } + } + } //else (more than one edge) + + BB.Remove(theComp, MinEdge); + return MinEdge; +} + +static Standard_Boolean FindMiddleEdges(const TopoDS_Vertex& theVertex1, + const TopoDS_Vertex& theVertex2, + const gp_Ax1& theAxis, + TopoDS_Compound& theComp, + TopTools_ListOfShape& theElist) +{ + TopTools_IndexedDataMapOfShapeListOfShape VEmap; + TopExp::MapShapesAndAncestors( theComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap ); + if (VEmap.IsEmpty()) + return Standard_False; + + if (!VEmap.Contains(theVertex1) || + !VEmap.Contains(theVertex2)) + return Standard_False; + + TopoDS_Vertex CurVertex = theVertex1; + for (;;) + { + TopoDS_Edge CurEdge; + + CurEdge = FindEdgeCloseToBisectorPlane(CurVertex, theComp, theAxis); + if (CurEdge.IsNull()) + return Standard_False; + + TopoDS_Vertex V1, V2; + TopExp::Vertices(CurEdge, V1, V2); + CurVertex = (V1.IsSame(CurVertex))? V2 : V1; + + theElist.Append(CurEdge); + if (CurVertex.IsSame(theVertex2)) + return Standard_True; + } +} + +static Standard_Boolean FindCommonVertex(const TopoDS_Edge& theFirstEdge, + const TopoDS_Edge& theLastEdge, + const TopoDS_Vertex& theFirstVertex, + const TopoDS_Vertex& theLastVertex, + TopoDS_Vertex& theCommonVertex) +{ + if (!theFirstVertex.IsSame(theLastVertex)) + { + Standard_Boolean CommonVertexExists = TopExp::CommonVertex(theFirstEdge, + theLastEdge, + theCommonVertex); + return CommonVertexExists; + } + + TopoDS_Vertex V1, V2, V3, V4; + TopExp::Vertices(theFirstEdge, V1, V2); + TopExp::Vertices(theLastEdge, V3, V4); + + if (V1.IsSame(theFirstVertex)) + { + if (V2.IsSame(V3) || + V2.IsSame(V4)) + { + theCommonVertex = V2; + return Standard_True; + } + } + else + { + if (V1.IsSame(V3) || + V1.IsSame(V4)) + { + theCommonVertex = V1; + return Standard_True; + } + } + + return Standard_False; } diff --git a/src/BRepFill/BRepFill_TrimShellCorner.hxx b/src/BRepFill/BRepFill_TrimShellCorner.hxx index 2298d7c6b4..a134916e8b 100644 --- a/src/BRepFill/BRepFill_TrimShellCorner.hxx +++ b/src/BRepFill/BRepFill_TrimShellCorner.hxx @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -28,13 +29,14 @@ #include #include #include +#include class gp_Ax2; class TopoDS_Face; class TopoDS_Wire; class TopoDS_Shape; - +//! Trims sets of faces in the corner to make proper parts of pipe class BRepFill_TrimShellCorner { public: @@ -42,12 +44,13 @@ public: DEFINE_STANDARD_ALLOC - Standard_EXPORT BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, const gp_Ax2& theAxeOfBisPlane, const TopoDS_Face& theSecPlane); - - Standard_EXPORT BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, const gp_Ax2& theAxeOfBisPlane, const TopoDS_Wire& theSpine, const TopoDS_Face& theSecPlane); - - Standard_EXPORT void SetSpine (const TopoDS_Wire& theSpine); - + //! Constructor: takes faces to intersect, + //! type of transition (it can be RightCorner or RoundCorner) + //! and axis of bisector plane + Standard_EXPORT BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, + const BRepFill_TransitionStyle theTransition, + const gp_Ax2& theAxeOfBisPlane); + Standard_EXPORT void AddBounds (const Handle(TopTools_HArray2OfShape)& Bounds); Standard_EXPORT void AddUEdges (const Handle(TopTools_HArray2OfShape)& theUEdges); @@ -71,13 +74,29 @@ protected: private: + Standard_Boolean MakeFacesSec(const Standard_Integer theIndex, + const BOPDS_PDS& theDS, + const Standard_Integer theFaceIndex1, + const Standard_Integer theFaceIndex2, + const Standard_Integer theSSInterfIndex); + + Standard_Boolean MakeFacesNonSec(const Standard_Integer theIndex, + const BOPDS_PDS& theDS, + const Standard_Integer theFaceIndex1, + const Standard_Integer theFaceIndex2); + + Standard_Boolean ChooseSection(const TopoDS_Shape& Comp, + const TopoDS_Vertex& theFirstVertex, + const TopoDS_Vertex& theLastVertex, + TopoDS_Shape& resWire, + gp_Pln& resPlane, + Standard_Boolean& IsSingular); + BRepFill_TransitionStyle myTransition; gp_Ax2 myAxeOfBisPlane; TopoDS_Shape myShape1; TopoDS_Shape myShape2; - TopoDS_Wire mySpine; - TopoDS_Face mySecPln; Handle(TopTools_HArray2OfShape) myBounds; Handle(TopTools_HArray2OfShape) myUEdges; Handle(TopTools_HArray2OfShape) myFaces; diff --git a/tests/bugs/modalg_7/bug29204 b/tests/bugs/modalg_7/bug29204 new file mode 100644 index 0000000000..8ce39b7bdc --- /dev/null +++ b/tests/bugs/modalg_7/bug29204 @@ -0,0 +1,26 @@ +puts "============" +puts "OCC29204" +puts "============" +puts "" +################################################################################## +# BRepOffsetAPI_MakePipeShell produces invalid result and raises exception in Draw +################################################################################## + +restore [locate_data_file bug29204_sweep_spine.brep] sp +restore [locate_data_file bug29204_sweep_profile.brep] pr + +mksweep sp +addsweep pr +buildsweep result -C -S + +checkshape result + +checknbshapes result -solid 1 -shell 1 -face 28 -wire 28 -edge 64 -vertex 36 -shape 158 + +set tolres [checkmaxtol result] + +if { ${tolres} > 0.001} { + puts "Error: bad tolerance of result" +} + +checkprops result -v 1.16577e+007