From: jgv Date: Wed, 4 Oct 2017 11:08:48 +0000 (+0300) Subject: Improvements of the algorithm BRepOffsetAPI_PatchFaces: X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=c1ca6a033415f9b045889c707a4a6a4594096e09;p=occt-copy.git Improvements of the algorithm BRepOffsetAPI_PatchFaces: - Increase the value of extension in EnlargeGeometry to provide proper intersection of adjacent faces. - Numerous bug fixes in the algorithm. --- diff --git a/src/BRepOffset/BRepOffset_Tool.cxx b/src/BRepOffset/BRepOffset_Tool.cxx index da2d9b0a11..ba337e4612 100644 --- a/src/BRepOffset/BRepOffset_Tool.cxx +++ b/src/BRepOffset/BRepOffset_Tool.cxx @@ -2817,7 +2817,7 @@ static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S, const Standard_Boolean GlobalEnlargeVfirst, const Standard_Boolean GlobalEnlargeVlast) { - const Standard_Real coeff = 2.; + const Standard_Real coeff = 1.; const Standard_Real TolApex = 1.e-5; Standard_Boolean SurfaceChange = Standard_False; @@ -2865,7 +2865,7 @@ static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S, { viso = S->VIso( vf1 ); GeomAdaptor_Curve gac( viso ); - du = GCPnts_AbscissaPoint::Length( gac ) / coeff; + du = GCPnts_AbscissaPoint::Length( gac ) * coeff; uiso1 = S->UIso( uf1 ); uiso2 = S->UIso( uf2 ); if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex) @@ -2886,7 +2886,7 @@ static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S, { uiso = S->UIso( uf1 ); GeomAdaptor_Curve gac( uiso ); - dv = GCPnts_AbscissaPoint::Length( gac ) / coeff; + dv = GCPnts_AbscissaPoint::Length( gac ) * coeff; viso1 = S->VIso( vf1 ); viso2 = S->VIso( vf2 ); if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex) @@ -2941,7 +2941,7 @@ static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S, { viso = S->VIso( v1 ); gac.Load( viso ); - du = GCPnts_AbscissaPoint::Length( gac ) / coeff; + du = GCPnts_AbscissaPoint::Length( gac ) * coeff; uiso1 = S->UIso( u1 ); uiso2 = S->UIso( u2 ); if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex) @@ -2953,7 +2953,7 @@ static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S, { uiso = S->UIso( u1 ); gac.Load( uiso ); - dv = GCPnts_AbscissaPoint::Length( gac ) / coeff; + dv = GCPnts_AbscissaPoint::Length( gac ) * coeff; viso1 = S->VIso( v1 ); viso2 = S->VIso( v2 ); if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex) diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx index cf1be4cd4e..f382c1d338 100644 --- a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -38,9 +40,375 @@ #include #include #include -#include -#include +#include +//#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#ifdef DRAW_PatchFaces +#include +#endif + +static Standard_Boolean EdgeContains(const TopoDS_Edge& theEdge, + const TopoDS_Vertex& theVertex) +{ + TopoDS_Iterator ite(theEdge); + for (; ite.More(); ite.Next()) + if (theVertex.IsSame(ite.Value())) + return Standard_True; + + return Standard_False; +} + +static void UpdateVertexTolOnFace(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace) +{ + if (!EdgeContains(theEdge, theVertex)) + return; + + Standard_Real aParam = BRep_Tool::Parameter(theVertex, theEdge); + BRepAdaptor_Curve2d BAcurve2d(theEdge, theFace); + gp_Pnt2d aPnt2d = BAcurve2d.Value(aParam); + + BRepAdaptor_Surface BAsurf(theFace, Standard_False); + gp_Pnt aPnt = BAsurf.Value(aPnt2d.X(), aPnt2d.Y()); + + gp_Pnt PntVtx = BRep_Tool::Pnt(theVertex); + Standard_Real aDist = PntVtx.Distance(aPnt); + + BRep_Builder BB; + BB.UpdateVertex(theVertex, 1.001*aDist); +} + +static void ProlongEdge(const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + gp_Pnt& theFirstPnt, + gp_Pnt& theLastPnt) +{ + BRepAdaptor_Curve2d BAcurve2d(theEdge, theFace); + gp_Pnt2d EndP2d [2]; + gp_Pnt2d StartP2d [2]; + gp_Vec2d StartVec [2]; + Handle(Geom2d_Curve) Ray [2], BoundLine [4]; + Geom2dAdaptor_Curve GAray [2], GAline [4]; + + BAcurve2d.D1(BAcurve2d.FirstParameter(), StartP2d[0], StartVec[0]); + StartVec[0].Reverse(); + BAcurve2d.D1(BAcurve2d.LastParameter(), StartP2d[1], StartVec[1]); + + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace); + Standard_Real Umin, Umax, Vmin, Vmax; + aSurf->Bounds(Umin, Umax, Vmin, Vmax); + BoundLine[0] = new Geom2d_Line(gp_Pnt2d( Umin, Vmin ), + gp_Dir2d( 1., 0. )); + BoundLine[0] = new Geom2d_TrimmedCurve(BoundLine[0], 0., Umax-Umin); + BoundLine[1] = new Geom2d_Line(gp_Pnt2d( Umax, Vmin ), + gp_Dir2d( 0., 1. )); + BoundLine[1] = new Geom2d_TrimmedCurve(BoundLine[1], 0., Vmax-Vmin); + BoundLine[2] = new Geom2d_Line(gp_Pnt2d( Umax, Vmax ), + gp_Dir2d( -1., 0. )); + BoundLine[2] = new Geom2d_TrimmedCurve(BoundLine[2], 0., Umax-Umin); + BoundLine[3] = new Geom2d_Line(gp_Pnt2d( Umin, Vmax ), + gp_Dir2d( 0., -1. )); + BoundLine[3] = new Geom2d_TrimmedCurve(BoundLine[3], 0., Vmax-Vmin); + + GAline[0].Load(BoundLine[0]); + GAline[1].Load(BoundLine[1]); + GAline[2].Load(BoundLine[2]); + GAline[3].Load(BoundLine[3]); + + for (Standard_Integer i = 0; i < 2; i++) + { + Ray[i] = new Geom2d_Line(StartP2d[i], StartVec[i]); + //Ray[i] = new Geom2d_TrimmedCurve(Ray[i], 0., Precision::Infinite()); + GAray[i].Load(Ray[i], 0., Precision::Infinite()); + for (Standard_Integer j = 0; j < 4; j++) + { + Geom2dInt_GInter Inters2d(GAray[i], GAline[j], + Precision::PConfusion(), Precision::PConfusion()); + if (Inters2d.IsDone() && Inters2d.NbPoints() > 0) + { + const IntRes2d_IntersectionPoint& ip = Inters2d.Point(1); + EndP2d[i] = ip.Value(); + break; + } + } + } + + BRepAdaptor_Surface BAsurf(theFace, Standard_False); + theFirstPnt = BAsurf.Value(EndP2d[0].X(), EndP2d[0].Y()); + theLastPnt = BAsurf.Value(EndP2d[1].X(), EndP2d[1].Y()); +} + + +static Standard_Real Project2dPointOnSegment(const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + const Standard_Real theFirstPar, + const Standard_Real theLastPar, + const gp_Pnt2d& theP2dRef, + Standard_Real& theParam, + gp_Pnt2d& theP2d) +{ + Standard_Real fpar, lpar; + Handle(Geom2d_Curve) PCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, fpar, lpar); + Geom2dAdaptor_Curve GAcurve2d(PCurve, theFirstPar, theLastPar); + + Extrema_ExtPC2d Projector(theP2dRef, GAcurve2d); + Standard_Real Param[4], dist[4], distmin; + gp_Pnt2d Pnt2d[4]; + Param[1] = theFirstPar; + Param[2] = theLastPar; + Projector.TrimmedSquareDistances(dist[1], dist[2], Pnt2d[1], Pnt2d[2]); + dist[3] = RealLast(); + if (Projector.IsDone() && Projector.NbExt() > 0) + { + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= Projector.NbExt(); i++) + if (Projector.SquareDistance(i) < Projector.SquareDistance(imin)) + imin = i; + Param[3] = Projector.Point(imin).Parameter(); + dist[3] = Projector.SquareDistance(imin); + Pnt2d[3] = Projector.Point(imin).Value(); + } + + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= 3; i++) + if (dist[i] < dist[imin]) + imin = i; + + theParam = Param[imin]; + theP2d = Pnt2d[imin]; + distmin = dist[imin]; + return distmin; +} + +static void ProjectVertexOnAnotherEdge_2d(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theEdge2, + const TopoDS_Face& theFace, + const gp_Pnt2d& /*theP2dRef*/, + Standard_Real& theSqDistReached, + Standard_Real& theParamOnFirst, + Standard_Real& theParamOnSecond) +{ + theParamOnFirst = BRep_Tool::Parameter(theVertex, theEdge1); + BRepAdaptor_Curve2d FirstBAcurve2d(theEdge1, theFace); + BRepAdaptor_Curve2d SecondBAcurve2d(theEdge2, theFace); + gp_Pnt2d Point2dFromEdge1 = FirstBAcurve2d.Value(theParamOnFirst); + + Extrema_ExtPC2d Projector(Point2dFromEdge1, SecondBAcurve2d); + Standard_Real Param[4], dist[4]; + gp_Pnt2d Pnt2d[4]; + Param[1] = SecondBAcurve2d.FirstParameter(); + Param[2] = SecondBAcurve2d.LastParameter(); + Projector.TrimmedSquareDistances(dist[1], dist[2], Pnt2d[1], Pnt2d[2]); + //dist[1] = theP2dRef.SquareDistance(Pnt2d[1]); + //dist[2] = theP2dRef.SquareDistance(Pnt2d[2]); + dist[3] = RealLast(); + if (Projector.IsDone()) + { + Standard_Integer imin = 0; + for (Standard_Integer i = 1; i <= Projector.NbExt(); i++) + { + //gp_Pnt2d aPnt2dOnSecondEdge = Projector.Point(i).Value(); + //Standard_Real aDist = theP2dRef.SquareDistance(aPnt2dOnSecondEdge); + Standard_Real aDist = Projector.SquareDistance(i); + if (aDist < dist[3]) + { + dist[3] = aDist; + imin = i; + } + } + if (imin != 0) + { + Param[3] = Projector.Point(imin).Parameter(); + Pnt2d[3] = Projector.Point(imin).Value(); + } + } + + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= 3; i++) + if (dist[i] < dist[imin]) + imin = i; + + theParamOnSecond = Param[imin]; + theSqDistReached = dist[imin]; + + //BRepAdaptor_Surface BAnewsurf(theNewFace, Standard_False); + //thePnt = BAnewsurf.Value(Pnt[imin].X(), Pnt[imin].Y()); + + //thePnt2d = Pnt2d[imin]; + + //BRepAdaptor_Curve BAcurve(theEdge); + // BRepAdaptor_Curve BAnewcurve(theNewEdge); + + //thePnt = BAnewcurve.Value(theParam); + + //gp_Pnt PointOnEdge = BAcurve.Value(ParamOnEdge); + + //thePntSol.SetXYZ((thePntOnConst.XYZ() + thePnt.XYZ())/2); + + //theTolReached = PointOnEdge.Distance(thePnt); //sqrt(dist[imin]); + //theTolReached = thePntSol.Distance(thePnt); +} + +static Standard_Boolean IntersectIn2d(const TopoDS_Vertex& theNewVertex, + const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theEdge2, + const TopoDS_Face& theFace, + gp_Pnt2d& theP2dRef, + Standard_Real& theParamOnFirst, + Standard_Real& theParamOnSecond, + gp_Pnt& thePntSol, + gp_Pnt& thePntOnFirst, + gp_Pnt& thePntOnSecond, + TColStd_SequenceOfReal& theIntParamsOnFirst, + TColStd_SequenceOfReal& theIntParamsOnSecond) +{ + //Current range + BRepAdaptor_Curve BAprevcurve(theEdge1); + BRepAdaptor_Curve BAcurcurve(theEdge2); + BRepAdaptor_Curve2d BAprevcurve2d(theEdge1, theFace); + BRepAdaptor_Curve2d BAcurcurve2d(theEdge2, theFace); + + //Maximum range + /* + Standard_Real fpar, lpar; + Handle(Geom_Curve) Curve1 = BRep_Tool::Curve(theEdge1, fpar, lpar); + Handle(Geom_Curve) Curve2 = BRep_Tool::Curve(theEdge2, fpar, lpar); + Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(theEdge1, theFace, fpar, lpar); + Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(theEdge2, theFace, fpar, lpar); + GeomAdaptor_Curve BAprevcurve(Curve1); + GeomAdaptor_Curve BAcurcurve(Curve2); + Geom2dAdaptor_Curve BAprevcurve2d(PCurve1); + Geom2dAdaptor_Curve BAcurcurve2d(PCurve2); + */ + + Standard_Integer imin = 0; + //Standard_Real MinSumDist = RealLast(); + + Standard_Real ParOnPrev[4], ParOnCur[4], DistRef[4]; + gp_Pnt2d Pnt2d[4]; + DistRef[1] = DistRef[2] = DistRef[3] = RealLast(); + + Geom2dInt_GInter Inters2d(BAprevcurve2d, BAcurcurve2d, + Precision::PConfusion(), Precision::PConfusion()); + if (Inters2d.IsDone()) + { + for (Standard_Integer i = 1; i <= Inters2d.NbPoints(); i++) + { + const IntRes2d_IntersectionPoint& ip = Inters2d.Point(i); + Standard_Real ParOnFirst = ip.ParamOnFirst(); + Standard_Real ParOnSecond = ip.ParamOnSecond(); + theIntParamsOnFirst.Append(ParOnFirst); + theIntParamsOnSecond.Append(ParOnSecond); + gp_Pnt2d Pint2d = ip.Value(); + //Standard_Real aDist = Pnt2dOnNewEdge.SquareDistance(Pint2d); + Standard_Real aDist = theP2dRef.SquareDistance(Pint2d); + if (aDist < DistRef[1]) + { + DistRef[1] = aDist; + imin = i; + ParOnPrev[1] = ParOnFirst; + ParOnCur[1] = ParOnSecond; + } + //gp_Pnt Pint = BAprevcurve.Value(ip.ParamOnFirst()); + } + for (Standard_Integer i = 1; i <= Inters2d.NbSegments(); i++) + { + const IntRes2d_IntersectionSegment& iseg = Inters2d.Segment(i); + const IntRes2d_IntersectionPoint& FirstPoint = iseg.FirstPoint(); + const IntRes2d_IntersectionPoint& LastPoint = iseg.LastPoint(); + Standard_Real fparOnFirst = FirstPoint.ParamOnFirst(); + Standard_Real lparOnFirst = LastPoint.ParamOnFirst(); + Standard_Real fparOnSecond = FirstPoint.ParamOnSecond(); + Standard_Real lparOnSecond = LastPoint.ParamOnSecond(); + if (lparOnFirst < fparOnFirst) + { Standard_Real tmp = fparOnFirst; fparOnFirst = lparOnFirst; lparOnFirst = tmp; } + if (lparOnSecond < fparOnSecond) + { Standard_Real tmp = fparOnSecond; fparOnSecond = lparOnSecond; lparOnSecond = tmp; } + theIntParamsOnFirst.Append(fparOnFirst); + theIntParamsOnFirst.Append(lparOnFirst); + theIntParamsOnSecond.Append(fparOnSecond); + theIntParamsOnSecond.Append(lparOnSecond); + Standard_Real ParamOnFirst, ParamOnSecond; + gp_Pnt2d Pnt2dOnFirst, Pnt2dOnSecond; + Standard_Real aDist = Project2dPointOnSegment(theEdge1, theFace, + fparOnFirst, lparOnFirst, + theP2dRef, + ParamOnFirst, Pnt2dOnFirst); + Project2dPointOnSegment(theEdge2, theFace, + fparOnSecond, lparOnSecond, + Pnt2dOnFirst, + ParamOnSecond, Pnt2dOnSecond); + + if (aDist < DistRef[1]) + { + DistRef[1] = aDist; + imin = i; + ParOnPrev[1] = ParamOnFirst; + ParOnCur[1] = ParamOnSecond; + } + } + /* + if (imin != 0) + { + const IntRes2d_IntersectionPoint& ip = Inters2d.Point(imin); + ParOnPrev[1] = ip.ParamOnFirst(); + ParOnCur[1] = ip.ParamOnSecond(); + //theParamOnFirst = ip.ParamOnFirst(); + //theParamOnSecond = ip.ParamOnSecond(); + } + */ + } + + //Project + if (!theNewVertex.IsNull()) + { + if (EdgeContains(theEdge1, theNewVertex)) + { + ProjectVertexOnAnotherEdge_2d(theNewVertex, theEdge1, theEdge2, theFace, theP2dRef, + DistRef[2], ParOnPrev[2], ParOnCur[2]); + } + if (EdgeContains(theEdge2, theNewVertex)) + { + ProjectVertexOnAnotherEdge_2d(theNewVertex, theEdge2, theEdge1, theFace, theP2dRef, + DistRef[3], ParOnCur[3], ParOnPrev[3]); + } + } + + //Standard_Boolean SolutionFound = Standard_False; + Standard_Real MinDistRef = RealLast(); + imin = 0; + for (Standard_Integer i = 1; i <= 3; i++) + { + //if (!Precision::IsInfinite(DistRef[i])) + //SolutionFound = Standard_True; + if (DistRef[i] < MinDistRef) + { + MinDistRef = DistRef[i]; + imin = i; + } + } + + if (Precision::IsInfinite(MinDistRef)) + return Standard_False; + + theParamOnFirst = ParOnPrev[imin]; + theParamOnSecond = ParOnCur[imin]; + thePntOnFirst = BAprevcurve.Value(theParamOnFirst); + thePntOnSecond = BAcurcurve.Value(theParamOnSecond); + //theP2dRef = BAcurcurve2d.Value(theParamOnSecond); + thePntSol.SetXYZ((thePntOnFirst.XYZ() + thePntOnSecond.XYZ())/2); + return Standard_True; +} static TopoDS_Edge MakeNewEdgeWithOldPcurvesOnNewSurfaces(const TopoDS_Edge& theEdge, const TopoDS_Face& theOldFace1, @@ -53,7 +421,8 @@ static TopoDS_Edge MakeNewEdgeWithOldPcurvesOnNewSurfaces(const TopoDS_Edge& the BRep_Builder BB; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, fpar, lpar); - aNewEdge = BRepLib_MakeEdge(aCurve, aCurve->FirstParameter(), aCurve->LastParameter()); //??? + //aNewEdge = BRepLib_MakeEdge(aCurve, aCurve->FirstParameter(), aCurve->LastParameter()); //??? + aNewEdge = BRepLib_MakeEdge(aCurve, fpar, lpar); TopoDS_Vertex V1, V2; TopExp::Vertices(aNewEdge, V1, V2); aNewEdge.Free(Standard_True); @@ -66,6 +435,63 @@ static TopoDS_Edge MakeNewEdgeWithOldPcurvesOnNewSurfaces(const TopoDS_Edge& the Handle(Geom2d_Curve) aPCurve2 = BRep_Tool::CurveOnSurface(theEdge, theOldFace2, fpar, lpar); BB.UpdateEdge(aNewEdge, aPCurve2, theNewFace2, Etol); + gp_Pnt Pnt1, Pnt2, Pnt3, Pnt4; + ProlongEdge(aNewEdge, theNewFace1, Pnt1, Pnt2); + ProlongEdge(aNewEdge, theNewFace2, Pnt3, Pnt4); + + BRepAdaptor_Curve BAcurve(aNewEdge); + gp_Pnt FirstPnt = BAcurve.Value(BAcurve.FirstParameter()); + gp_Pnt LastPnt = BAcurve.Value(BAcurve.LastParameter()); + + Standard_Real DistFirst1 = FirstPnt.SquareDistance(Pnt1); + Standard_Real DistFirst2 = FirstPnt.SquareDistance(Pnt3); + Standard_Real DistLast1 = LastPnt.SquareDistance(Pnt2); + Standard_Real DistLast2 = LastPnt.SquareDistance(Pnt4); + + gp_Pnt NewFirstPnt, NewLastPnt; + NewFirstPnt = (DistFirst1 < DistFirst2)? Pnt1 : Pnt3; + NewLastPnt = (DistLast1 < DistLast2)? Pnt2 : Pnt4; + + Handle(Geom_BoundedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, + BAcurve.FirstParameter(), + BAcurve.LastParameter()); + GeomLib::ExtendCurveToPoint(aTrCurve, NewFirstPnt, 1, Standard_False); //before + GeomLib::ExtendCurveToPoint(aTrCurve, NewLastPnt, 1, Standard_True); //after + Handle(Geom_Curve) aCurveExt = aTrCurve; + + BB.UpdateEdge(aNewEdge, aTrCurve, Etol); + BB.Range(aNewEdge, aTrCurve->FirstParameter(), aTrCurve->LastParameter()); + + Handle(Geom_Surface) NewSurf1 = BRep_Tool::Surface(theNewFace1); + Handle(ShapeAnalysis_Surface) SAS1 = new ShapeAnalysis_Surface(NewSurf1); + ShapeConstruct_ProjectCurveOnSurface aToolProj; + aToolProj.Init(SAS1, Precision::Confusion()); + Handle(Geom2d_Curve) NewPCurve1; + aToolProj.Perform(aCurveExt, + aTrCurve->FirstParameter(), + aTrCurve->LastParameter(), + NewPCurve1); + Standard_Real TolReached = SAS1->Gap(); + //BB.UpdateEdge(anEdge, NullPCurve, aFace, 0.); + BB.UpdateEdge(aNewEdge, NewPCurve1, theNewFace1, TolReached); + + Handle(Geom_Surface) NewSurf2 = BRep_Tool::Surface(theNewFace2); + Handle(ShapeAnalysis_Surface) SAS2 = new ShapeAnalysis_Surface(NewSurf2); + aToolProj.Init(SAS2, Precision::Confusion()); + Handle(Geom2d_Curve) NewPCurve2; + aToolProj.Perform(aCurveExt, + aTrCurve->FirstParameter(), + aTrCurve->LastParameter(), + NewPCurve2); + TolReached = SAS2->Gap(); + BB.UpdateEdge(aNewEdge, NewPCurve2, theNewFace2, TolReached); + + Standard_Real ParamOfMaxDist; + BOPTools_AlgoTools::ComputeTolerance(theNewFace1, aNewEdge, TolReached, ParamOfMaxDist); + BB.UpdateEdge(aNewEdge, 1.001*TolReached); + BOPTools_AlgoTools::ComputeTolerance(theNewFace2, aNewEdge, TolReached, ParamOfMaxDist); + BB.UpdateEdge(aNewEdge, 1.001*TolReached); + return aNewEdge; } @@ -87,13 +513,68 @@ static void UpdateEdgeByProjectionOfPCurve(TopoDS_Edge& anEdge, Standard_Real TolReached = SAS->Gap(); //BB.UpdateEdge(anEdge, NullPCurve, aFace, 0.); BB.UpdateEdge(anEdge, NewPCurve, aBoundedNewFace, TolReached); + //Update tolerance for same parameter + Standard_Real ParamOfMaxDist; + BOPTools_AlgoTools::ComputeTolerance(aBoundedNewFace, anEdge, TolReached, ParamOfMaxDist); + /* + Standard_Integer NCONTROL = 23; + BRepAdaptor_Curve BAcurve(anEdge); + BRepAdaptor_Curve BAcurveonsu(anEdge, aBoundedNewFace); + for (Standard_Integer i = 0; i < NCONTROL; i++) + { + Standard_Real prm = ((NCONTROL-1-i)*fpar + i*lpar)/(NCONTROL-1); + gp_Pnt Pnt1 = BAcurve.Value(prm); + gp_Pnt Pnt2 = BAcurveonsu.Value(prm); + Standard_Real aDist = Pnt1.Distance(Pnt2); + if (aDist > TolReached) + TolReached = aDist; + } + */ + BB.UpdateEdge(anEdge, TolReached); + /////// + TopoDS_Vertex V1, V2; TopExp::Vertices(anEdge, V1, V2); BB.UpdateVertex(V1, TolReached); BB.UpdateVertex(V2, TolReached); } -static void ProjectVertexOnNewEdge(const TopoDS_Vertex& theVertex, +static Standard_Real ProjectPointOnEdge(const gp_Pnt& thePoint, + const TopoDS_Edge& theEdge, + Standard_Real& theParam, + gp_Pnt& thePnt) +{ + BRepAdaptor_Curve BAcurve(theEdge); + Extrema_ExtPC Projector(thePoint, BAcurve); + Standard_Real Param[4], dist[4]; + gp_Pnt Pnt[4]; + Param[1] = BAcurve.FirstParameter(); + Param[2] = BAcurve.LastParameter(); + Projector.TrimmedSquareDistances(dist[1], dist[2], Pnt[1], Pnt[2]); + dist[3] = RealLast(); + if (Projector.IsDone() && Projector.NbExt() > 0) + { + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= Projector.NbExt(); i++) + if (Projector.SquareDistance(i) < Projector.SquareDistance(imin)) + imin = i; + Param[3] = Projector.Point(imin).Parameter(); + dist[3] = Projector.SquareDistance(imin); + Pnt[3] = Projector.Point(imin).Value(); + } + + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= 3; i++) + if (dist[i] < dist[imin]) + imin = i; + + theParam = Param[imin]; + thePnt = Pnt[imin]; + Standard_Real MinSqDist = dist[imin]; + return MinSqDist; +} + +/*static void ProjectVertexOnNewEdge(const TopoDS_Vertex& theVertex, const TopoDS_Edge& theEdge, const TopoDS_Edge& theNewEdge, Standard_Real& theParam, @@ -130,8 +611,88 @@ static void ProjectVertexOnNewEdge(const TopoDS_Vertex& theVertex, theParam = Param[imin]; thePnt = Pnt[imin]; theTolReached = sqrt(dist[imin]); +}*/ + +static Standard_Boolean IsPCurveUiso(const Handle(Geom2d_Curve)& thePCurve, + Standard_Real theFirstPar, + Standard_Real theLastPar) +{ + gp_Pnt2d FirstP2d = thePCurve->Value(theFirstPar); + gp_Pnt2d LastP2d = thePCurve->Value(theLastPar); + + Standard_Real DeltaU = Abs(FirstP2d.X() - LastP2d.X()); + Standard_Real DeltaV = Abs(FirstP2d.Y() - LastP2d.Y()); + + return (DeltaU < DeltaV); +} + +static TopoDS_Edge GetSeamEdge(const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + const TopoDS_Face& theNewFace) +{ + TopoDS_Edge aSeamEdge; + + Standard_Real fpar, lpar; + Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, fpar, lpar); + Standard_Boolean IsUiso = IsPCurveUiso(aPCurve, fpar, lpar); + + TopExp_Explorer Explo(theNewFace, TopAbs_EDGE); + for (; Explo.More(); Explo.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); + if (BRepTools::IsReallyClosed(anEdge, theNewFace)) + { + Standard_Real NewFirst, NewLast; + Handle(Geom2d_Curve) aNewPCurve = BRep_Tool::CurveOnSurface(anEdge, theNewFace, + NewFirst, NewLast); + Standard_Boolean IsNewUiso = IsPCurveUiso(aNewPCurve, NewFirst, NewLast); + if (IsNewUiso == IsUiso) + { + aSeamEdge = anEdge; + break; + } + } + } + + TopoDS_Edge aNewEdge = TopoDS::Edge(aSeamEdge.EmptyCopied()); + return aNewEdge; +} + +static Standard_Boolean IsPCurveFirst(const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace) +{ + Standard_Real fpar, lpar; + Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(theEdge, theFace, fpar, lpar); + TopoDS_Edge RevEdge = TopoDS::Edge(theEdge.Reversed()); + Handle(Geom2d_Curve) AnotherPCurve = BRep_Tool::CurveOnSurface(RevEdge, theFace, fpar, lpar); + Standard_Boolean IsUiso = IsPCurveUiso(aPCurve, fpar, lpar); + + gp_Pnt2d aP2d = aPCurve->Value(fpar); + gp_Pnt2d AnotherP2d = AnotherPCurve->Value(fpar); + + Standard_Integer IndCoord = (IsUiso)? 1 : 2; // U or V + + Standard_Real aCoord = aP2d.Coord(IndCoord); + Standard_Real AnotherCoord = AnotherP2d.Coord(IndCoord); + + return (aCoord < AnotherCoord); } +static void CorrectOrientationOfSeam(const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + TopoDS_Edge& theNewEdge, + const TopoDS_Face& theNewFace) +{ + if (!BRepTools::IsReallyClosed(theEdge, theFace)) //only for seam + return; + + Standard_Boolean IsFirstPCurve = IsPCurveFirst(theEdge, theFace); + Standard_Boolean IsFirstNewPCurve = IsPCurveFirst(theNewEdge, theNewFace); + if (IsFirstPCurve != IsFirstNewPCurve) + theNewEdge.Reverse(); +} + +/* static TopoDS_Edge GetGeneratedEdge(const TopoDS_Edge& anEdge, const TopoDS_Face& aFace, const TopoDS_Face& aNewFace) @@ -169,18 +730,7 @@ static TopAbs_Orientation OrientationInEdge(const TopoDS_Vertex& theVertex, return TopAbs_FORWARD; return TopAbs_REVERSED; -} - -static Standard_Boolean EdgeContains(const TopoDS_Edge& theEdge, - const TopoDS_Vertex& theVertex) -{ - TopoDS_Iterator ite(theEdge); - for (; ite.More(); ite.Next()) - if (theVertex.IsSame(ite.Value())) - return Standard_True; - - return Standard_False; -} +}*/ static Standard_Boolean IsTangentFaces(const TopoDS_Edge& theEdge, @@ -251,7 +801,7 @@ static Standard_Boolean IsTangentFaces(const TopoDS_Edge& theEdge, else if (!aCont.IsG2()) return Standard_False; } - + if (nbNotDone == aNbSamples) return Standard_False; @@ -294,7 +844,36 @@ void BRepOffsetAPI_PatchFaces::AddPatchFace(const TopoDS_Face& theFace, void BRepOffsetAPI_PatchFaces::Build() { TopExp::MapShapesAndUniqueAncestors(myInitialShape, TopAbs_EDGE, TopAbs_FACE, myEFmap); + //TopTools_IndexedDataMapOfShapeListOfShape VEmap; + TopExp::MapShapesAndUniqueAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, myVEmap); + for (Standard_Integer i = 1; i <= myVEmap.Extent(); i++) + { + const TopoDS_Shape& aVertex = myVEmap.FindKey(i); + TopTools_ListOfShape aFaceList; + TopTools_MapOfShape aFaceMap; + const TopTools_ListOfShape& Elist = myVEmap(i); + TopTools_ListIteratorOfListOfShape itl(Elist); + for (; itl.More(); itl.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); + if (BRep_Tool::Degenerated(anEdge)) + continue; + const TopTools_ListOfShape& Flist = myEFmap.FindFromKey(anEdge); + TopTools_ListIteratorOfListOfShape itl2(Flist); + for (; itl2.More(); itl2.Next()) + { + const TopoDS_Shape& aFace = itl2.Value(); + if (aFaceMap.Add(aFace)) + aFaceList.Append(aFace); + } + } + myVFmap.Bind(aVertex, aFaceList); + } +#ifdef DRAW_PatchFaces + TopoDS_Compound aComp; + BRep_Builder().MakeCompound(aComp); +#endif //Draft filling of for (Standard_Integer i = 1; i <= myFacePatchFace.Extent(); i++) { @@ -305,6 +884,8 @@ void BRepOffsetAPI_PatchFaces::Build() for (; Explo.More(); Explo.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); + if (BRep_Tool::Degenerated(anEdge)) + continue; const TopTools_ListOfShape& Lfaces = myEFmap.FindFromKey(anEdge); TopoDS_Face aNeighborFace = (aFace.IsSame(Lfaces.First()))? TopoDS::Face(Lfaces.Last()) : TopoDS::Face(Lfaces.First()); @@ -316,6 +897,9 @@ void BRepOffsetAPI_PatchFaces::Build() if (IsTangentEdge) { myTangentEdges.Add(anEdge); +#ifdef DRAW_PatchFaces + BRep_Builder().Add(aComp, anEdge); +#endif continue; } @@ -325,8 +909,14 @@ void BRepOffsetAPI_PatchFaces::Build() Standard_True,Standard_True,Standard_True,Standard_True,Standard_True, Standard_False); //not too big myFaceNewFace.Add(aNeighborFace, aNewFace); +#ifdef DRAW_PatchFaces + BRep_Builder().Add(aComp, aNewFace); +#endif } } +#ifdef DRAW_PatchFaces + DBRep::Set("nf",aComp); +#endif //Make draft intersection edges: draft filling of BRep_Builder BB; @@ -353,6 +943,9 @@ void BRepOffsetAPI_PatchFaces::Build() for (; wexp.More(); wexp.Next()) { TopoDS_Edge anEdge = wexp.Current(); + if (BRep_Tool::Degenerated(anEdge)) + continue; + BRepAdaptor_Curve BAcurve(anEdge); Standard_Boolean ToReverse = Standard_False; TopoDS_Edge aNewEdge; if (myEdgeNewEdge.IsBound(anEdge)) @@ -366,8 +959,10 @@ void BRepOffsetAPI_PatchFaces::Build() if (Lfaces.Extent() == 1) //seam edge { cout< aSecTolMax) + Success = Standard_False; + } else //no intersection { cout< smooth edge"< smooth edge"< aSecTolMax) + { + Success = Standard_False; + break; + } + + Standard_Real aSqDistProj = ProjectPointOnEdge(MidPnt, aSecEdge, aParam, aPnt); + if (aSqDistProj < MinSqDistProj) + { + MinSqDistProj = aSqDistProj; + aNewEdge = aSecEdge; + } + } + } } if (!Success) //a smooth edge with bigger angle { @@ -442,7 +1067,7 @@ void BRepOffsetAPI_PatchFaces::Build() //Remove neighbor face from myFaceNewFace.Swap(myFaceNewFace.FindIndex(aNeighborFace), myFaceNewFace.Extent()); myFaceNewFace.RemoveLast(); - + myTangentEdges.Add(anEdge); UpdatedConstEdges.Add(anEdge); } @@ -451,6 +1076,7 @@ void BRepOffsetAPI_PatchFaces::Build() aNewEdge = MakeNewEdgeWithOldPcurvesOnNewSurfaces(anEdge, aFace, aBoundedNewFace, aNeighborFace, aBoundedNewNeighborFace); + mySmoothEdges.Add(anEdge); myEdgeNewEdge.Bind(anEdge.Oriented(TopAbs_FORWARD), aNewEdge); } continue; @@ -471,25 +1097,13 @@ void BRepOffsetAPI_PatchFaces::Build() BB.UpdateEdge(aNewEdge, PCurve2, aBoundedNewNeighborFace, 0.); //Check orientation of new edge - BRepAdaptor_Curve BAcurve(anEdge); + //BRepAdaptor_Curve BAcurve(anEdge); BRepAdaptor_Curve BAnewcurve(aNewEdge); - gp_Pnt FirstPnt, FirstNewPnt; + gp_Pnt FirstPnt, FirstNewPnt, aPnt; gp_Vec DirOnCurve, DirOnNewCurve; BAcurve.D1(BAcurve.FirstParameter(), FirstPnt, DirOnCurve); - Standard_Real ParamOnNewEdge = BAnewcurve.FirstParameter(); - Extrema_ExtPC Projector(FirstPnt, BAnewcurve); - if (!Projector.IsDone() || Projector.NbExt() == 0) - { - cout< 0) - { - Standard_Integer indmin = 1; - for (Standard_Integer ind = 2; ind <= Projector.NbExt(); ind++) - if (Projector.SquareDistance(ind) < Projector.SquareDistance(indmin)) - indmin = ind; - ParamOnNewEdge = Projector.Point(indmin).Parameter(); - } + Standard_Real ParamOnNewEdge; + ProjectPointOnEdge(FirstPnt, aNewEdge, ParamOnNewEdge, aPnt); BAnewcurve.D1(ParamOnNewEdge, FirstNewPnt, DirOnNewCurve); Standard_Real ScalProd = DirOnCurve * DirOnNewCurve; if (ScalProd < 0.) @@ -514,7 +1128,7 @@ void BRepOffsetAPI_PatchFaces::Build() for (Standard_Integer i = 1; i <= myFaceNewFace.Extent(); i++) { TopoDS_Face aFace = TopoDS::Face(myFaceNewFace.FindKey(i)); - TopoDS_Shape aNewFace = myFaceNewFace(i); + TopoDS_Face aNewFace = TopoDS::Face(myFaceNewFace(i)); TopoDS_Face aBoundedNewFace = TopoDS::Face(myNewFaceBoundedFace(aNewFace)); TopoDS_Iterator itf(aFace); @@ -530,10 +1144,13 @@ void BRepOffsetAPI_PatchFaces::Build() BRepTools_WireExplorer wexp(F_Wire, aFace); TopoDS_Vertex CurVertex = wexp.CurrentVertex(); TopoDS_Edge FirstEdge = wexp.Current(); + if (BRep_Tool::Degenerated(FirstEdge)) + { + wexp.Next(); + FirstEdge = wexp.Current(); + } TopoDS_Edge FirstNewEdge = FirstEdge; - if (myOrientedEdgeNewEdge.IsBound(FirstEdge)) - FirstNewEdge = TopoDS::Edge(myOrientedEdgeNewEdge(FirstEdge)); - else if (myEdgeNewEdge.IsBound(FirstEdge)) + if (myEdgeNewEdge.IsBound(FirstEdge)) FirstNewEdge = TopoDS::Edge(myEdgeNewEdge(FirstEdge)); TopoDS_Edge CurEdge, PrevEdge = FirstEdge; TopoDS_Edge CurNewEdge, PrevNewEdge = FirstNewEdge; @@ -547,9 +1164,9 @@ void BRepOffsetAPI_PatchFaces::Build() if (myEdgeNewEdge.IsBound(FirstEdge))//new edge: update { - Standard_Real fpar, lpar; - BRep_Tool::Range(FirstEdge, fpar, lpar); - BB.Range(FirstNewEdge, fpar, lpar); + //Standard_Real fpar, lpar; + //BRep_Tool::Range(FirstEdge, fpar, lpar); + //BB.Range(FirstNewEdge, fpar, lpar); BRepAdaptor_Curve BAcurve(FirstNewEdge); gp_Pnt FirstPnt = BAcurve.Value(BAcurve.FirstParameter()); if (CurNewVertex.IsNull()) @@ -562,17 +1179,19 @@ void BRepOffsetAPI_PatchFaces::Build() for (; wexp.More(); wexp.Next()) { CurEdge = wexp.Current(); - if (myOrientedEdgeNewEdge.IsBound(CurEdge)) - CurNewEdge = TopoDS::Edge(myOrientedEdgeNewEdge(CurEdge)); - else if (myEdgeNewEdge.IsBound(CurEdge)) + if (BRep_Tool::Degenerated(CurEdge)) + continue; + if (myEdgeNewEdge.IsBound(CurEdge)) CurNewEdge = TopoDS::Edge(myEdgeNewEdge(CurEdge)); else CurNewEdge = CurEdge; CurVertex = wexp.CurrentVertex(); UpdateEdgesAndVertex(PrevEdge, PrevNewEdge, CurEdge, CurNewEdge, - CurVertex); + CurVertex, + aFace, aNewFace, aBoundedNewFace); if (!PrevEdge.IsSame(PrevNewEdge) && + !BRepTools::IsReallyClosed(PrevEdge, aFace) && PrevEdge.Orientation() == TopAbs_REVERSED) PrevNewEdge.Reverse(); BB.Add(aNewWire, PrevNewEdge); @@ -585,8 +1204,10 @@ void BRepOffsetAPI_PatchFaces::Build() CurVertex = wexp.CurrentVertex(); UpdateEdgesAndVertex(PrevEdge, PrevNewEdge, CurEdge, CurNewEdge, - CurVertex); + CurVertex, + aFace, aNewFace, aBoundedNewFace); if (!PrevEdge.IsSame(PrevNewEdge) && + !BRepTools::IsReallyClosed(PrevEdge, aFace) && PrevEdge.Orientation() == TopAbs_REVERSED) PrevNewEdge.Reverse(); BB.Add(aNewWire, PrevNewEdge); @@ -619,11 +1240,11 @@ void BRepOffsetAPI_PatchFaces::Build() } BB.Add(aSolid, aShell); - ShapeFix_Shape Fixer(aSolid); - Fixer.Perform(); + //ShapeFix_Shape Fixer(aSolid); + //Fixer.Perform(); - myShape = Fixer.Shape(); - //myShape = aSolid; + //myShape = Fixer.Shape(); + myShape = aSolid; Done(); } @@ -632,119 +1253,190 @@ void BRepOffsetAPI_PatchFaces::UpdateEdgesAndVertex(const TopoDS_Edge& thePrevEd TopoDS_Edge& thePrevNewEdge, const TopoDS_Edge& theCurEdge, TopoDS_Edge& theCurNewEdge, - TopoDS_Vertex& theCurVertex) + const TopoDS_Vertex& theCurVertex, + const TopoDS_Face& theFace, + const TopoDS_Face& theNewFace, + const TopoDS_Face& theBoundedNewFace) { + if (thePrevEdge == theCurEdge) //only one edge in wire in fact + return; + + CorrectOrientationOfSeam(thePrevEdge, theFace, + thePrevNewEdge, theNewFace); + CorrectOrientationOfSeam(theCurEdge, theFace, + theCurNewEdge, theNewFace); + BRep_Builder BB; + BRepAdaptor_Surface BAsurf(theBoundedNewFace, Standard_False); + Standard_Boolean IsConstVertex = Standard_False; TopoDS_Vertex CurNewVertex; if (myVertexNewVertex.IsBound(theCurVertex)) CurNewVertex = TopoDS::Vertex(myVertexNewVertex(theCurVertex)); else { - Standard_Boolean IsConstVertex = (!(myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) || - !(myEdgeNewEdge.IsBound(theCurEdge) || myOrientedEdgeNewEdge.IsBound(theCurEdge))); + IsConstVertex = (!myEdgeNewEdge.IsBound(thePrevEdge) || + !myEdgeNewEdge.IsBound(theCurEdge) || + IsMoreThan3Edges(theCurVertex)); if (IsConstVertex) CurNewVertex = theCurVertex; } - Standard_Boolean IsSeamPrev = (myOrientedEdgeNewEdge.IsBound(thePrevEdge)); - Standard_Boolean IsSeamCur = (myOrientedEdgeNewEdge.IsBound(theCurEdge)); + TopAbs_Orientation OrientationOfCurVertexInPrev = theCurVertex.Orientation(); - if ((myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) && - (myEdgeNewEdge.IsBound(theCurEdge) || myOrientedEdgeNewEdge.IsBound(theCurEdge))) //two new edges: intersect + if (myEdgeNewEdge.IsBound(thePrevEdge) && + myEdgeNewEdge.IsBound(theCurEdge)) //two new edges: intersect { - Standard_Real ParamOnPrev, ParamOnCur, TolProj; - gp_Pnt PntOnPrev, PntOnCur; - ProjectVertexOnNewEdge(theCurVertex, thePrevEdge, thePrevNewEdge, - ParamOnPrev, PntOnPrev, TolProj); - ProjectVertexOnNewEdge(theCurVertex, theCurEdge, theCurNewEdge, - ParamOnCur, PntOnCur, TolProj); + Standard_Real ParamOnConst, ParamOnPrevRef, ParamOnCurRef, ParamOnPrev, ParamOnCur, TolProj; + gp_Pnt PntOnConst, PntOnPrevRef, PntOnCurRef, PntOnPrev, PntOnCur, PntSol; + gp_Pnt2d Pnt2dOnPrev, Pnt2dOnCur; + ProjectVertexOnNewEdge_2d(theCurVertex, + thePrevEdge, theFace, + thePrevNewEdge, theBoundedNewFace, + ParamOnConst, ParamOnPrevRef, + PntOnConst, PntOnPrevRef, PntSol, + Pnt2dOnPrev, TolProj); + ProjectVertexOnNewEdge_2d(theCurVertex, + theCurEdge, theFace, + theCurNewEdge, theBoundedNewFace, + ParamOnConst, ParamOnCurRef, + PntOnConst, PntOnCurRef, PntSol, + Pnt2dOnCur, TolProj); + gp_Pnt2d P2dRef((Pnt2dOnPrev.XY() + Pnt2dOnCur.XY())/2); + gp_Pnt P3dRef = BAsurf.Value(P2dRef.X(), P2dRef.Y()); + + //Standard_Real DistIn3d = PntOnPrev.Distance(PntOnCur); Standard_Real TolReached; gp_Pnt PntVtx = (CurNewVertex.IsNull())? BRep_Tool::Pnt(theCurVertex) : BRep_Tool::Pnt(CurNewVertex); - TolReached = PntOnPrev.Distance(PntOnCur); - Standard_Real DistVtoPrev = PntVtx.Distance(PntOnPrev); - Standard_Real DistVtoCur = PntVtx.Distance(PntOnCur); - TolReached = Max(TolReached, DistVtoPrev); - TolReached = Max(TolReached, DistVtoCur); - BRepExtrema_ExtCC ExtrEE(thePrevNewEdge, theCurNewEdge); - if (!ExtrEE.IsDone() || ExtrEE.NbExt() == 0) - { - cout< by distances to inner points of intersection + UpdateVertexTol(CurNewVertex, + thePrevNewEdge, thePrevEdge, OrientationOfCurVertexInPrev, + theCurNewEdge, theCurEdge, + theFace, + IntParamsOnFirst, IntParamsOnSecond); + + UpdateVertexTolOnAllFaces(CurNewVertex, theCurVertex); } //two new edges: intersect - else if ((myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) || - (myEdgeNewEdge.IsBound(theCurEdge) || myOrientedEdgeNewEdge.IsBound(theCurEdge))) //one constant edge: project point onto curve + else if (myEdgeNewEdge.IsBound(thePrevEdge) || + myEdgeNewEdge.IsBound(theCurEdge)) //one constant edge: project point onto curve { TopoDS_Edge ConstantEdge, ModifiedEdge, NewEdge; - Standard_Boolean IsAdjacentSeam; - if (myEdgeNewEdge.IsBound(thePrevEdge) || myOrientedEdgeNewEdge.IsBound(thePrevEdge)) + TopAbs_Orientation OrForNew; + if (myEdgeNewEdge.IsBound(thePrevEdge)) { ConstantEdge = theCurEdge; ModifiedEdge = thePrevEdge; NewEdge = thePrevNewEdge; - IsAdjacentSeam = IsSeamCur; + OrForNew = OrientationOfCurVertexInPrev; } else { ConstantEdge = thePrevEdge; ModifiedEdge = theCurEdge; NewEdge = theCurNewEdge; - IsAdjacentSeam = IsSeamPrev; + OrForNew = TopAbs::Reverse(OrientationOfCurVertexInPrev); } - Standard_Real ParamOnNewEdge, TolReached; - gp_Pnt PntOnNewEdge; - ProjectVertexOnNewEdge(theCurVertex, ModifiedEdge, NewEdge, - ParamOnNewEdge, PntOnNewEdge, TolReached); - BB.UpdateVertex(theCurVertex, TolReached); + Standard_Real ParamOnConstEdge, ParamOnNewEdge, TolReached; + gp_Pnt PntOnConstEdge, PntOnNewEdge, PntSol; + gp_Pnt2d Pnt2dOnNewEdge; + ProjectVertexOnNewEdge_2d(theCurVertex, + ModifiedEdge, theFace, + NewEdge, theBoundedNewFace, + ParamOnConstEdge, ParamOnNewEdge, + PntOnConstEdge, PntOnNewEdge, PntSol, + Pnt2dOnNewEdge, TolReached); + + TColStd_SequenceOfReal IntParamsOnFirst, IntParamsOnSecond; + IntersectIn2d(CurNewVertex, + ConstantEdge, NewEdge, theBoundedNewFace, Pnt2dOnNewEdge, + ParamOnConstEdge, ParamOnNewEdge, PntSol, PntOnConstEdge, PntOnNewEdge, + IntParamsOnFirst, IntParamsOnSecond); - if (!EdgeContains(NewEdge, theCurVertex)) - PutVertexToEdge(theCurVertex, theCurVertex, NewEdge, ModifiedEdge, ParamOnNewEdge); + gp_Pnt PntVtx = BRep_Tool::Pnt(CurNewVertex); + TolReached = PntVtx.Distance(PntOnNewEdge); + BB.UpdateVertex(CurNewVertex, 1.001*TolReached); + + PutVertexToEdge(CurNewVertex, OrForNew, + NewEdge, ModifiedEdge, + theFace, ParamOnNewEdge); + + //Update tolerance of by distances to inner points of intersection + UpdateVertexTol(CurNewVertex, + ConstantEdge, ConstantEdge, TopAbs::Reverse(OrForNew), //OrForConstant, + NewEdge, ModifiedEdge, + theFace, + IntParamsOnFirst, IntParamsOnSecond); + + UpdateVertexTolOnAllFaces(CurNewVertex, theCurVertex); } //else (one constant edge: project point onto curve) else //two constant edges { @@ -753,29 +1445,264 @@ void BRepOffsetAPI_PatchFaces::UpdateEdgesAndVertex(const TopoDS_Edge& thePrevEd } -void BRepOffsetAPI_PatchFaces::PutVertexToEdge(const TopoDS_Vertex& theVertex, - const TopoDS_Vertex& theProVertex, - TopoDS_Edge& theEdge, - const TopoDS_Edge& theProEdge, - const Standard_Real theParamOnEdge) +void BRepOffsetAPI_PatchFaces::PutVertexToEdge(const TopoDS_Vertex& theVertex, + const TopAbs_Orientation theProVertexOrientation, + const TopoDS_Edge& theEdge, + const TopoDS_Edge& theProEdge, + const TopoDS_Face& theProFace, + const Standard_Real theParamOnEdge) { BRep_Builder BB; - TopAbs_Orientation anOr = OrientationInEdge(theProVertex, theProEdge); - if (myEdgeNewEdge.IsBound(theProEdge) && - myEdgeNewEdge(theProEdge).Orientation() == TopAbs_REVERSED) + TopAbs_Orientation anOr = theProVertexOrientation; + if (theProEdge.Orientation() == TopAbs_REVERSED) anOr = TopAbs::Reverse(anOr); - TopoDS_Shape F_Edge = theEdge.Oriented(TopAbs_FORWARD); - F_Edge.Free(Standard_True); - BB.Add(F_Edge, theVertex.Oriented(anOr)); - if (!Precision::IsInfinite(theParamOnEdge)) + if (BRepTools::IsReallyClosed(theProEdge, theProFace)) { - Standard_Real fpar, lpar; - BRep_Tool::Range(theEdge, fpar, lpar); - if (anOr == TopAbs_FORWARD) - BB.Range(theEdge, theParamOnEdge, lpar); - else - BB.Range(theEdge, fpar, theParamOnEdge); + if (theEdge.Orientation() != theProEdge.Orientation()) + anOr = TopAbs::Reverse(anOr); + } + else + { + if (myEdgeNewEdge.IsBound(theProEdge) && + myEdgeNewEdge(theProEdge).Orientation() == TopAbs_REVERSED) + anOr = TopAbs::Reverse(anOr); + } + + Standard_Boolean EdgeContainsVertex = EdgeContains(theEdge, theVertex); + + if (!EdgeContainsVertex) + { + TopoDS_Shape F_Edge = theEdge.Oriented(TopAbs_FORWARD); + F_Edge.Free(Standard_True); + + Standard_Real aTolE = BRep_Tool::Tolerance(TopoDS::Edge(F_Edge)); + BB.UpdateVertex(theVertex, aTolE); + + BB.Add(F_Edge, theVertex.Oriented(anOr)); + } + + // trim edge by the parameter of vertex on edge + Standard_Real fpar, lpar; + BRep_Tool::Range(theEdge, fpar, lpar); + + Standard_Real NewFirst = fpar, NewLast = lpar; + if (anOr == TopAbs_FORWARD) + NewFirst = theParamOnEdge; + else + NewLast = theParamOnEdge; + + BB.Range(theEdge, NewFirst, NewLast); +} + +void BRepOffsetAPI_PatchFaces::ProjectVertexOnNewEdge_2d(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + const TopoDS_Edge& theNewEdge, + const TopoDS_Face& theNewFace, + Standard_Real& theParamOnConst, + Standard_Real& theParam, + gp_Pnt& thePntOnConst, + gp_Pnt& thePnt, + gp_Pnt& thePntSol, + gp_Pnt2d& thePnt2d, + Standard_Real& theTolReached) +{ + Standard_Real ParamOnEdge = BRep_Tool::Parameter(theVertex, theEdge); + theParamOnConst = ParamOnEdge; + BRepAdaptor_Curve2d BAcurve2d(theEdge, theFace); + BRepAdaptor_Curve2d BAnewcurve2d(theNewEdge, theNewFace); + gp_Pnt2d Point2dFromEdge; + // + BRepAdaptor_Curve BAcurve(theEdge); + gp_Pnt PointOnEdge = BAcurve.Value(ParamOnEdge); + thePntOnConst = PointOnEdge; + // + if (myFacePatchFace.Contains(theFace)) + { + BRepAdaptor_Surface BAnewsurf(theNewFace); + Extrema_ExtPS ProjPS(PointOnEdge, BAnewsurf, + Precision::PConfusion(), Precision::PConfusion()); + Standard_Integer imin = 1; + for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++) + if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(imin)) + imin = iext; + Standard_Real uu, vv; + ProjPS.Point(imin).Parameter(uu,vv); + Point2dFromEdge.SetCoord(uu,vv); + } + else + { + Point2dFromEdge = BAcurve2d.Value(ParamOnEdge); + } + Extrema_ExtPC2d Projector(Point2dFromEdge, BAnewcurve2d); + Standard_Real Param[4], dist[4]; + gp_Pnt2d Pnt2d[4]; + Param[1] = BAnewcurve2d.FirstParameter(); + Param[2] = BAnewcurve2d.LastParameter(); + Projector.TrimmedSquareDistances(dist[1], dist[2], Pnt2d[1], Pnt2d[2]); + dist[3] = RealLast(); + if (Projector.IsDone() && Projector.NbExt() > 0) + { + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= Projector.NbExt(); i++) + if (Projector.SquareDistance(i) < Projector.SquareDistance(imin)) + imin = i; + Param[3] = Projector.Point(imin).Parameter(); + dist[3] = Projector.SquareDistance(imin); + Pnt2d[3] = Projector.Point(imin).Value(); + } + + Standard_Integer imin = 1; + for (Standard_Integer i = 2; i <= 3; i++) + if (dist[i] < dist[imin]) + imin = i; + + theParam = Param[imin]; + //BRepAdaptor_Surface BAnewsurf(theNewFace, Standard_False); + //thePnt = BAnewsurf.Value(Pnt[imin].X(), Pnt[imin].Y()); + thePnt2d = Pnt2d[imin]; + //BRepAdaptor_Curve BAcurve(theEdge); + BRepAdaptor_Curve BAnewcurve(theNewEdge); + thePnt = BAnewcurve.Value(theParam); + //gp_Pnt PointOnEdge = BAcurve.Value(ParamOnEdge); + thePntSol.SetXYZ((thePntOnConst.XYZ() + thePnt.XYZ())/2); + //theTolReached = PointOnEdge.Distance(thePnt); //sqrt(dist[imin]); + theTolReached = thePntSol.Distance(thePnt); +} + +Standard_Boolean BRepOffsetAPI_PatchFaces::IsMoreThan3Edges(const TopoDS_Vertex& theVertex) +{ + const TopTools_ListOfShape& Flist = myVFmap(theVertex); + TopTools_ListIteratorOfListOfShape itl(Flist); + for (; itl.More(); itl.Next()) + { + const TopoDS_Shape& aFace = itl.Value(); + if (!myFaceNewFace.Contains(aFace)) + return Standard_True; + } + + return Standard_False; +} + +Standard_Boolean BRepOffsetAPI_PatchFaces::AreSmoothlyConnected(const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theEdge2, + const TopoDS_Vertex& theVertex, + const TopoDS_Face& theFace, + TopoDS_Edge& theThirdEdge) +{ + TopoDS_Shape Face1, Face2; + TopTools_ListIteratorOfListOfShape itl; + + const TopTools_ListOfShape& Flist1 = myEFmap.FindFromKey(theEdge1); + for (itl.Initialize(Flist1); itl.More(); itl.Next()) + { + const TopoDS_Shape& aFace = itl.Value(); + if (!aFace.IsSame(theFace)) + { + Face1 = aFace; + break; + } + } + + const TopTools_ListOfShape& Flist2 = myEFmap.FindFromKey(theEdge2); + for (itl.Initialize(Flist2); itl.More(); itl.Next()) + { + const TopoDS_Shape& aFace = itl.Value(); + if (!aFace.IsSame(theFace)) + { + Face2 = aFace; + break; + } + } + + const TopTools_ListOfShape& Elist = myVEmap.FindFromKey(theVertex); + for (itl.Initialize(Elist); itl.More(); itl.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); + if (anEdge.IsSame(theEdge1) || + anEdge.IsSame(theEdge2)) + continue; + const TopTools_ListOfShape& Flist = myEFmap.FindFromKey(anEdge); + if (Face1.IsSame(Flist.First()) && Face2.IsSame(Flist.Last()) || + Face1.IsSame(Flist.Last()) && Face2.IsSame(Flist.First())) + { + theThirdEdge = anEdge; + break; + } + } + + return (mySmoothEdges.Contains(theThirdEdge)); +} + +void BRepOffsetAPI_PatchFaces::UpdateVertexTolOnAllFaces(const TopoDS_Vertex& theVertex, + const TopoDS_Vertex& theProVertex) +{ + const TopTools_ListOfShape& Elist = myVEmap.FindFromKey(theProVertex); + TopTools_ListIteratorOfListOfShape ite(Elist); + + for (; ite.More(); ite.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(ite.Value()); + + TopoDS_Edge NewEdge = anEdge; + if (myEdgeNewEdge.IsBound(anEdge)) + NewEdge = TopoDS::Edge(myEdgeNewEdge(anEdge)); + + const TopTools_ListOfShape& Flist = myEFmap.FindFromKey(anEdge); + TopTools_ListIteratorOfListOfShape itf(Flist); + for (; itf.More(); itf.Next()) + { + const TopoDS_Face& aFace = TopoDS::Face(itf.Value()); + + TopoDS_Face aBoundedNewFace = aFace; + if (myFaceNewFace.Contains(aFace)) + { + TopoDS_Shape aNewFace = myFaceNewFace.FindFromKey(aFace); + aBoundedNewFace = TopoDS::Face(myNewFaceBoundedFace(aNewFace)); + } + + UpdateVertexTolOnFace(theVertex, NewEdge, aBoundedNewFace); + } + } +} + +void BRepOffsetAPI_PatchFaces::UpdateVertexTol(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theProEdge1, + const TopAbs_Orientation theOrOfVertexForEdge1, + const TopoDS_Edge& theEdge2, + const TopoDS_Edge& theProEdge2, + const TopoDS_Face& theFace, + TColStd_SequenceOfReal& theIntParamsOnFirst, + TColStd_SequenceOfReal& theIntParamsOnSecond) +{ + BRepAdaptor_Curve BAcurve1(theEdge1); + BRepAdaptor_Curve BAcurve2(theEdge2); + gp_Pnt PntVtx = BRep_Tool::Pnt(theVertex); + BRep_Builder BB; + + for (Standard_Integer i = 1; i <= theIntParamsOnFirst.Length(); i++) + { + Standard_Real aParamOnFirst = theIntParamsOnFirst(i); + Standard_Real aParamOnSecond = theIntParamsOnSecond(i); + if (aParamOnFirst <= BAcurve1.FirstParameter() || + aParamOnFirst >= BAcurve1.LastParameter() || + aParamOnSecond <= BAcurve2.FirstParameter() || + aParamOnSecond >= BAcurve2.LastParameter()) + continue; + + gp_Pnt aPnt = BAcurve1.Value(aParamOnFirst); + Standard_Real aDist = PntVtx.Distance(aPnt); + BB.UpdateVertex(theVertex, 1.001*aDist); + + PutVertexToEdge(theVertex, theOrOfVertexForEdge1, + theEdge1, theProEdge1, + theFace, aParamOnFirst); + + PutVertexToEdge(theVertex, TopAbs::Reverse(theOrOfVertexForEdge1), + theEdge2, theProEdge2, + theFace, aParamOnSecond); } } diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx index 31d205bebb..bcc23c87cb 100644 --- a/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_PatchFaces.hxx @@ -27,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include class TopoDS_Shape; @@ -67,26 +69,65 @@ private: TopoDS_Edge& thePrevNewEdge, const TopoDS_Edge& theCurEdge, TopoDS_Edge& theCurNewEdge, - TopoDS_Vertex& theCurVertex); + const TopoDS_Vertex& theCurVertex, + const TopoDS_Face& theFace, + const TopoDS_Face& theNewFace, + const TopoDS_Face& theBoundedNewFace); - Standard_EXPORT void PutVertexToEdge(const TopoDS_Vertex& theVertex, - const TopoDS_Vertex& theProVertex, - TopoDS_Edge& theEdge, - const TopoDS_Edge& theProEdge, - const Standard_Real theParamOnEdge); + Standard_EXPORT void PutVertexToEdge(const TopoDS_Vertex& theVertex, + const TopAbs_Orientation theProVertexOrientation, + const TopoDS_Edge& theEdge, + const TopoDS_Edge& theProEdge, + const TopoDS_Face& theFace, + const Standard_Real theParamOnEdge); + + Standard_EXPORT void ProjectVertexOnNewEdge_2d(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + const TopoDS_Edge& theNewEdge, + const TopoDS_Face& theNewFace, + Standard_Real& theParamOnConst, + Standard_Real& theParam, + gp_Pnt& thePntOnConst, + gp_Pnt& thePnt, + gp_Pnt& thePntSol, + gp_Pnt2d& thePnt2d, + Standard_Real& theTolReached); + + Standard_EXPORT Standard_Boolean IsMoreThan3Edges(const TopoDS_Vertex& theVertex); + + Standard_EXPORT Standard_Boolean AreSmoothlyConnected(const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theEdge2, + const TopoDS_Vertex& theVertex, + const TopoDS_Face& theFace, + TopoDS_Edge& theThirdEdge); + + Standard_EXPORT void UpdateVertexTol(const TopoDS_Vertex& theVertex, + const TopoDS_Edge& theEdge1, + const TopoDS_Edge& theProEdge1, + const TopAbs_Orientation theOrOfVertexForEdge1, + const TopoDS_Edge& theEdge2, + const TopoDS_Edge& theProEdge2, + const TopoDS_Face& theFace, + TColStd_SequenceOfReal& theIntParamsOnFirst, + TColStd_SequenceOfReal& theIntParamsOnSecond); + + Standard_EXPORT void UpdateVertexTolOnAllFaces(const TopoDS_Vertex& theVertex, + const TopoDS_Vertex& theProVertex); - TopoDS_Shape myInitialShape; TopTools_IndexedDataMapOfShapeShape myFacePatchFace; TopTools_IndexedDataMapOfShapeShape myFaceNewFace; TopTools_DataMapOfShapeShape myNewFaceBoundedFace; TopTools_DataMapOfShapeShape myEdgeNewEdge; - TopTools_DataMapOfOrientedShapeShape myOrientedEdgeNewEdge; TopTools_DataMapOfShapeShape myVertexNewVertex; TopTools_MapOfShape myTangentEdges; + TopTools_MapOfShape mySmoothEdges; TopTools_IndexedDataMapOfShapeListOfShape myEFmap; + TopTools_IndexedDataMapOfShapeListOfShape myVEmap; + TopTools_DataMapOfShapeListOfShape myVFmap; };