From aee24cb547e62c49953ac65faf17a48ca3ba1958 Mon Sep 17 00:00:00 2001 From: gka Date: Wed, 2 Mar 2016 11:01:02 +0300 Subject: [PATCH] 0027151: Exception is raised during performing command "splitshape" in the Test Harness Added protection for cases of the overlapped edges. Returning value for methods in the LocOpe_SplitShape::AddOpenWire(), LocOpe_SplitShape::AddClosedWire() are modified from void to boolean in order to avoid raising exceptions. To avoid regression for test case modalg_5 bug25243 tolerance of vertices of the degenerated edges are increased to value of tolerance of the splitting vertex for case when splitting vertex was projected on the degenerated edge. --- src/LocOpe/LocOpe_SplitShape.cxx | 280 ++++++++++++----------------- src/LocOpe/LocOpe_SplitShape.hxx | 8 +- src/LocOpe/LocOpe_Spliter.cxx | 4 +- src/LocOpe/LocOpe_WiresOnShape.cxx | 167 ++++++++--------- tests/bugs/modalg_6/bug27151 | 21 +++ 5 files changed, 222 insertions(+), 258 deletions(-) create mode 100644 tests/bugs/modalg_6/bug27151 diff --git a/src/LocOpe/LocOpe_SplitShape.cxx b/src/LocOpe/LocOpe_SplitShape.cxx index 54a44a1061..53da2aba7d 100644 --- a/src/LocOpe/LocOpe_SplitShape.cxx +++ b/src/LocOpe/LocOpe_SplitShape.cxx @@ -66,11 +66,11 @@ static Standard_Boolean IsInside(const TopoDS_Face&, static void GetDirection(const TopoDS_Edge&, const TopoDS_Face&, - Standard_Real&, gp_Pnt2d&, - gp_Vec2d&); + gp_Vec2d&, + Standard_Boolean isFirstEnd); -static void ChoixUV(const TopoDS_Edge&, +static Standard_Boolean ChoixUV(const TopoDS_Edge&, const TopoDS_Face&, const TopTools_IndexedMapOfShape&, TopoDS_Edge&, @@ -86,9 +86,6 @@ static TopoDS_Shape ChooseDirection(const TopoDS_Shape&, inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2, const BRepAdaptor_Surface& theBAS)//const Standard_Real tol) { - // Standard_Real tol = Precision::Confusion(); - // return P1.SquareDistance(P2) < 10*tol; - //gka Standard_Boolean isSame = Standard_True; if(theBAS.IsUPeriodic()) isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5); @@ -159,7 +156,7 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V, const TopoDS_Edge& E) { if (!CanSplit(E)) { - Standard_ConstructionError::Raise(); + return; } BRep_Builder B; @@ -169,22 +166,31 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V, } TopTools_ListIteratorOfListOfShape itl(le); Standard_Real f,l; - + TopTools_ListOfShape aNewList; for (; itl.More(); itl.Next()) { const TopoDS_Edge& edg = TopoDS::Edge(itl.Value()); BRep_Tool::Range(edg,f,l); - if (P>f && P f + Precision::PConfusion() && P < l - Precision::PConfusion()) { break; + } + aNewList.Append(edg); } if (!itl.More()) { - Standard_ConstructionError::Raise(); + return; } TopoDS_Edge edg = TopoDS::Edge(itl.Value()); le.Remove(itl); if (V.Orientation() == TopAbs_FORWARD || V.Orientation() == TopAbs_REVERSED) { + edg.Orientation(TopAbs_FORWARD); + TopoDS_Vertex aCurV1, aCurV2; + TopExp::Vertices(edg, aCurV1, aCurV2); + Standard_Real aPar1 = BRep_Tool::Parameter(aCurV1,edg); + + Standard_Real aPar2 = BRep_Tool::Parameter(aCurV2,edg); + TopoDS_Shape aLocalShape = edg.EmptyCopied(); TopoDS_Edge E1 = TopoDS::Edge(aLocalShape); aLocalShape = edg.EmptyCopied(); @@ -194,37 +200,50 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V, E1.Orientation(TopAbs_FORWARD); E2.Orientation(TopAbs_FORWARD); TopoDS_Vertex newVtx = V; + Standard_Real aTolSplitV = BRep_Tool::Tolerance(V); + + aCurV1.Orientation(TopAbs_FORWARD); + + B.Add(E1,aCurV1); + //for degenerated edges tolerance of vertices should be set to maximal value + //from tolerance of the vertex of the edge and tolerance of splitting vertex + Standard_Real aTolV1 = ( BRep_Tool::Degenerated(edg) ? + Max(BRep_Tool::Tolerance(aCurV1), aTolSplitV) : BRep_Tool::Tolerance(aCurV1)); + + B.UpdateVertex(aCurV1,aPar1,E1, aTolV1); newVtx.Orientation(TopAbs_REVERSED); B.Add(E1,newVtx); B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V)); newVtx.Orientation(TopAbs_FORWARD); B.Add(E2,newVtx); B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V)); - edg.Orientation(TopAbs_FORWARD); - TopExp_Explorer exp; - for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) { - // for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) { - const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current()); - f = BRep_Tool::Parameter(vtx,edg); - if (f < P) { - B.Add(E1,vtx); - B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx)); - } - else { - B.Add(E2,vtx); - B.UpdateVertex(vtx,f,E2,BRep_Tool::Tolerance(vtx)); - } + + aCurV2.Orientation(TopAbs_REVERSED); + B.Add(E2,aCurV2); + + //for degenerated edges tolerance of vertices should be set to maximal value + //from tolerance of the vertex of the edge and tolerance of splitting vertex + Standard_Real aTolV2 = ( BRep_Tool::Degenerated(edg) ? aTolV1 : BRep_Tool::Tolerance(aCurV2)); + B.UpdateVertex(aCurV2,aPar2,E2,aTolV2); + + aNewList.Append(E1); + aNewList.Append(E2); + for (; itl.More(); itl.Next()) + { + const TopoDS_Edge& edg = TopoDS::Edge(itl.Value()); + aNewList.Append(edg); } - le.Append(E1); - le.Append(E2); + myMap.UnBind(E); + myMap.Bind(E, aNewList); + } else { TopoDS_Shape aLocalShape = edg.EmptyCopied(); TopoDS_Edge E1 = TopoDS::Edge(aLocalShape); - // TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied()); + TopExp_Explorer exp; for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) { - // for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) { + const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current()); f = BRep_Tool::Parameter(vtx,edg); B.Add(E1,vtx); @@ -241,12 +260,12 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V, //purpose : adds the list of wires on the face //======================================================================= -void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, +Standard_Boolean LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, const TopoDS_Face& F) { if (myDone) { - Standard_ConstructionError::Raise(); + return Standard_False; } TopTools_ListOfShape& lf = myMap(F); @@ -261,25 +280,25 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, BRepTools::Update(F); + TopTools_ListOfShape aLInside; for (; itl.More(); itl.Next()) { const TopoDS_Face& fac = TopoDS::Face(itl.Value()); - Standard_Boolean AllWiresInside = Standard_True; TopTools_ListIteratorOfListOfShape itwires(Lwires); for (; itwires.More(); itwires.Next()) { const TopoDS_Wire& aWire = TopoDS::Wire(itwires.Value()); - if (!IsInside(fac, aWire)) + if (IsInside(fac, aWire)) { - AllWiresInside = Standard_False; - break; + aLInside.Append(aWire); + } } - if (AllWiresInside) + if(aLInside.Extent()) break; } - if (!itl.More()) { - Standard_ConstructionError::Raise(); + if (!aLInside.Extent() || !itl.More()) { + return Standard_False; } TopoDS_Face FaceRef = TopoDS::Face(itl.Value()); @@ -289,7 +308,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, TopTools_ListOfShape NewWires; TopTools_DataMapOfShapeInteger SectionsTimes; - for (itl.Initialize(Lwires); itl.More(); itl.Next()) + for (itl.Initialize(aLInside); itl.More(); itl.Next()) SectionsTimes.Bind(itl.Value(), 2); TopTools_ListOfShape BreakVertices; @@ -298,7 +317,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, TopTools_DataMapOfShapeShape VerWireMap; Standard_Integer i; TopExp_Explorer ExploF, ExploW; - for (itl.Initialize(Lwires); itl.More(); itl.Next()) + for (itl.Initialize(aLInside); itl.More(); itl.Next()) { const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value()); TopoDS_Vertex Ver [2]; @@ -327,7 +346,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, } TopTools_DataMapOfShapeListOfShape VerSecMap; - for (itl.Initialize(Lwires); itl.More(); itl.Next()) + for (itl.Initialize(aLInside); itl.More(); itl.Next()) { const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value()); TopoDS_Vertex V1, V2; @@ -524,7 +543,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, /////////////////// // JAG 10.11.95 Codage des regularites - for (itl.Initialize(Lwires); itl.More(); itl.Next()) + for (itl.Initialize(aLInside); itl.More(); itl.Next()) for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next()) { const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current()); @@ -532,6 +551,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, BB.Continuity(edg,F,F,GeomAbs_CN); } } + return Standard_True; } @@ -540,12 +560,12 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires, //purpose : //======================================================================= -void LocOpe_SplitShape::Add(const TopoDS_Wire& W, +Standard_Boolean LocOpe_SplitShape::Add(const TopoDS_Wire& W, const TopoDS_Face& F) { if (myDone) { - Standard_ConstructionError::Raise(); + return Standard_False; } @@ -557,16 +577,18 @@ void LocOpe_SplitShape::Add(const TopoDS_Wire& W, try { OCC_CATCH_SIGNALS if (!LocOpe::Closed(W,F)) { - AddOpenWire(W,F); + if(!AddOpenWire(W,F)) + return Standard_False; } else { - AddClosedWire(W,F); + if(!AddClosedWire(W,F)) + return Standard_False; } } catch (Standard_Failure ) { #ifdef OCCT_DEBUG cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <D1(l,plast,dlast); - if (dlast.Magnitude() < gp::Resolution()) - { - gp_Pnt2d PrevPnt = C2d->Value(l - dpar); - dlast.SetXY(plast.XY() - PrevPnt.XY()); - } - } - else { - C2d->D1(f,plast,dlast); - if (dlast.Magnitude() < gp::Resolution()) - { - gp_Pnt2d NextPnt = C2d->Value(f + dpar); - dlast.SetXY(NextPnt.XY() - plast.XY()); - } - dlast.Reverse(); - } - + GetDirection(LastEdge, TopoDS::Face(aLocalFace),plast , dlast, Standard_False); + Standard_Boolean cond; if(IsPeriodic) { @@ -861,12 +860,10 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W, orient = edg.Orientation(); TopExp::Vertices(edg,vdeb,vfin); - if (orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) { - PossE.Add(edg.Oriented(orient)); - } - else if (orient == TopAbs_REVERSED && Vlast.IsSame(vfin)) { - PossE.Add(edg.Oriented(orient)); - } + + if ((orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) || + (orient == TopAbs_REVERSED && Vlast.IsSame(vfin))) + PossE.Add(edg); } nbPoss = PossE.Extent(); if (nbPoss == 0) @@ -878,41 +875,24 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W, if (nbPoss == 1) { aNextEdge = TopoDS::Edge (PossE.FindKey (1)); TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation()); - C2d = BRep_Tool::CurveOnSurface(aNextEdge, - TopoDS::Face(aLocalFaceTemp), f, l); - Standard_Real dparnew = (l - f)*0.01; - - if (aNextEdge.Orientation() == TopAbs_FORWARD) { - C2d->D1(l,plast,dlast); - if (dlast.Magnitude() < gp::Resolution()) - { - gp_Pnt2d PrevPnt = C2d->Value(l - dparnew); - dlast.SetXY(plast.XY() - PrevPnt.XY()); - } - } - else { - C2d->D1(f,plast,dlast); - if (dlast.Magnitude() < gp::Resolution()) - { - gp_Pnt2d NextPnt = C2d->Value(f + dparnew); - dlast.SetXY(NextPnt.XY() - plast.XY()); - } - dlast.Reverse(); - } + GetDirection(aNextEdge, TopoDS::Face(aLocalFaceTemp),plast , dlast, Standard_False); + } else if (nbPoss > 1) { // Faire choix en U,V... TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation()); - ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE, - aNextEdge, plast, dlast, toll); + if(!ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE, + aNextEdge, plast, dlast, toll)) + return Standard_False; + } if (nbPoss >= 1) { if (aNextEdge.IsNull()) { // loop is not closed. Split is not possible - Standard_ConstructionError::Raise("Split is not possible: split loop is not closed"); + return Standard_False; } if (MapE.Contains(aNextEdge)) @@ -935,7 +915,7 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W, //MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur else{ cout<<"erreur Spliter : pas de chainage du wire"<D0 (aFirst, thePnt); + gp_Pnt2d aNextPnt = aC2d->Value(aFirst + dpar); + theDir = gp_Vec2d(thePnt, aNextPnt); } - else - { - aVtx = TopExp::LastVertex (theEdge); - aC2d->D0 (aLast, thePnt); - } - - BRepAdaptor_Surface aSurf (theFace, Standard_False); - theTol = BRep_Tool::Tolerance (aVtx); - Standard_Real aTol = Max (aSurf.UResolution (theTol), aSurf.VResolution (theTol)); - aTol = Min (aTol, (aLast - aFirst)*0.1); - - gp_Pnt2d aP2d; - if (anOr == TopAbs_FORWARD) - { - aFirst += aTol; - aC2d->D0 (aFirst, aP2d); - } else { - aLast -= aTol; - aC2d->D0 (aLast, aP2d); + aC2d->D0 (aLast, thePnt); + gp_Pnt2d aPrevPnt = aC2d->Value(aLast - dpar); + theDir = gp_Vec2d( aPrevPnt, thePnt ); } - theDir = gp_Vec2d (thePnt, aP2d); + if(anOr == TopAbs_REVERSED) + theDir.Reverse(); } //======================================================================= @@ -1413,7 +1382,7 @@ static void GetDirection(const TopoDS_Edge& theEdge, //purpose : //======================================================================= -static void ChoixUV(const TopoDS_Edge& Last, +Standard_Boolean ChoixUV(const TopoDS_Edge& Last, const TopoDS_Face& F, const TopTools_IndexedMapOfShape& Poss, TopoDS_Edge& theResEdge, @@ -1421,8 +1390,6 @@ static void ChoixUV(const TopoDS_Edge& Last, gp_Vec2d& dlst, const Standard_Real toll) { - - Standard_Real f,l; gp_Pnt2d p2d; gp_Vec2d v2d; gp_Pnt aPCur, aPlst; @@ -1435,15 +1402,19 @@ static void ChoixUV(const TopoDS_Edge& Last, gp_Dir2d ref2d(dlst); Handle(Geom2d_Curve) C2d; - Standard_Real dpar; + Standard_Integer index = 0, imin=0; Standard_Real angmax = -M_PI, dist, ang; - - + for (index = 1; index <= Poss.Extent(); index++) { TopoDS_Edge anEdge = TopoDS::Edge (Poss.FindKey (index)); - GetDirection (anEdge, F, tol, p2d, v2d); + + TopoDS_Vertex aVF = TopExp::FirstVertex(anEdge, Standard_True); + if( aVF.IsNull()) + return 0; + tol = BRep_Tool::Tolerance(aVF); + GetDirection (anEdge, F, p2d, v2d, Standard_True); surf.D0 (p2d.X(), p2d.Y(), aPCur); @@ -1467,29 +1438,10 @@ static void ChoixUV(const TopoDS_Edge& Last, if (imin) { theResEdge = TopoDS::Edge (Poss.FindKey (imin)); - C2d = BRep_Tool::CurveOnSurface (theResEdge, F, f, l); - dpar = (l - f)*0.01; - if (theResEdge.Orientation() == TopAbs_FORWARD) - { - C2d->D1 (l, plst, dlst); - if (dlst.Magnitude() < gp::Resolution()) - { - gp_Pnt2d PrevPnt = C2d->Value(l - dpar); - dlst.SetXY(plst.XY() - PrevPnt.XY()); - } - } - else - { - C2d->D1 (f, plst, dlst); - if (dlst.Magnitude() < gp::Resolution()) - { - gp_Pnt2d NextPnt = C2d->Value(f + dpar); - dlst.SetXY(NextPnt.XY() - plst.XY()); - } - dlst.Reverse(); - } + GetDirection (theResEdge, F, plst, dlst, Standard_False); } + return (imin); } //======================================================================= diff --git a/src/LocOpe/LocOpe_SplitShape.hxx b/src/LocOpe/LocOpe_SplitShape.hxx index 5e5581020f..df6a6e32fc 100644 --- a/src/LocOpe/LocOpe_SplitShape.hxx +++ b/src/LocOpe/LocOpe_SplitShape.hxx @@ -65,10 +65,10 @@ public: Standard_EXPORT void Add (const TopoDS_Vertex& V, const Standard_Real P, const TopoDS_Edge& E); //! Adds the wire on the face . - Standard_EXPORT void Add (const TopoDS_Wire& W, const TopoDS_Face& F); + Standard_EXPORT Standard_Boolean Add (const TopoDS_Wire& W, const TopoDS_Face& F); //! Adds the list of wires on the face . - Standard_EXPORT void Add (const TopTools_ListOfShape& Lwires, const TopoDS_Face& F); + Standard_EXPORT Standard_Boolean Add (const TopTools_ListOfShape& Lwires, const TopoDS_Face& F); //! Returns the "original" shape. const TopoDS_Shape& Shape() const; @@ -95,9 +95,9 @@ protected: private: - Standard_EXPORT void AddOpenWire (const TopoDS_Wire& W, const TopoDS_Face& F); + Standard_EXPORT Standard_Boolean AddOpenWire (const TopoDS_Wire& W, const TopoDS_Face& F); - Standard_EXPORT void AddClosedWire (const TopoDS_Wire& W, const TopoDS_Face& F); + Standard_EXPORT Standard_Boolean AddClosedWire (const TopoDS_Wire& W, const TopoDS_Face& F); Standard_EXPORT void Put (const TopoDS_Shape& S); diff --git a/src/LocOpe/LocOpe_Spliter.cxx b/src/LocOpe/LocOpe_Spliter.cxx index 4fdd222833..d7080b1780 100644 --- a/src/LocOpe/LocOpe_Spliter.cxx +++ b/src/LocOpe/LocOpe_Spliter.cxx @@ -143,7 +143,7 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW) TopTools_MapOfShape theFacesWithSection; for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) { - const TopoDS_Edge& edg = PW->Edge(); + TopoDS_Edge edg = PW->Edge(); for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) { const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current()); if (!mapV.Contains(vtx)) { @@ -286,7 +286,7 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW) TopoDS_Shape ebase = lsubs.First(); lsubs.Clear(); lsubs.Append(e1.Oriented(ebase.Orientation())); - theSubs.Substitute(ebase.Oriented(TopAbs_FORWARD),lsubs); + theSubs.Substitute(ebase,lsubs); } else { #ifdef OCCT_DEBUG diff --git a/src/LocOpe/LocOpe_WiresOnShape.cxx b/src/LocOpe/LocOpe_WiresOnShape.cxx index b538a48088..e1a5648a54 100644 --- a/src/LocOpe/LocOpe_WiresOnShape.cxx +++ b/src/LocOpe/LocOpe_WiresOnShape.cxx @@ -84,9 +84,7 @@ static void PutPCurves(const TopoDS_Edge&, static void FindInternalIntersections(const TopoDS_Edge&, const TopoDS_Face&, - TopTools_IndexedDataMapOfShapeListOfShape&, - TopTools_DataMapOfShapeShape&, - TopTools_MapOfShape&); + TopTools_IndexedDataMapOfShapeListOfShape&); //======================================================================= //function : LocOpe_WiresOnShape @@ -243,7 +241,7 @@ void LocOpe_WiresOnShape::BindAll() continue; if (myCheckInterior) - FindInternalIntersections(edg, fac, Splits, myMap, theMap); + FindInternalIntersections(edg, fac, Splits); } for (Ind = 1; Ind <= Splits.Extent(); Ind++) @@ -262,13 +260,7 @@ void LocOpe_WiresOnShape::BindAll() myMapEF.Add(itl.Value(), aFace); } - // Il faut s`occuper maintenant des vertex "de changement de face", - // et des vertex "libres" -// TopTools_DataMapIteratorOfDataMapOfShapeShape ite2; - -// for (ite.Initialize(myMapEF); ite.More(); ite.Next()) { -// const TopoDS_Edge& edg = TopoDS::Edge(ite.Key()); -// const TopoDS_Face& fac = TopoDS::Face(ite.Value()); + for (Ind = 1; Ind <= myMapEF.Extent(); Ind++) { const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind)); const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind)); @@ -281,24 +273,27 @@ void LocOpe_WiresOnShape::BindAll() if (theMap.Contains(vtx)) { continue; } - //// + Standard_Real vtx_param = BRep_Tool::Parameter(vtx, edg); BRepAdaptor_Curve2d BAcurve2d(edg, fac); gp_Pnt2d p2d = BAcurve2d.Value(vtx_param); - //// + TopoDS_Edge Epro; Standard_Real prm = 0.; Standard_Boolean ok = Project(vtx, p2d, fac, Epro, prm); if (ok) { + for (exp2.Init(Epro,TopAbs_VERTEX); exp2.More(); exp2.Next()) { const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current()); if (vtx2.IsSame(vtx)) { break; } else if (BRepTools::Compare(vtx,vtx2)) { + Standard_Real aF1, aL1; + BRep_Tool::Range(Epro, fac, aF1, aL1); if (!BRep_Tool::Degenerated(Epro) || - Abs(prm-BAcurve2d.FirstParameter()) <= Precision::PConfusion() || - Abs(prm-BAcurve2d.LastParameter()) <= Precision::PConfusion()) + Abs(prm-aF1) <= Precision::PConfusion() || + Abs(prm-aL1) <= Precision::PConfusion()) { myMap.Bind(vtx,vtx2); break; @@ -460,13 +455,24 @@ Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V, } Ed = TopoDS::Edge(myMap(V)); - TopoDS_Face theFace = TopoDS::Face(myMapEF.FindFromKey(EdgeFrom)); - //// - Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom); - BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, theFace); - gp_Pnt2d p2d = BAcurve2d.Value(vtx_param); - //// - prm = Project(V, p2d, Ed, theFace); + if(!myMapEF.Contains(EdgeFrom)) + return Standard_False; + + TopoDS_Shape aShape = myMapEF.FindFromKey(EdgeFrom); + if( aShape.ShapeType() == TopAbs_FACE) + { + + TopoDS_Face aFace = TopoDS::Face(aShape); + Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom); + BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, aFace); + gp_Pnt2d p2d = BAcurve2d.Value(vtx_param); + + + prm = Project(V, p2d, Ed, aFace); + } + else + prm = Project( V, TopoDS::Edge(Ed)); + return Standard_True; } @@ -509,12 +515,33 @@ Standard_Boolean Project(const TopoDS_Vertex& V, if(theEdge.IsNull()) return Standard_False; - - Standard_Real ttol = BRep_Tool::Tolerance(V) + BRep_Tool::Tolerance(theEdge); - if (dmin <= ttol) { + //compute distance in 3D space + + Handle(Geom2d_Curve) aCrvBound = BRep_Tool::CurveOnSurface(theEdge, F, f, l); + gp_Pnt2d aPBound2d; + aCrvBound->D0(param,aPBound2d); + gp_Pnt aPBound; + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F); + aSurf->D0(aPBound2d.X(), aPBound2d.Y(), aPBound); + + //point of vertex computed by pcurve of the splitting edge + gp_Pnt aPV2d; + aSurf->D0(p2d.X(), p2d.Y(), aPV2d); + //point of vertex in 3D splace + gp_Pnt aP3dV = BRep_Tool::Pnt(V); + + Standard_Real aDist3d2 = Max( aPV2d.SquareDistance(aPBound), aP3dV.SquareDistance(aPBound)); + Standard_Real aTolV = BRep_Tool::Tolerance(V); + Standard_Real ttol = aTolV + BRep_Tool::Tolerance(theEdge); + if (aDist3d2 <= ttol* ttol) { valret = Standard_True; + BRep_Builder B; - B.UpdateVertex(V, Max(dmin, BRep_Tool::Tolerance(V))); + if( aTolV * aTolV < aDist3d2) + { + Standard_Real aNewTol = sqrt(aDist3d2) + Precision::Confusion(); + B.UpdateVertex(V, aNewTol); + } } #ifdef OCCT_DEBUG_MESH else { @@ -609,9 +636,6 @@ void PutPCurve(const TopoDS_Edge& Edg, Standard_Real f,l; - //if (!BRep_Tool::CurveOnSurface(Edg,Fac,f,l).IsNull()) { - // return; - //} Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(Edg,Fac,f,l); if ( !aC2d.IsNull() ) { gp_Pnt2d p2d; @@ -712,20 +736,6 @@ void PutPCurve(const TopoDS_Edge& Edg, } } -/* - if (theUmin > Umax-tolu) { - while (theUmin > Umax-tolu) { - theUmin -= up; - nbtra--; - } - } - else if (theUmax < Umin+tolu) { - while (theUmax < Umin+tolu) { - theUmax += up; - nbtra++; - } - } -*/ if (nbtra !=0) { C2d->Translate(gp_Vec2d(nbtra*up,0.)); } @@ -1010,12 +1020,12 @@ void PutPCurves(const TopoDS_Edge& Efrom, C->D1(f,pt,d1f); - //// + TopoDS_Vertex FirstVertex = TopExp::FirstVertex(Efrom); Standard_Real vtx_param = BRep_Tool::Parameter(FirstVertex, Efrom); BRepAdaptor_Curve2d BAcurve2d(Efrom, Fac); gp_Pnt2d p2d = BAcurve2d.Value(vtx_param); - //// + Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),p2d,Eto,Fac); C = BRep_Tool::Curve(Eto,Loc,f,l); @@ -1139,9 +1149,7 @@ void PutPCurves(const TopoDS_Edge& Efrom, void FindInternalIntersections(const TopoDS_Edge& theEdge, const TopoDS_Face& theFace, - TopTools_IndexedDataMapOfShapeListOfShape& Splits, - TopTools_DataMapOfShapeShape& GlobalMap, - TopTools_MapOfShape& theMap) + TopTools_IndexedDataMapOfShapeListOfShape& Splits) { Standard_Real TolExt = Precision::PConfusion(); Standard_Integer i, j, aNbExt; @@ -1153,16 +1161,19 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge, gp_Pnt thePnt [2]; thePnt[0] = BRep_Tool::Pnt(theVertices[0]); thePnt[1] = BRep_Tool::Pnt(theVertices[1]); - + Standard_Real aTolV[2]; + aTolV[0] =BRep_Tool::Tolerance(theVertices[0]); + aTolV[1] =BRep_Tool::Tolerance(theVertices[1]); + BRepAdaptor_Curve2d thePCurve(theEdge, theFace); Bnd_Box2d theBox; BndLib_Add2dCurve::Add(thePCurve, BRep_Tool::Tolerance(theEdge), theBox); Standard_Real thePar [2]; - Standard_Real /*theFpar, theLpar,*/ aFpar, aLpar; + Standard_Real aFpar, aLpar; const Handle(Geom_Curve)& theCurve = BRep_Tool::Curve(theEdge, thePar[0], thePar[1]); GeomAdaptor_Curve theGAcurve(theCurve, thePar[0], thePar[1]); - + Standard_Real aDistMax = Precision::Confusion() * Precision::Confusion(); TopExp_Explorer Explo(theFace, TopAbs_EDGE); for (; Explo.More(); Explo.Next()) { @@ -1184,53 +1195,33 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge, aNbExt = anExtrema.NbExt(); Standard_Real MaxTol = Max(BRep_Tool::Tolerance(theEdge), BRep_Tool::Tolerance(anEdge)); + Standard_Real aMaxTol2 = MaxTol * MaxTol; for (i = 1; i <= aNbExt; i++) { - Standard_Real aDist = Sqrt(anExtrema.SquareDistance(i)); - if (aDist > MaxTol) + Standard_Real aDist = anExtrema.SquareDistance(i); + if (aDist > aMaxTol2) continue; Extrema_POnCurv aPOnC1, aPOnC2; anExtrema.Points(i, aPOnC1, aPOnC2); Standard_Real theIntPar = aPOnC1.Parameter(); Standard_Real anIntPar = aPOnC2.Parameter(); - Standard_Boolean IntersFound = Standard_False; for (j = 0; j < 2; j++) //try to find intersection on an extremity of "theEdge" { - if (Abs(theIntPar - thePar[j]) <= Precision::PConfusion() && - aDist <= Precision::Confusion()) - { - theMap.Add(theVertices[j]); - TopExp_Explorer exp2(anEdge, TopAbs_VERTEX); - for (; exp2.More(); exp2.Next()) - { - const TopoDS_Vertex& aVertex = TopoDS::Vertex(exp2.Current()); - if (aVertex.IsSame(theVertices[j])) - { - IntersFound = Standard_True; - break; - } - if (BRepTools::Compare(theVertices[j], aVertex)) - { - GlobalMap.Bind(theVertices[j], aVertex); - IntersFound = Standard_True; - break; - } - } - if (!IntersFound) - { - GlobalMap.Bind(theVertices[j], anEdge); - IntersFound = Standard_True; - break; - } - } + if (Abs(theIntPar - thePar[j]) <= Precision::PConfusion()) + break; } - if (!IntersFound && aDist <= Precision::Confusion()) //intersection is inside "theEdge" => split + //intersection found in the middle of the edge + if (j >= 2) //intersection is inside "theEdge" => split { gp_Pnt aPoint = aCurve->Value(anIntPar); - if (aPoint.Distance(thePnt[0]) > BRep_Tool::Tolerance(theVertices[0]) && - aPoint.Distance(thePnt[1]) > BRep_Tool::Tolerance(theVertices[1])) + if (aPoint.SquareDistance(thePnt[0]) > aTolV[0] * aTolV[0] && + aPoint.SquareDistance(thePnt[1]) > aTolV[1] * aTolV[1]) + { SplitPars.Append(theIntPar); + if( aDist > aDistMax) + aDistMax = aDist; + } } } } @@ -1247,14 +1238,13 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge, SplitPars(i) = SplitPars(j); SplitPars(j) = Tmp; } - //Remove repeating points i = 1; while (i < SplitPars.Length()) { gp_Pnt Pnt1 = theCurve->Value(SplitPars(i)); gp_Pnt Pnt2 = theCurve->Value(SplitPars(i+1)); - if (Pnt1.Distance(Pnt2) <= Precision::Confusion()) + if (Pnt1.SquareDistance(Pnt2) <= Precision::Confusion()* Precision::Confusion()) SplitPars.Remove(i+1); else i++; @@ -1263,8 +1253,7 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge, //Split TopTools_ListOfShape NewEdges; BRep_Builder BB; - //theVertices[0].Orientation(TopAbs_FORWARD); - //theVertices[1].Orientation(TopAbs_REVERSED); + TopoDS_Vertex FirstVertex = theVertices[0], LastVertex; Standard_Real FirstPar = thePar[0], LastPar; for (i = 1; i <= SplitPars.Length()+1; i++) @@ -1275,6 +1264,8 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge, LastPar = SplitPars(i); gp_Pnt LastPoint = theCurve->Value(LastPar); LastVertex = BRepLib_MakeVertex(LastPoint); + BRep_Builder aB; + aB.UpdateVertex(LastVertex, sqrt(aDistMax)); } else { diff --git a/tests/bugs/modalg_6/bug27151 b/tests/bugs/modalg_6/bug27151 new file mode 100644 index 0000000000..6198c4fc1a --- /dev/null +++ b/tests/bugs/modalg_6/bug27151 @@ -0,0 +1,21 @@ +puts "========" +puts "OCC27151" +puts "========" +puts "" +######################################################################################### +# Exception is raised during performing command "splitshape" in the Test Harness +######################################################################################### + +restore [locate_data_file bug27151.brep] a +explode a +renamevar a_1 f1 +renamevar a_2 w0 +explode f1 e +explode w0 e +wire w1 w0_2 w0_3 +splitshape rs f1 f1 w1 @ f1_4 w0_1 +fixshape res rs 1.e-07 1 +checkprops res -s 173.371 +checknbshapes res -face 2 + +checkview -display res -3d -path ${imagedir}/${test_image}.png -- 2.20.1