// Created on: 1996-09-03 // Created by: Yves FRICAUD // Copyright (c) 1996-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DRAW #include #include #include #include #include #include Standard_Boolean Inter2dAffichInt2d; static Standard_Integer NbF2d = 0; static Standard_Integer NbE2d = 0; static Standard_Integer NbNewVertices = 0; #endif //======================================================================= //function : CommonVertex //purpose : //======================================================================= static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1, TopoDS_Edge& E2) { TopoDS_Vertex V1[2],V2[2],V; // TopExp::Vertices(E1,V1[0],V1[1], Standard_True); TopExp::Vertices(E2,V2[0],V2[1], Standard_True); // The first edge is the current one, the second edge is the next one. // We check last vertex of the first edge first. if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1]; if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0]; // return V; } static Standard_Integer DefineClosedness(const TopoDS_Face& theFace) { TopExp_Explorer anExplo (theFace, TopAbs_EDGE); for (; anExplo.More(); anExplo.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge (anExplo.Current()); if (BRepTools::IsReallyClosed(anEdge, theFace)) { Standard_Real fpar, lpar; Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar); gp_Vec2d aTangent = aPCurve->DN(fpar, 1); Standard_Real aCrossProd1 = aTangent ^ gp::DX2d(); Standard_Real aCrossProd2 = aTangent ^ gp::DY2d(); if (Abs(aCrossProd2) < Abs(aCrossProd1)) //pcurve is parallel to OY return 1; else return 2; } } return 0; } static void GetEdgesOrientedInFace(const TopoDS_Shape& theShape, const TopoDS_Face& theFace, const Handle(BRepAlgo_AsDes)& theAsDes, TopTools_SequenceOfShape& theSeqEdges) { const TopTools_ListOfShape& aEdges = theAsDes->Descendant (theFace); TopExp_Explorer anExplo (theShape, TopAbs_EDGE); for (; anExplo.More(); anExplo.Next()) { const TopoDS_Shape& anEdge = anExplo.Current(); TopTools_ListIteratorOfListOfShape itl (aEdges); for (; itl.More(); itl.Next()) { const TopoDS_Shape& anEdgeInFace = itl.Value(); if (anEdgeInFace.IsSame(anEdge)) { theSeqEdges.Append (anEdgeInFace); break; } } } if (theSeqEdges.Length() == 1) return; TopTools_IndexedDataMapOfShapeListOfShape aVEmap; for (Standard_Integer ii = 1; ii <= theSeqEdges.Length(); ii++) TopExp::MapShapesAndAncestors (theSeqEdges(ii), TopAbs_VERTEX, TopAbs_EDGE, aVEmap); TopoDS_Vertex aFirstVertex; TopoDS_Edge aFirstEdge; for (Standard_Integer ii = 1; ii <= aVEmap.Extent(); ii++) { const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVEmap.FindKey(ii)); const TopTools_ListOfShape& aElist = aVEmap(ii); if (aElist.Extent() == 1) { const TopoDS_Edge& anEdge = TopoDS::Edge(aElist.First()); TopoDS_Vertex aV1, aV2; TopExp::Vertices(anEdge, aV1, aV2, Standard_True); //with orientation if (aV1.IsSame(aVertex)) { aFirstVertex = aVertex; aFirstEdge = anEdge; break; } } } if (aFirstEdge.IsNull()) //closed set of edges { //Standard_Real aPeriod = 0.; Standard_Integer IndCoord = DefineClosedness (theFace); /* BRepAdaptor_Surface aBAsurf (theFace, Standard_False); if (IndCoord == 1) aPeriod = aBAsurf.LastUParameter() - aBAsurf.FirstUParameter(); else if (IndCoord == 2) aPeriod = aBAsurf.LastVParameter() - aBAsurf.FirstVParameter(); */ if (IndCoord != 0) { Standard_Real aMaxDelta = 0.; for (Standard_Integer ii = 1; ii <= aVEmap.Extent(); ii++) { const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVEmap.FindKey(ii)); const TopTools_ListOfShape& aElist = aVEmap(ii); const TopoDS_Edge& anEdge1 = TopoDS::Edge(aElist.First()); const TopoDS_Edge& anEdge2 = TopoDS::Edge(aElist.Last()); Standard_Real aParam1 = BRep_Tool::Parameter(aVertex, anEdge1); Standard_Real aParam2 = BRep_Tool::Parameter(aVertex, anEdge2); BRepAdaptor_Curve2d aBAcurve1 (anEdge1, theFace); BRepAdaptor_Curve2d aBAcurve2 (anEdge2, theFace); gp_Pnt2d aPnt1 = aBAcurve1.Value(aParam1); gp_Pnt2d aPnt2 = aBAcurve2.Value(aParam2); Standard_Real aDelta = Abs(aPnt1.Coord(IndCoord) - aPnt2.Coord(IndCoord)); if (aDelta > aMaxDelta) { aMaxDelta = aDelta; aFirstVertex = aVertex; } } const TopTools_ListOfShape& aElist = aVEmap.FindFromKey(aFirstVertex); TopTools_ListIteratorOfListOfShape itl (aElist); for (; itl.More(); itl.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); TopoDS_Vertex aV1, aV2; TopExp::Vertices(anEdge, aV1, aV2, Standard_True); //with orientation if (aV1.IsSame(aFirstVertex)) { aFirstEdge = anEdge; break; } } } } Standard_Integer aNbEdges = theSeqEdges.Length(); theSeqEdges.Clear(); theSeqEdges.Append (aFirstEdge); TopoDS_Edge anEdge = aFirstEdge; for (;;) { TopoDS_Vertex aLastVertex = TopExp::LastVertex (anEdge, Standard_True); //with orientation if (aLastVertex.IsSame(aFirstVertex)) break; const TopTools_ListOfShape& aElist = aVEmap.FindFromKey(aLastVertex); if (aElist.Extent() == 1) break; if (aElist.First().IsSame(anEdge)) anEdge = TopoDS::Edge(aElist.Last()); else anEdge = TopoDS::Edge(aElist.First()); theSeqEdges.Append (anEdge); if (theSeqEdges.Length() == aNbEdges) break; } } //======================================================================= //function : Store //purpose : Store the vertices into AsDes for the edge . // 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& theEdge, const TopTools_ListOfShape& theLV, const Standard_Real theTol, const Standard_Boolean IsToUpdate, Handle(BRepAlgo_AsDes) theAsDes2d, TopTools_IndexedDataMapOfShapeListOfShape& theDMVV) { // Update vertices TopTools_ListIteratorOfListOfShape aIt(theLV); for (; aIt.More(); aIt.Next()) { const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value()); BRep_Builder().UpdateVertex(aV, theTol); } // Get vertices already added to the edge and check the distances to the new ones const TopTools_ListOfShape& aLVEx = theAsDes2d->Descendant(theEdge); if (!IsToUpdate && aLVEx.IsEmpty()) { if (theLV.Extent()) theAsDes2d->Add(theEdge, theLV); return; } // GeomAPI_ProjectPointOnCurve aProjPC; Standard_Real aTolE = 0.0; if (IsToUpdate) { Standard_Real aT1, aT2; const Handle(Geom_Curve)& aC = BRep_Tool::Curve(theEdge, aT1, aT2); aProjPC.Init(aC, aT1, aT2); aTolE = BRep_Tool::Tolerance(theEdge); } // TopTools_MapOfShape aMV; for (aIt.Init(theLV); aIt.More(); aIt.Next()) { const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value()); if (!aMV.Add(aV)) { continue; } // const gp_Pnt& aP = BRep_Tool::Pnt(aV); const Standard_Real aTol = BRep_Tool::Tolerance(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; } const gp_Pnt& aPEx = BRep_Tool::Pnt(aVEx); const Standard_Real aTolVEx = BRep_Tool::Tolerance(aVEx); if (aP.IsEqual(aPEx, aTol + aTolVEx)) { aLVC.Append(aVEx); } } // if (aItEx.More()) { continue; } // if (IsToUpdate) { // get parameter of the vertex on the edge aProjPC.Perform(aP); if (!aProjPC.NbPoints()) { continue; } // if (aProjPC.LowerDistance() > aTol + aTolE) { continue; } // Standard_Real aT = aProjPC.LowerDistanceParameter(); TopoDS_Shape aLocalShape = aV.Oriented(TopAbs_INTERNAL); BRep_Builder().UpdateVertex(TopoDS::Vertex(aLocalShape), aT, theEdge, aTol); } // if (aLVC.Extent()) { TopTools_ListIteratorOfListOfShape aItLV(aLVC); for (; aItLV.More(); aItLV.Next()) { const TopoDS_Shape& aVC = aItLV.Value(); TopTools_ListOfShape* pLV = theDMVV.ChangeSeek(aVC); if (!pLV) { pLV = &theDMVV(theDMVV.Add(aVC, TopTools_ListOfShape())); } pLV->Append(aV); } // TopTools_ListOfShape* pLV = theDMVV.ChangeSeek(aV); if (!pLV) { pLV = &theDMVV(theDMVV.Add(aV, TopTools_ListOfShape())); } pLV->Append(aLVC); } theAsDes2d->Add(theEdge, aV); } } //======================================================================= //function : Store //purpose : Store the intersection vertices between two edges into AsDes //======================================================================= static void Store (const TopoDS_Edge& theE1, const TopoDS_Edge& theE2, const TopTools_ListOfShape& theLV1, const TopTools_ListOfShape& theLV2, const Standard_Real theTol, Handle(BRepAlgo_AsDes) theAsDes2d, TopTools_IndexedDataMapOfShapeListOfShape& theDMVV) { for (Standard_Integer i = 0; i < 2; ++i) { const TopoDS_Edge& aE = !i ? theE1 : theE2; const TopTools_ListOfShape& aLV = !i ? theLV1 : theLV2; Store(aE, aLV, theTol, Standard_False, theAsDes2d, theDMVV); } } //======================================================================= //function : EdgeInter //purpose : //======================================================================= static void EdgeInter(const TopoDS_Face& F, const BRepAdaptor_Surface& BAsurf, const TopoDS_Edge& E1, const TopoDS_Edge& E2, const Handle(BRepAlgo_AsDes)& AsDes, Standard_Real Tol, Standard_Boolean WithOri, TopTools_IndexedDataMapOfShapeListOfShape& aDMVV) { #ifdef DRAW if (Inter2dAffichInt2d) { char name[256]; sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++); DBRep::Set(name,E1); sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++); DBRep::Set(name,E2); } #endif if (E1.IsSame(E2)) return; Standard_Real f[3],l[3]; Standard_Real TolDub = 1.e-7; Standard_Integer i; BRep_Tool::Range(E1, f[1], l[1]); BRep_Tool::Range(E2, f[2], l[2]); BRepAdaptor_Curve CE1(E1,F); BRepAdaptor_Curve CE2(E2,F); TopoDS_Edge EI[3]; EI[1] = E1; EI[2] = E2; TopTools_ListOfShape LV1; TopTools_ListOfShape LV2; BRep_Builder B; TopoDS_Vertex CV; if (!TopExp::CommonVertex( E1, E2, CV )) { BRepLib::BuildCurve3d(E1); BRepLib::BuildCurve3d(E2); Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); TolSum = Max( TolSum, 1.e-5 ); TColgp_SequenceOfPnt ResPoints; TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2; gp_Pnt DegPoint; Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2); if (WithDegen) { Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2; TopoDS_Iterator iter( EI[ideg] ); if (iter.More()) { const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value()); DegPoint = BRep_Tool::Pnt(vdeg); } else { BRepAdaptor_Curve CEdeg( EI[ideg], F ); DegPoint = CEdeg.Value( CEdeg.FirstParameter() ); } } // Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]); Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]); Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]); Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]); Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub ); for (i = 1; i <= Inter2d.NbPoints(); i++) { gp_Pnt P3d; if (WithDegen) P3d = DegPoint; else { gp_Pnt2d P2d = Inter2d.Point(i).Value(); P3d = BAsurf.Value( P2d.X(), P2d.Y() ); } ResPoints.Append( P3d ); ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() ); ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() ); } for (i = 1; i <= ResPoints.Length(); i++) { Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter(); Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter(); if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2)) { #ifdef OCCT_DEBUG std::cout << "Inter2d : Solution rejected due to infinite parameter"< l[1]+Tol) { std::cout << "out of limit"< l[1]+Tol) { std::cout << "out of limit"< 1) { //std::cout << "IFV - RefEdgeInter: remove vertex" << std::endl; gp_Pnt Pref = BRep_Tool::Pnt(theVref); Standard_Real dmin = RealLast(); TopoDS_Vertex Vmin; for (it1LV1.Initialize(LV1); it1LV1.More(); it1LV1.Next()) { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value())); Standard_Real d = P.SquareDistance(Pref); if(d < dmin) { dmin = d; Vmin = TopoDS::Vertex(it1LV1.Value()); } } for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); it1LV1.More(); it1LV1.Next(),it1LV2.Next()) { if(!Vmin.IsSame(it1LV1.Value())) { LV1.Remove(it1LV1); LV2.Remove(it1LV2); if(!it1LV1.More()) break; } } } TopTools_ListIteratorOfListOfShape itl (LV1); for (; itl.More(); itl.Next()) { TopoDS_Shape aNewVertex = itl.Value(); aNewVertex.Orientation(TopAbs_FORWARD); if (theImageVV.HasImage (theVref)) theImageVV.Add (theVref.Oriented(TopAbs_FORWARD), aNewVertex); else theImageVV.Bind (theVref.Oriented(TopAbs_FORWARD), aNewVertex); } ////----------------------------------------------------- Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); TolStore = Max (TolStore, Tol); // Compare to Line-Line tolerance TolStore = Max (TolStore, TolLL); Store (E1,E2,LV1,LV2,TolStore,AsDes, aDMVV); } } //====================================================================== //function : EvaluateMaxSegment //purpose : return MaxSegment to pass in approximation //====================================================================== static Standard_Integer evaluateMaxSegment(const Adaptor3d_CurveOnSurface& aCurveOnSurface) { const Handle(Adaptor3d_Surface)& aSurf = aCurveOnSurface.GetSurface(); const Handle(Adaptor2d_Curve2d)& aCurv2d = aCurveOnSurface.GetCurve(); Standard_Real aNbSKnots = 0, aNbC2dKnots = 0; if (aSurf->GetType() == GeomAbs_BSplineSurface) { Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline(); aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots()); } if (aCurv2d->GetType() == GeomAbs_BSplineCurve) { aNbC2dKnots = aCurv2d->NbKnots(); } Standard_Integer aReturn = (Standard_Integer) ( 30 + Max(aNbSKnots, aNbC2dKnots) ) ; return aReturn; } //======================================================================= //function : ExtendPCurve //purpose : //======================================================================= static Standard_Boolean ExtendPCurve(const Handle(Geom2d_Curve)& aPCurve, const Standard_Real anEf, const Standard_Real anEl, const Standard_Real a2Offset, Handle(Geom2d_Curve)& NewPCurve) { NewPCurve = aPCurve; if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve))) NewPCurve = Handle(Geom2d_TrimmedCurve)::DownCast (NewPCurve)->BasisCurve(); Standard_Real FirstPar = NewPCurve->FirstParameter(); Standard_Real LastPar = NewPCurve->LastParameter(); if (NewPCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) && (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)) { if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BezierCurve))) { Handle(Geom2d_BezierCurve) aBezier = Handle(Geom2d_BezierCurve)::DownCast (NewPCurve); if (aBezier->NbPoles() == 2) { TColgp_Array1OfPnt2d thePoles(1,2); aBezier->Poles(thePoles); gp_Vec2d aVec(thePoles(1), thePoles(2)); NewPCurve = new Geom2d_Line(thePoles(1), aVec); return Standard_True; } } else if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BSplineCurve))) { Handle(Geom2d_BSplineCurve) aBSpline = Handle(Geom2d_BSplineCurve)::DownCast (NewPCurve); if (aBSpline->NbKnots() == 2 && aBSpline->NbPoles() == 2) { TColgp_Array1OfPnt2d thePoles(1,2); aBSpline->Poles(thePoles); gp_Vec2d aVec(thePoles(1), thePoles(2)); NewPCurve = new Geom2d_Line(thePoles(1), aVec); return Standard_True; } } } FirstPar = aPCurve->FirstParameter(); LastPar = aPCurve->LastParameter(); Handle(Geom2d_TrimmedCurve) aTrCurve = new Geom2d_TrimmedCurve(aPCurve, FirstPar, LastPar); // The curve is not prolonged on begin or end. // Trying to prolong it adding a segment to its bound. gp_Pnt2d aPBnd; gp_Vec2d aVBnd; gp_Pnt2d aPBeg; gp_Dir2d aDBnd; Handle(Geom2d_Line) aLin; Handle(Geom2d_TrimmedCurve) aSegment; Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1); Standard_Real aTol = Precision::Confusion(); Standard_Real aDelta = Max(a2Offset, 1.); if (FirstPar > anEf - a2Offset) { aPCurve->D1(FirstPar, aPBnd, aVBnd); aDBnd.SetXY(aVBnd.XY()); aPBeg = aPBnd.Translated(gp_Vec2d(-aDelta*aDBnd.XY())); aLin = new Geom2d_Line(aPBeg, aDBnd); aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return Standard_False; } if (LastPar < anEl + a2Offset) { aPCurve->D1(LastPar, aPBeg, aVBnd); aDBnd.SetXY(aVBnd.XY()); aLin = new Geom2d_Line(aPBeg, aDBnd); aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return Standard_False; } NewPCurve = aCompCurve.BSplineCurve(); return Standard_True; } //======================================================================= //function : ExtentEdge //purpose : //======================================================================= // Modified by skv - Fri Dec 26 17:00:55 2003 OCC4455 Begin //static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE) Standard_Boolean BRepOffset_Inter2d::ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset) { //BRepLib::BuildCurve3d(E); TopoDS_Shape aLocalShape = E.EmptyCopied(); Standard_Real anEf; Standard_Real anEl; Standard_Real a2Offset = 2.*Abs(theOffset); BRep_Builder BB; Standard_Integer i, j; BRep_Tool::Range(E, anEf, anEl); NE = TopoDS::Edge(aLocalShape); // NE = TopoDS::Edge(E.EmptyCopied()); // Enough for analytic edges, for general case reconstruct the // geometry of the edge recalculating the intersection of surfaces. //BRepLib::BuildCurve3d(E); Standard_Integer NbPCurves = 0; Standard_Real FirstParOnPC = RealFirst(), LastParOnPC = RealLast(); Handle(Geom2d_Curve) MinPC; Handle(Geom_Surface) MinSurf; TopLoc_Location MinLoc; BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves() ); for (; itr.More(); itr.Next()) { Handle( BRep_CurveRepresentation ) CurveRep = itr.Value(); Standard_Real FirstPar, LastPar; if (CurveRep->IsCurveOnSurface()) { NbPCurves++; Handle(Geom2d_Curve) theCurve = CurveRep->PCurve(); FirstPar = theCurve->FirstParameter(); LastPar = theCurve->LastParameter(); if (theCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) && (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)) { Handle(Geom2d_Curve) NewPCurve; if (ExtendPCurve(theCurve, anEf, anEl, a2Offset, NewPCurve)) { CurveRep->PCurve(NewPCurve); FirstPar = NewPCurve->FirstParameter(); LastPar = NewPCurve->LastParameter(); if (CurveRep->IsCurveOnClosedSurface()) { Handle(Geom2d_Curve) PCurve2 = CurveRep->PCurve2(); if (ExtendPCurve(PCurve2, anEf, anEl, a2Offset, NewPCurve)) CurveRep->PCurve2(NewPCurve); } } } else if (theCurve->IsPeriodic()) { Standard_Real delta = (theCurve->Period() - (anEl - anEf))*0.5; delta *= 0.95; FirstPar = anEf - delta; LastPar = anEl + delta; } else if (theCurve->IsClosed()) LastPar -= 0.05*(LastPar - FirstPar); //check FirstPar and LastPar: the pcurve should be in its surface theCurve = CurveRep->PCurve(); Handle(Geom_Surface) theSurf = CurveRep->Surface(); Standard_Real Umin, Umax, Vmin, Vmax; theSurf->Bounds(Umin, Umax, Vmin, Vmax); TColGeom2d_SequenceOfCurve BoundLines; if (!Precision::IsInfinite(Vmin)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmin ), gp_Dir2d( 1., 0. )); BoundLines.Append(aLine); } if (!Precision::IsInfinite(Umin)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umin, 0. ), gp_Dir2d( 0., 1. )); BoundLines.Append(aLine); } if (!Precision::IsInfinite(Vmax)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmax ), gp_Dir2d( 1., 0. )); BoundLines.Append(aLine); } if (!Precision::IsInfinite(Umax)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umax, 0. ), gp_Dir2d( 0., 1. )); BoundLines.Append(aLine); } TColStd_SequenceOfReal params; Geom2dInt_GInter IntCC; Geom2dAdaptor_Curve GAcurve(theCurve); for (i = 1; i <= BoundLines.Length(); i++) { Geom2dAdaptor_Curve GAline( BoundLines(i) ); IntCC.Perform( GAcurve, GAline, Precision::PConfusion(), Precision::PConfusion()); if (IntCC.IsDone()) { for (j = 1; j <= IntCC.NbPoints(); j++) { const IntRes2d_IntersectionPoint& ip = IntCC.Point(j); gp_Pnt2d aPoint = ip.Value(); if (aPoint.X() >= Umin && aPoint.X() <= Umax && aPoint.Y() >= Vmin && aPoint.Y() <= Vmax) params.Append( ip.ParamOnFirst() ); } for (j = 1; j <= IntCC.NbSegments(); j++) { const IntRes2d_IntersectionSegment& is = IntCC.Segment(j); if (is.HasFirstPoint()) { const IntRes2d_IntersectionPoint& ip = is.FirstPoint(); gp_Pnt2d aPoint = ip.Value(); if (aPoint.X() >= Umin && aPoint.X() <= Umax && aPoint.Y() >= Vmin && aPoint.Y() <= Vmax) params.Append( ip.ParamOnFirst() ); } if (is.HasLastPoint()) { const IntRes2d_IntersectionPoint& ip = is.LastPoint(); gp_Pnt2d aPoint = ip.Value(); if (aPoint.X() >= Umin && aPoint.X() <= Umax && aPoint.Y() >= Vmin && aPoint.Y() <= Vmax) params.Append( ip.ParamOnFirst() ); } } } } if (!params.IsEmpty()) { if (params.Length() == 1) { gp_Pnt2d PntFirst = theCurve->Value(FirstPar); if (PntFirst.X() >= Umin && PntFirst.X() <= Umax && PntFirst.Y() >= Vmin && PntFirst.Y() <= Vmax) { if (LastPar > params(1)) LastPar = params(1); } else if (FirstPar < params(1)) FirstPar = params(1); } else { Standard_Real fpar = RealLast(), lpar = RealFirst(); for (i = 1; i <= params.Length(); i++) { if (params(i) < fpar) fpar = params(i); if (params(i) > lpar) lpar = params(i); } if (FirstPar < fpar) FirstPar = fpar; if (LastPar > lpar) LastPar = lpar; } } //// end of check //// (Handle(BRep_GCurve)::DownCast(CurveRep))->SetRange( FirstPar, LastPar ); //gp_Pnt2d Pfirst = theCurve->Value(FirstPar); //gp_Pnt2d Plast = theCurve->Value(LastPar); //(Handle(BRep_CurveOnSurface)::DownCast(CurveRep))->SetUVPoints( Pfirst, Plast ); //update FirstParOnPC and LastParOnPC if (FirstPar > FirstParOnPC) { FirstParOnPC = FirstPar; MinPC = theCurve; MinSurf = theSurf; MinLoc = CurveRep->Location(); } if (LastPar < LastParOnPC) { LastParOnPC = LastPar; MinPC = theCurve; MinSurf = theSurf; MinLoc = CurveRep->Location(); } } } Standard_Real f, l; Handle(Geom_Curve) C3d = BRep_Tool::Curve( NE, f, l ); if (NbPCurves) { MinLoc = E.Location() * MinLoc; if (!C3d.IsNull()) { if (MinPC->IsClosed()) { f = FirstParOnPC; l = LastParOnPC; } else if (C3d->IsPeriodic()) { Standard_Real delta = (C3d->Period() - (l - f))*0.5; delta *= 0.95; f -= delta; l += delta; } else if (C3d->IsClosed()) l -= 0.05*(l - f); else { f = FirstParOnPC; l = LastParOnPC; GeomAPI_ProjectPointOnCurve Projector; if (!Precision::IsInfinite(FirstParOnPC)) { gp_Pnt2d P2d1 = MinPC->Value(FirstParOnPC); gp_Pnt P1 = MinSurf->Value( P2d1.X(), P2d1.Y() ); P1.Transform(MinLoc.Transformation()); Projector.Init( P1, C3d ); if (Projector.NbPoints() > 0) f = Projector.LowerDistanceParameter(); #ifdef OCCT_DEBUG else std::cout<<"ProjectPointOnCurve not done"<Value(LastParOnPC); gp_Pnt P2 = MinSurf->Value( P2d2.X(), P2d2.Y() ); P2.Transform(MinLoc.Transformation()); Projector.Init( P2, C3d ); if (Projector.NbPoints() > 0) l = Projector.LowerDistanceParameter(); #ifdef OCCT_DEBUG else std::cout<<"ProjectPointOnCurve not done"<Transformed(MinLoc.Transformation())); Standard_Real max_deviation = 0.; if (Precision::IsInfinite(FirstParOnPC) || Precision::IsInfinite(LastParOnPC)) { if (MinPC->IsInstance(STANDARD_TYPE(Geom2d_Line))) { Standard_Boolean IsLine = Standard_False; if (MinSurf->IsInstance(STANDARD_TYPE(Geom_Plane))) IsLine = Standard_True; else if (MinSurf->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)) || MinSurf->IsInstance(STANDARD_TYPE(Geom_ConicalSurface))) { Handle(Geom2d_Line) theLine = Handle(Geom2d_Line)::DownCast (MinPC); gp_Dir2d LineDir = theLine->Direction(); if (LineDir.IsParallel( gp::DY2d(), Precision::Angular() )) IsLine = Standard_True; } if (IsLine) { gp_Pnt2d P2d1 = MinPC->Value(0.), P2d2 = MinPC->Value(1.); gp_Pnt P1 = MinSurf->Value(P2d1.X(), P2d1.Y()); gp_Pnt P2 = MinSurf->Value(P2d2.X(), P2d2.Y()); gp_Vec aVec(P1, P2); C3d = new Geom_Line( P1, aVec ); } } } else { Geom2dAdaptor_Curve AC2d( MinPC, FirstParOnPC, LastParOnPC ); GeomAdaptor_Surface GAsurf( MinSurf ); Handle(Geom2dAdaptor_Curve) HC2d = new Geom2dAdaptor_Curve( AC2d ); Handle(GeomAdaptor_Surface) HSurf = new GeomAdaptor_Surface( GAsurf ); Adaptor3d_CurveOnSurface ConS( HC2d, HSurf ); Standard_Real /*max_deviation,*/ average_deviation; GeomAbs_Shape Continuity = GeomAbs_C1; Standard_Integer MaxDegree = 14; Standard_Integer MaxSegment = evaluateMaxSegment(ConS); GeomLib::BuildCurve3d(Precision::Confusion(), ConS, FirstParOnPC, LastParOnPC, C3d, max_deviation, average_deviation, Continuity, MaxDegree, MaxSegment); } BB.UpdateEdge( NE, C3d, max_deviation ); //BB.Range( NE, FirstParOnPC, LastParOnPC ); Standard_Boolean ProjectionSuccess = Standard_True; if (NbPCurves > 1) //BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True ); for (itr.Initialize((Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves()); itr.More(); itr.Next()) { Handle( BRep_CurveRepresentation ) CurveRep = itr.Value(); Standard_Real FirstPar, LastPar; if (CurveRep->IsCurveOnSurface()) { Handle(Geom2d_Curve) theCurve = CurveRep->PCurve(); Handle(Geom_Surface) theSurf = CurveRep->Surface(); TopLoc_Location theLoc = CurveRep->Location(); if (theCurve == MinPC && theSurf == MinSurf && theLoc == MinLoc) continue; FirstPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First(); LastPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last(); if (Abs(FirstPar - FirstParOnPC) > Precision::PConfusion() || Abs(LastPar - LastParOnPC) > Precision::PConfusion()) { theLoc = E.Location() * theLoc; theSurf = Handle(Geom_Surface)::DownCast (theSurf->Transformed(theLoc.Transformation())); if (theCurve->IsInstance(STANDARD_TYPE(Geom2d_Line)) && theSurf->IsKind(STANDARD_TYPE(Geom_BoundedSurface))) { gp_Dir2d theDir = Handle(Geom2d_Line)::DownCast (theCurve)->Direction(); if (theDir.IsParallel(gp::DX2d(), Precision::Angular()) || theDir.IsParallel(gp::DY2d(), Precision::Angular())) { Standard_Real U1, U2, V1, V2; theSurf->Bounds(U1, U2, V1, V2); gp_Pnt2d Origin = Handle(Geom2d_Line)::DownCast (theCurve)->Location(); if (Abs(Origin.X()-U1) <= Precision::Confusion() || Abs(Origin.X()-U2) <= Precision::Confusion() || Abs(Origin.Y()-V1) <= Precision::Confusion() || Abs(Origin.Y()-V2) <= Precision::Confusion()) { BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True ); break; } } } if (!C3d.IsNull() && FirstParOnPC < LastParOnPC) { Handle(Geom2d_Curve) ProjPCurve = GeomProjLib::Curve2d(C3d, FirstParOnPC, LastParOnPC, theSurf); if (ProjPCurve.IsNull()) ProjectionSuccess = Standard_False; else CurveRep->PCurve(ProjPCurve); } else { return Standard_False; } } } } if (ProjectionSuccess) BB.Range( NE, FirstParOnPC, LastParOnPC ); else { BB.Range( NE, FirstParOnPC, LastParOnPC, Standard_True ); BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True ); } } } else //no pcurves { Standard_Real FirstPar = C3d->FirstParameter(); Standard_Real LastPar = C3d->LastParameter(); if (C3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) && (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)) { Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(C3d, FirstPar, LastPar); // The curve is not prolonged on begin or end. // Trying to prolong it adding a segment to its bound. gp_Pnt aPBnd; gp_Vec aVBnd; gp_Pnt aPBeg; gp_Dir aDBnd; Handle(Geom_Line) aLin; Handle(Geom_TrimmedCurve) aSegment; GeomConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1); Standard_Real aTol = Precision::Confusion(); Standard_Real aDelta = Max(a2Offset, 1.); if (FirstPar > anEf - a2Offset) { C3d->D1(FirstPar, aPBnd, aVBnd); aDBnd.SetXYZ(aVBnd.XYZ()); aPBeg = aPBnd.Translated(gp_Vec(-aDelta*aDBnd.XYZ())); aLin = new Geom_Line(aPBeg, aDBnd); aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return Standard_True; } if (LastPar < anEl + a2Offset) { C3d->D1(LastPar, aPBeg, aVBnd); aDBnd.SetXYZ(aVBnd.XYZ()); aLin = new Geom_Line(aPBeg, aDBnd); aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return Standard_True; } C3d = aCompCurve.BSplineCurve(); FirstPar = C3d->FirstParameter(); LastPar = C3d->LastParameter(); BB.UpdateEdge(NE, C3d, Precision::Confusion()); } else if (C3d->IsPeriodic()) { Standard_Real delta = (C3d->Period() - (anEl - anEf))*0.5; delta *= 0.95; FirstPar = anEf - delta; LastPar = anEl + delta; } else if (C3d->IsClosed()) LastPar -= 0.05*(LastPar - FirstPar); BB.Range( NE, FirstPar, LastPar ); } return Standard_True; } // Modified by skv - Fri Dec 26 17:00:57 2003 OCC4455 End //======================================================================= //function : UpdateVertex //purpose : //======================================================================= static Standard_Boolean UpdateVertex(const TopoDS_Vertex& V, TopoDS_Edge& OE, TopoDS_Edge& NE, Standard_Real TolConf) { BRepAdaptor_Curve OC(OE); BRepAdaptor_Curve NC(NE); Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter(); Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter(); Standard_Real U = 0.; Standard_Real ParTol = Precision::PConfusion(); gp_Pnt P = BRep_Tool::Pnt(V); Standard_Boolean OK = Standard_False; if (P.Distance(OC.Value(Of)) < TolConf) { if (Of >= Nf + ParTol && Of <= Nl + ParTol && P.Distance(NC.Value(Of)) < TolConf) { OK = Standard_True; U = Of; } } if (P.Distance(OC.Value(Ol)) < TolConf) { if (Ol >= Nf + ParTol && Ol <= Nl + ParTol && P.Distance(NC.Value(Ol)) < TolConf) { OK = Standard_True; U = Ol; } } if (OK) { BRep_Builder B; TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD); TopoDS_Edge EE = TopoDS::Edge(aLocalShape); // TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD)); aLocalShape = V.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape), U,NE,BRep_Tool::Tolerance(NE)); // B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), // U,NE,BRep_Tool::Tolerance(NE)); } return OK; } //======================================================================= //function : Compute //purpose : //======================================================================= void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)& AsDes, const TopoDS_Face& F, const TopTools_IndexedMapOfShape& NewEdges, const Standard_Real Tol, const TopTools_DataMapOfShapeListOfShape& theEdgeIntEdges, TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, const Message_ProgressRange& theRange) { #ifdef DRAW NbF2d++; NbE2d = 0; #endif //Do not intersect the edges of face TopTools_MapOfShape EdgesOfFace; TopExp_Explorer Explo( F, TopAbs_EDGE ); for (; Explo.More(); Explo.Next()) EdgesOfFace.Add( Explo.Current() ); //----------------------------------------------------------- // calculate intersections2d on faces touched by // intersection3d //--------------------------------------------------------- TopTools_ListIteratorOfListOfShape it1LE ; TopTools_ListIteratorOfListOfShape it2LE ; //----------------------------------------------- // Intersection of edges 2*2. //----------------------------------------------- const TopTools_ListOfShape& LE = AsDes->Descendant(F); TopoDS_Vertex V1,V2; Standard_Integer j, i = 1; BRepAdaptor_Surface BAsurf(F); // Message_ProgressScope aPS(theRange, "Intersecting edges on faces", LE.Size()); for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next(), aPS.Next()) { if (!aPS.More()) { return; } const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value()); j = 1; it2LE.Initialize(LE); while (j < i && it2LE.More()) { const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value()); Standard_Boolean ToIntersect = Standard_True; if (theEdgeIntEdges.IsBound(E1)) { const TopTools_ListOfShape& aElist = theEdgeIntEdges(E1); TopTools_ListIteratorOfListOfShape itedges (aElist); for (; itedges.More(); itedges.Next()) if (E2.IsSame (itedges.Value())) ToIntersect = Standard_False; if (ToIntersect) { for (itedges.Initialize(aElist); itedges.More(); itedges.Next()) { const TopoDS_Shape& anEdge = itedges.Value(); if (theEdgeIntEdges.IsBound(anEdge)) { const TopTools_ListOfShape& aElist2 = theEdgeIntEdges(anEdge); TopTools_ListIteratorOfListOfShape itedges2 (aElist2); for (; itedges2.More(); itedges2.Next()) if (E2.IsSame (itedges2.Value())) ToIntersect = Standard_False; } } } } //-------------------------------------------------------------- // Intersections of New edges obtained by intersection // between them and with edges of restrictions //------------------------------------------------------ if (ToIntersect && (!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, theDMVV); // EdgeInter(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),E1,E2,AsDes,Tol,Standard_True); } it2LE.Next(); j++; } i++; } } //======================================================================= //function : ConnexIntByInt //purpose : //======================================================================= Standard_Boolean BRepOffset_Inter2d::ConnexIntByInt (const TopoDS_Face& FI, BRepOffset_Offset& OFI, TopTools_DataMapOfShapeShape& MES, const TopTools_DataMapOfShapeShape& Build, const Handle(BRepAlgo_AsDes)& theAsDes, const Handle(BRepAlgo_AsDes)& AsDes2d, const Standard_Real Offset, const Standard_Real Tol, const BRepOffset_Analyse& Analyse, TopTools_IndexedMapOfShape& FacesWithVerts, BRepAlgo_Image& theImageVV, TopTools_DataMapOfShapeListOfShape& theEdgeIntEdges, TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, const Message_ProgressRange& theRange) { TopTools_DataMapOfShapeListOfShape MVE; BRepOffset_Tool::MapVertexEdges(FI,MVE); Message_ProgressScope aPS(theRange, "Intersecting edges obtained as intersection of faces", 1, Standard_True); //--------------------- // Extension of edges. //--------------------- TopoDS_Edge NE; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(MVE); for ( ; it.More(); it.Next()) { if (!aPS.More()) { return Standard_False; } const TopTools_ListOfShape& L = it.Value(); Standard_Boolean YaBuild = 0; TopTools_ListIteratorOfListOfShape itL(L); for (; itL.More(); itL.Next()) { YaBuild = Build.IsBound(itL.Value()); if (YaBuild) break; } if (YaBuild) { for (itL.Initialize(L); itL.More(); itL.Next()) { const TopoDS_Edge& EI = TopoDS::Edge(itL.Value()); if (EI.Orientation() != TopAbs_FORWARD && EI.Orientation() != TopAbs_REVERSED) continue; TopoDS_Shape aLocalShape = OFI.Generated(EI); const TopoDS_Edge& OE = TopoDS::Edge(aLocalShape); if (!MES.IsBound(OE) && !Build.IsBound(EI)) { if (!ExtentEdge(OE, NE, Offset)) { return Standard_False; } MES.Bind (OE,NE); } } } } TopoDS_Face FIO = TopoDS::Face(OFI.Face()); if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO)); // BRepAdaptor_Surface BAsurf(FIO); TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE); for (; exp.More(); exp.Next(), aPS.Next()) { if (!aPS.More()) { return Standard_False; } const TopoDS_Wire& W = TopoDS::Wire(exp.Current()); BRepTools_WireExplorer wexp; Standard_Boolean end = Standard_False ; TopoDS_Edge FirstE,CurE,NextE; TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD); TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD); wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace)); if (!wexp.More()) continue; // Protection from case when explorer does not contain edges. CurE = FirstE = wexp.Current(); TopTools_IndexedMapOfShape Edges; while (!end) { wexp.Next(); if (wexp.More()) { NextE = wexp.Current(); } else { NextE = FirstE; end = Standard_True; } if (CurE.IsSame(NextE)) continue; TopoDS_Vertex Vref = CommonVertex(CurE, NextE); CurE = Analyse.EdgeReplacement (FI, CurE); NextE = Analyse.EdgeReplacement (FI, NextE); TopoDS_Shape aLocalShape = OFI.Generated(CurE); TopoDS_Edge CEO = TopoDS::Edge(aLocalShape); aLocalShape = OFI.Generated(NextE); TopoDS_Edge NEO = TopoDS::Edge(aLocalShape); //------------------------------------------ // Inter processing of images of CurE NextE. //------------------------------------------ TopTools_ListOfShape LV1,LV2; Standard_Boolean DoInter = 1; TopoDS_Shape NE1,NE2; TopTools_SequenceOfShape NE1seq, NE2seq; TopAbs_Orientation anOr1 = TopAbs_EXTERNAL, anOr2 = TopAbs_EXTERNAL; Standard_Integer aChoice = 0; if (Build.IsBound(CurE) && Build.IsBound(NextE)) { aChoice = 1; NE1 = Build(CurE ); NE2 = Build(NextE); GetEdgesOrientedInFace (NE1, FIO, theAsDes, NE1seq); GetEdgesOrientedInFace (NE2, FIO, theAsDes, NE2seq); anOr1 = TopAbs_REVERSED; anOr2 = TopAbs_FORWARD; } else if (Build.IsBound(CurE) && MES.IsBound(NEO)) { aChoice = 2; NE1 = Build(CurE); NE2 = MES (NEO); NE2.Orientation (NextE.Orientation()); GetEdgesOrientedInFace (NE1, FIO, theAsDes, NE1seq); NE2seq.Append (NE2); anOr1 = TopAbs_REVERSED; anOr2 = TopAbs_FORWARD; } else if (Build.IsBound(NextE) && MES.IsBound(CEO)) { aChoice = 3; NE1 = Build(NextE); NE2 = MES(CEO); NE2.Orientation (CurE.Orientation()); GetEdgesOrientedInFace (NE1, FIO, theAsDes, NE1seq); NE2seq.Append (NE2); anOr1 = TopAbs_FORWARD; anOr2 = TopAbs_REVERSED; } else { DoInter = 0; } if (DoInter) { //------------------------------------ // NE1,NE2 can be a compound of Edges. //------------------------------------ Standard_Boolean bCoincide; TopoDS_Edge aE1, aE2; if (aChoice == 1 || aChoice == 2) { aE1 = TopoDS::Edge (NE1seq.Last()); aE2 = TopoDS::Edge (NE2seq.First()); } else // aChoice == 3 { aE1 = TopoDS::Edge (NE1seq.First()); aE2 = TopoDS::Edge (NE2seq.Last()); } if (aE1.Orientation() == TopAbs_REVERSED) anOr1 = TopAbs::Reverse(anOr1); if (aE2.Orientation() == TopAbs_REVERSED) anOr2 = TopAbs::Reverse(anOr2); RefEdgeInter(FIO, BAsurf, aE1, aE2, anOr1, anOr2, AsDes2d, Tol, Standard_True, Vref, theImageVV, theDMVV, bCoincide); if (theEdgeIntEdges.IsBound(aE1)) theEdgeIntEdges(aE1).Append(aE2); else { TopTools_ListOfShape aElist; aElist.Append(aE2); theEdgeIntEdges.Bind (aE1, aElist); } if (theEdgeIntEdges.IsBound(aE2)) theEdgeIntEdges(aE2).Append(aE1); else { TopTools_ListOfShape aElist; aElist.Append(aE1); theEdgeIntEdges.Bind (aE2, aElist); } // // check if some of the offset edges have been // generated out of the common vertex if (Build.IsBound(Vref)) { FacesWithVerts.Add(FI); } } else { TopoDS_Vertex V = CommonVertex(CEO,NEO); if (!V.IsNull()) { if (MES.IsBound(CEO)) { UpdateVertex (V,CEO,TopoDS::Edge(MES(CEO)),Tol); AsDes2d->Add (MES(CEO),V); } if (MES.IsBound(NEO)) { UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol); AsDes2d->Add (MES(NEO),V); } } } CurE = wexp.Current(); } } return Standard_True; } //======================================================================= //function : ConnexIntByIntInVert //purpose : Intersection of the edges generated out of vertices //======================================================================= void BRepOffset_Inter2d::ConnexIntByIntInVert (const TopoDS_Face& FI, BRepOffset_Offset& OFI, TopTools_DataMapOfShapeShape& MES, const TopTools_DataMapOfShapeShape& Build, const Handle(BRepAlgo_AsDes)& AsDes, const Handle(BRepAlgo_AsDes)& AsDes2d, const Standard_Real Tol, const BRepOffset_Analyse& Analyse, TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, const Message_ProgressRange& theRange) { TopoDS_Face FIO = TopoDS::Face(OFI.Face()); if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO)); // TopTools_MapOfShape aME; const TopTools_ListOfShape& aLE = AsDes->Descendant(FIO); TopTools_ListIteratorOfListOfShape aItLE(aLE); for (; aItLE.More(); aItLE.Next()) { const TopoDS_Shape& aE = aItLE.Value(); aME.Add(aE); } // BRepAdaptor_Surface BAsurf(FIO); // Message_ProgressScope aPS(theRange, "Intersecting edges created from vertices", 1, Standard_True); TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE); for (; exp.More(); exp.Next(), aPS.Next()) { if (!aPS.More()) { return; } const TopoDS_Wire& W = TopoDS::Wire(exp.Current()); // BRepTools_WireExplorer wexp; Standard_Boolean end = Standard_False ; TopoDS_Edge FirstE,CurE,NextE; // TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD); TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD); wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace)); if (!wexp.More()) continue; // Protection from case when explorer does not contain edges. // CurE = FirstE = wexp.Current(); while (!end) { wexp.Next(); if (wexp.More()) { NextE = wexp.Current(); } else { NextE = FirstE; end = Standard_True; } if (CurE.IsSame(NextE)) continue; // TopoDS_Vertex Vref = CommonVertex(CurE, NextE); if (!Build.IsBound(Vref)) { CurE = NextE; continue; } CurE = Analyse.EdgeReplacement (FI, CurE); NextE = Analyse.EdgeReplacement (FI, NextE); TopoDS_Shape aLocalShape = OFI.Generated(CurE); TopoDS_Edge CEO = TopoDS::Edge(aLocalShape); aLocalShape = OFI.Generated(NextE); TopoDS_Edge NEO = TopoDS::Edge(aLocalShape); // TopoDS_Shape NE1,NE2; TopAbs_Orientation anOr1 = TopAbs_EXTERNAL, anOr2 = TopAbs_EXTERNAL; if (Build.IsBound(CurE) && Build.IsBound(NextE)) { NE1 = Build(CurE ); NE2 = Build(NextE); } else if (Build.IsBound(CurE) && MES.IsBound(NEO)) { NE1 = Build(CurE); NE2 = MES (NEO); } else if (Build.IsBound(NextE) && MES.IsBound(CEO)) { NE1 = Build(NextE); NE2 = MES(CEO); } else { CurE = wexp.Current(); continue; } // TopExp_Explorer Exp1, Exp2; Standard_Boolean bCoincide; // intersect edges generated from vertex with the edges of the face const TopoDS_Shape& NE3 = Build(Vref); // for (Exp2.Init(NE3, TopAbs_EDGE); Exp2.More(); Exp2.Next()) { const TopoDS_Edge& aE3 = *(TopoDS_Edge*)&Exp2.Current(); if (!aME.Contains(aE3)) { continue; } // // intersection with first edge for (Exp1.Init(NE1, TopAbs_EDGE); Exp1.More(); Exp1.Next()) { const TopoDS_Edge& aE1 = TopoDS::Edge(Exp1.Current()); BRepAlgo_Image anEmptyImage; RefEdgeInter(FIO, BAsurf, aE1, aE3, anOr1, anOr2, AsDes2d, Tol, Standard_True, Vref, anEmptyImage, theDMVV, bCoincide); if (bCoincide) { // in case of coincidence trim the edge E3 the same way as E1 Store(aE3, AsDes2d->Descendant(aE1), Tol, Standard_True, AsDes2d, theDMVV); } } // // intersection with second edge for (Exp1.Init(NE2, TopAbs_EDGE); Exp1.More(); Exp1.Next()) { const TopoDS_Edge& aE2 = TopoDS::Edge(Exp1.Current()); BRepAlgo_Image anEmptyImage; RefEdgeInter(FIO, BAsurf, aE2, aE3, anOr1, anOr2, AsDes2d, Tol, Standard_True, Vref, anEmptyImage, theDMVV, bCoincide); if (bCoincide) { // in case of coincidence trim the edge E3 the same way as E2 Store(aE3, AsDes2d->Descendant(aE2), Tol, Standard_True, AsDes2d, theDMVV); } } // // intersection of the edges generated from vertex // among themselves for (Exp1.Init(NE3, TopAbs_EDGE); Exp1.More(); Exp1.Next()) { if (aE3.IsSame(Exp1.Current())) { break; } } // for (Exp1.Next(); Exp1.More(); Exp1.Next()) { const TopoDS_Edge& aE3Next = TopoDS::Edge(Exp1.Current()); if (aME.Contains(aE3Next)) { BRepAlgo_Image anEmptyImage; RefEdgeInter(FIO, BAsurf, aE3Next, aE3, anOr1, anOr2, AsDes2d, Tol, Standard_True, Vref, anEmptyImage, theDMVV, bCoincide); } } } CurE = wexp.Current(); } } } //======================================================================= //function : MakeChain //purpose : //======================================================================= static void MakeChain(const TopoDS_Shape& theV, const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, TopTools_MapOfShape& theMDone, TopTools_ListOfShape& theChain) { if (theMDone.Add(theV)) { theChain.Append(theV); const TopTools_ListOfShape* pLV = theDMVV.Seek(theV); if (pLV) { TopTools_ListIteratorOfListOfShape aIt(*pLV); for (; aIt.More(); aIt.Next()) { MakeChain(aIt.Value(), theDMVV, theMDone, theChain); } } } } //======================================================================= //function : FuseVertices //purpose : //======================================================================= Standard_Boolean BRepOffset_Inter2d::FuseVertices (const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV, const Handle(BRepAlgo_AsDes)& theAsDes, BRepAlgo_Image& theImageVV) { 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 TopTools_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)); // TopTools_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; if (!BRep_Tool::Parameter(aVOldInt, aE, aT)) { return Standard_False; } aBB.UpdateVertex(aVNewInt, aT, aE, aTolE); } // and replace the vertex theAsDes->Replace(aVOld, aVNew); if (theImageVV.IsImage(aVOld)) { const TopoDS_Vertex& aProVertex = TopoDS::Vertex (theImageVV.ImageFrom(aVOld)); theImageVV.Add (aProVertex, aVNew.Oriented(TopAbs_FORWARD)); } } } return Standard_True; }