// Created on: 1997-01-24 // Created by: Laurent BOURESCHE // Copyright (c) 1997-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. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OCCT_DEBUG #include #include #include #include #include #include #include #ifdef DRAW #include #endif static Standard_Integer IndexOfSection = 0; extern Standard_Boolean Blend_GettraceDRAWSECT(); #ifdef OCCT_DEBUG_BBPP_N_TRDERIV // for debug : visualisation of the section static Standard_Boolean BBPP(const Standard_Real param, Blend_SurfRstFunction& Func, const math_Vector& sol, const Standard_Real tol, Blend_Point& BP) { if (!Func.IsSolution(sol, tol)) return 0; gp_Pnt pnts = Func.PointOnS(); gp_Pnt pntrst = Func.PointOnRst(); gp_Pnt2d p2ds = Func.Pnt2dOnS(); gp_Pnt2d p2drst = Func.Pnt2dOnRst(); Standard_Real w = Func.ParameterOnRst(); BP = Blend_Point(pnts, pntrst, param, p2ds.X(), p2ds.Y(), p2drst.X(), p2drst.Y(), w); return 1; } static void tracederiv(Blend_SurfRstFunction& Func, const Blend_Point& BP1, const Blend_Point& BP2) { Standard_Integer hp, hk, hd, hp2d, i; Func.GetShape(hp, hk, hd, hp2d); TColgp_Array1OfPnt TP1(1, hp); TColgp_Array1OfVec TDP1(1, hp); TColgp_Array1OfPnt2d TP2d1(1, hp2d); TColgp_Array1OfVec2d TDP2d1(1, hp2d); TColStd_Array1OfReal TW1(1, hp); TColStd_Array1OfReal TDW1(1, hp); Func.Section(BP1, TP1, TDP1, TP2d1, TDP2d1, TW1, TDW1); TColgp_Array1OfPnt TP2(1, hp); TColgp_Array1OfVec TDP2(1, hp); TColgp_Array1OfPnt2d TP2d2(1, hp2d); TColgp_Array1OfVec2d TDP2d2(1, hp2d); TColStd_Array1OfReal TW2(1, hp); TColStd_Array1OfReal TDW2(1, hp); Func.Section(BP2, TP2, TDP2, TP2d2, TDP2d2, TW2, TDW2); Standard_Real param1 = BP1.Parameter(); Standard_Real param2 = BP2.Parameter(); Standard_Real scal = 1. / (param1 - param2); std::cout << std::endl; std::cout << "control derivatives at point : " << param1 << std::endl; for (i = 1; i <= hp; i++) { std::cout << std::endl; std::cout << "point : " << i << std::endl; std::cout << "dx calculated : " << TDP1(i).X() << std::endl; std::cout << "dx estimated : " << scal * (TP1(i).X() - TP2(i).X()) << std::endl; std::cout << "dy calculated : " << TDP1(i).Y() << std::endl; std::cout << "dy estimated : " << scal * (TP1(i).Y() - TP2(i).Y()) << std::endl; std::cout << "dz calculated : " << TDP1(i).Z() << std::endl; std::cout << "dz estimated : " << scal * (TP1(i).Z() - TP2(i).Z()) << std::endl; std::cout << "dw calculated : " << TDW1(i) << std::endl; std::cout << "dw estimated : " << scal * (TW1(i) - TW2(i)) << std::endl; } for (i = 1; i <= hp2d; i++) { std::cout << std::endl; std::cout << "point 2d : " << i << std::endl; std::cout << "dx calculated : " << TDP2d1(i).X() << std::endl; std::cout << "dx estimated : " << scal * (TP2d1(i).X() - TP2d2(i).X()) << std::endl; std::cout << "dy calculated : " << TDP2d1(i).Y() << std::endl; std::cout << "dy estimated : " << scal * (TP2d1(i).Y() - TP2d2(i).Y()) << std::endl; } } #endif static void Drawsect(const Standard_Real param, Blend_SurfRstFunction& Func) { gp_Pnt pnts = Func.PointOnS(); gp_Pnt pntrst = Func.PointOnRst(); gp_Pnt2d p2ds = Func.Pnt2dOnS(); gp_Pnt2d p2drst = Func.Pnt2dOnRst(); Standard_Real w = Func.ParameterOnRst(); Blend_Point BP(pnts, pntrst, param, p2ds.X(), p2ds.Y(), p2drst.X(), p2drst.Y(), w); Standard_Integer hp, hk, hd, hp2d; Func.GetShape(hp, hk, hd, hp2d); TColStd_Array1OfReal TK(1, hk); Func.Knots(TK); TColStd_Array1OfInteger TMul(1, hk); Func.Mults(TMul); TColgp_Array1OfPnt TP(1, hp); TColgp_Array1OfPnt2d TP2d(1, hp2d); TColStd_Array1OfReal TW(1, hp); Func.Section(BP, TP, TP2d, TW); Handle(Geom_BSplineCurve) sect = new Geom_BSplineCurve(TP, TW, TK, TMul, hd); IndexOfSection++; #ifdef DRAW char tname[100]; Standard_CString name = tname; sprintf(name, "%s_%d", "Section", IndexOfSection); DrawTrSurf::Set(name, sect); #endif } #endif //======================================================================= // function : ArcToRecadre // purpose : Find a suitable arc // PrevIndex is used to reject an already tested arc //======================================================================= Standard_Integer BRepBlend_SurfRstLineBuilder::ArcToRecadre(const math_Vector& theSol, const Standard_Integer PrevIndex, gp_Pnt2d& lastpt2d, gp_Pnt2d& pt2d, Standard_Real& ponarc) { Standard_Integer IndexSol = 0, nbarc = 0; Standard_Boolean ok = Standard_False; Standard_Boolean byinter = (line->NbPoints() != 0), okinter = 0; Standard_Real distmin = RealLast(); Standard_Real uprev = 0., vprev = 0., prm = 0., dist = 0.; if (byinter) previousP.ParametersOnS(uprev, vprev); pt2d.SetCoord(theSol(1), theSol(2)); lastpt2d.SetCoord(uprev, vprev); domain1->Init(); while (domain1->More()) { nbarc++; ok = 0; if (byinter) { ok = okinter = BRepBlend_BlendTool::Inters(pt2d, lastpt2d, surf1, domain1->Value(), prm, dist); } if (!ok) ok = BRepBlend_BlendTool::Project(pt2d, surf1, domain1->Value(), prm, dist); if (ok && (nbarc != PrevIndex)) { if (dist < distmin || okinter) { distmin = dist; ponarc = prm; IndexSol = nbarc; if (okinter && (PrevIndex == 0)) break; } } domain1->Next(); } return IndexSol; } //================================================================================================= BRepBlend_SurfRstLineBuilder::BRepBlend_SurfRstLineBuilder( const Handle(Adaptor3d_Surface)& Surf1, const Handle(Adaptor3d_TopolTool)& Domain1, const Handle(Adaptor3d_Surface)& Surf2, const Handle(Adaptor2d_Curve2d)& Rst, const Handle(Adaptor3d_TopolTool)& Domain2) : done(Standard_False), sol(1, 3), surf1(Surf1), domain1(Domain1), surf2(Surf2), rst(Rst), domain2(Domain2), tolpoint3d(0.0), tolpoint2d(0.0), tolgui(0.0), pasmax(0.0), fleche(0.0), param(0.0), rebrou(Standard_False), iscomplete(Standard_False), comptra(Standard_False), sens(0.0), decrochdeb(Standard_False), decrochfin(Standard_False) { } //================================================================================================= void BRepBlend_SurfRstLineBuilder::Perform(Blend_SurfRstFunction& Func, Blend_FuncInv& Finv, Blend_SurfPointFuncInv& FinvP, Blend_SurfCurvFuncInv& FinvC, const Standard_Real Pdep, const Standard_Real Pmax, const Standard_Real MaxStep, const Standard_Real Tol3d, const Standard_Real Tol2d, const Standard_Real TolGuide, const math_Vector& ParDep, const Standard_Real Fleche, const Standard_Boolean Appro) { done = Standard_False; iscomplete = Standard_False; comptra = Standard_False; line = new BRepBlend_Line(); tolpoint3d = Tol3d; tolpoint2d = Tol2d; tolgui = Abs(TolGuide); fleche = Abs(Fleche); rebrou = Standard_False; pasmax = Abs(MaxStep); if (Pmax - Pdep >= 0.) { sens = 1.; } else { sens = -1.; } Blend_Status State; param = Pdep; Func.Set(param); if (Appro) { TopAbs_State siturst, situs; Standard_Boolean decroch; math_Vector tolerance(1, 3), infbound(1, 3), supbound(1, 3); Func.GetTolerance(tolerance, tolpoint3d); Func.GetBounds(infbound, supbound); math_FunctionSetRoot rsnld(Func, tolerance, 30); rsnld.Perform(Func, ParDep, infbound, supbound); if (!rsnld.IsDone()) { return; } rsnld.Root(sol); if (!CheckInside(Func, siturst, situs, decroch)) { return; } } else { sol = ParDep; } State = TestArret(Func, Standard_False, Blend_OK); if (State != Blend_OK) { return; } #ifdef OCCT_DEBUG if (Blend_GettraceDRAWSECT()) { Drawsect(param, Func); } #endif // Update the line. line->Append(previousP); Standard_Real U, V; previousP.ParametersOnS(U, V); // W = previousP.ParameterOnC(); BRepBlend_Extremity ptf1(previousP.PointOnS(), U, V, previousP.Parameter(), tolpoint3d); BRepBlend_Extremity ptf2(previousP.PointOnC(), U, V, previousP.Parameter(), tolpoint3d); if (!previousP.IsTangencyPoint()) { ptf1.SetTangent(previousP.TangentOnS()); ptf2.SetTangent(previousP.TangentOnC()); } if (sens > 0.) { line->SetStartPoints(ptf1, ptf2); } else { line->SetEndPoints(ptf1, ptf2); } InternalPerform(Func, Finv, FinvP, FinvC, Pmax); done = Standard_True; } //================================================================================================= Standard_Boolean BRepBlend_SurfRstLineBuilder::PerformFirstSection(Blend_SurfRstFunction& Func, Blend_FuncInv& Finv, Blend_SurfPointFuncInv& FinvP, Blend_SurfCurvFuncInv& FinvC, const Standard_Real Pdep, const Standard_Real Pmax, const math_Vector& ParDep, const Standard_Real Tol3d, const Standard_Real Tol2d, const Standard_Real TolGuide, const Standard_Boolean RecRst, const Standard_Boolean RecP, const Standard_Boolean RecS, Standard_Real& Psol, math_Vector& ParSol) { done = Standard_False; iscomplete = Standard_False; comptra = Standard_False; line = new BRepBlend_Line(); tolpoint3d = Tol3d; tolpoint2d = Tol2d; tolgui = Abs(TolGuide); rebrou = Standard_False; if (Pmax - Pdep >= 0.) { sens = 1.; } else { sens = -1.; } Blend_Status State = Blend_OnRst12; Standard_Real trst = 0.; Standard_Boolean recadp, recadrst, recads; Standard_Real wp, wrst, ws; Standard_Real U = 0., V = 0.; math_Vector infbound(1, 3), supbound(1, 3), tolerance(1, 3); math_Vector solinvp(1, 3), solinvrst(1, 4), solinvs(1, 3); Handle(Adaptor3d_HVertex) Vtxp, Vtxrst, Vtxs, Vtxc; Standard_Boolean IsVtxp = 0, IsVtxrst = 0, IsVtxs = 0; Handle(Adaptor2d_Curve2d) Arc; wp = wrst = ws = Pmax; param = Pdep; Func.Set(param); Func.GetTolerance(tolerance, tolpoint3d); Func.GetBounds(infbound, supbound); math_FunctionSetRoot rsnld(Func, tolerance, 30); rsnld.Perform(Func, ParDep, infbound, supbound); if (!rsnld.IsDone()) return Standard_False; rsnld.Root(sol); recads = RecS && Recadre(FinvC, solinvs, Arc, IsVtxs, Vtxs); if (recads) { ws = solinvs(1); } recadp = RecP && Recadre(FinvP, solinvp, IsVtxp, Vtxp); if (recadp) { wp = solinvp(1); } recadrst = RecRst && Recadre(Func, Finv, solinvrst, IsVtxrst, Vtxrst); if (recadrst) { wrst = solinvrst(2); } if (!recads && !recadp && !recadrst) return Standard_False; if (recadp && recadrst) { if (sens * (wrst - wp) > tolgui) { // first one leaves the domain wrst = wp; U = solinvp(2); V = solinvp(3); trst = BRepBlend_BlendTool::Parameter(Vtxp, rst); IsVtxrst = IsVtxp; Vtxrst = Vtxp; } else { U = solinvrst(3); V = solinvrst(4); trst = solinvrst(1); } } else if (recadp) { wrst = wp; U = solinvp(2); V = solinvp(3); trst = BRepBlend_BlendTool::Parameter(Vtxp, rst); IsVtxrst = IsVtxp; Vtxrst = Vtxp; recadrst = Standard_True; } else if (recadrst) { U = solinvrst(3); V = solinvrst(4); trst = solinvrst(1); } if (recads && recadrst) { if (Abs(ws - wrst) < tolgui) { State = Blend_OnRst12; param = 0.5 * (ws + wrst); sol(1) = U; sol(2) = V; sol(3) = solinvs(2); } else if (sens * (ws - wrst) < 0) { // ground on surf State = Blend_OnRst1; param = ws; Arc->Value(solinvs(3)).Coord(U, V); sol(1) = U; sol(2) = V; sol(3) = solinvs(2); } else { // ground on rst State = Blend_OnRst2; param = wrst; sol(1) = U; sol(2) = V; sol(3) = trst; } Func.Set(param); } else if (recads) { // ground on surf State = Blend_OnRst1; param = ws; Arc->Value(solinvs(3)).Coord(U, V); sol(1) = U; sol(2) = V; sol(3) = solinvs(2); Func.Set(param); } else if (recadrst) { // ground on rst State = Blend_OnRst2; param = wrst; sol(1) = U; sol(2) = V; sol(3) = trst; Func.Set(param); } State = TestArret(Func, Standard_False, State); Psol = param; ParSol = sol; return Standard_True; } //================================================================================================= Standard_Boolean BRepBlend_SurfRstLineBuilder::Complete(Blend_SurfRstFunction& Func, Blend_FuncInv& Finv, Blend_SurfPointFuncInv& FinvP, Blend_SurfCurvFuncInv& FinvC, const Standard_Real Pmin) { if (!done) { throw StdFail_NotDone(); } if (iscomplete) { return Standard_True; } if (sens > 0.) { previousP = line->Point(1); } else { previousP = line->Point(line->NbPoints()); } sens = -sens; param = previousP.Parameter(); previousP.ParametersOnS(sol(1), sol(2)); sol(3) = previousP.ParameterOnC(); InternalPerform(Func, Finv, FinvP, FinvC, Pmin); iscomplete = Standard_True; return Standard_True; } //================================================================================================= void BRepBlend_SurfRstLineBuilder::InternalPerform(Blend_SurfRstFunction& Func, Blend_FuncInv& Finv, Blend_SurfPointFuncInv& FinvP, Blend_SurfCurvFuncInv& FinvC, const Standard_Real Bound) { Standard_Real stepw = pasmax; Standard_Integer nbp = line->NbPoints(); if (nbp >= 2) { // The last step is reproduced if it is not too small. if (sens < 0.) { stepw = (line->Point(2).Parameter() - line->Point(1).Parameter()); } else { stepw = (line->Point(nbp).Parameter() - line->Point(nbp - 1).Parameter()); } stepw = Max(stepw, 100. * tolgui); } Standard_Real parprec = param; if (sens * (parprec - Bound) >= -tolgui) { return; } Blend_Status State = Blend_OnRst12; TopAbs_State situonc = TopAbs_UNKNOWN, situons = TopAbs_UNKNOWN; Standard_Boolean decroch = Standard_False; Standard_Boolean Arrive, recadp, recadrst, recads, echecrecad; Standard_Real wp, wrst, ws; Standard_Real U = 0., V = 0.; Standard_Real trst = 0.; math_Vector infbound(1, 3), supbound(1, 3); math_Vector parinit(1, 3), tolerance(1, 3); math_Vector solinvp(1, 3), solinvrst(1, 4), solinvs(1, 3); Handle(Adaptor3d_HVertex) Vtxp, Vtxrst, Vtxs, Vtxc; Standard_Boolean IsVtxp = 0, IsVtxrst = 0, IsVtxs = 0; BRepBlend_Extremity Extrst, Exts; Handle(Adaptor2d_Curve2d) Arc; // IntSurf_Transition Tline,Tarc; Func.GetTolerance(tolerance, tolpoint3d); Func.GetBounds(infbound, supbound); math_FunctionSetRoot rsnld(Func, tolerance, 30); parinit = sol; Arrive = Standard_False; param = parprec + sens * stepw; if (sens * (param - Bound) > 0.) { stepw = sens * (Bound - parprec) * 0.5; param = parprec + sens * stepw; } while (!Arrive) { Standard_Boolean bonpoint = 1; #ifdef OCCT_DEBUG_BBPP_N_TRDERIV // debdebdebdebdebdeb Func.Set(param); rsnld.Perform(Func, parinit, infbound, supbound); if (rsnld.IsDone()) { rsnld.Root(sol); Blend_Point bp1; if (BBPP(param, Func, sol, tolpoint3d, bp1)) { Standard_Real dw = 1.e-10; Func.Set(param + dw); rsnld.Perform(Func, parinit, infbound, supbound); if (rsnld.IsDone()) { rsnld.Root(sol); Blend_Point bp2; if (BBPP(param + dw, Func, sol, tolpoint3d, bp2)) { tracederiv(Func, bp1, bp2); } } } } // debdebdebdebdebdeb #endif Func.Set(param); rsnld.Perform(Func, parinit, infbound, supbound); if (rsnld.IsDone()) { rsnld.Root(sol); if (!CheckInside(Func, situonc, situons, decroch) && line->NbPoints() == 1) { State = Blend_StepTooLarge; bonpoint = 0; } } else { State = Blend_StepTooLarge; bonpoint = 0; } if (bonpoint) { wp = wrst = ws = Bound; recadp = recadrst = recads = Standard_False; echecrecad = Standard_False; if (situons == TopAbs_OUT || situons == TopAbs_ON) { // pb inverse rst/rst recads = Recadre(FinvC, solinvs, Arc, IsVtxs, Vtxs); if (recads) { ws = solinvs(1); // It is necessary to reevaluate the deviation (BUC60360) gp_Vec t, n; Func.Set(ws); Arc->Value(solinvs(3)).Coord(U, V); sol(1) = U; sol(2) = V; sol(3) = solinvs(2); decroch = Func.Decroch(sol, t, n); } else { echecrecad = Standard_True; } } if (situonc == TopAbs_OUT || situonc == TopAbs_ON) { // pb inverse point/surf recadp = Recadre(FinvP, solinvp, IsVtxp, Vtxp); if (recadp) { wp = solinvp(1); } else { echecrecad = Standard_True; } } if (decroch) { // pb inverse rst/surf recadrst = Recadre(Func, Finv, solinvrst, IsVtxrst, Vtxrst); if (recadrst) { wrst = solinvrst(2); } else { echecrecad = Standard_True; } } decroch = 0; if (recadp || recads || recadrst) echecrecad = Standard_False; if (!echecrecad) { if (recadp && recadrst) { if (sens * (wrst - wp) > tolgui) { // first one leaves the domain wrst = wp; U = solinvp(2); V = solinvp(3); trst = BRepBlend_BlendTool::Parameter(Vtxp, rst); IsVtxrst = IsVtxp; Vtxrst = Vtxp; } else { decroch = 1; U = solinvrst(3); V = solinvrst(4); trst = solinvrst(1); } } else if (recadp) { wrst = wp; U = solinvp(2); V = solinvp(3); trst = BRepBlend_BlendTool::Parameter(Vtxp, rst); IsVtxrst = IsVtxp; Vtxrst = Vtxp; recadrst = Standard_True; } else if (recadrst) { decroch = 1; U = solinvrst(3); V = solinvrst(4); trst = solinvrst(1); } if (recads && recadrst) { if (Abs(ws - wrst) < tolgui) { State = Blend_OnRst12; param = 0.5 * (ws + wrst); sol(1) = U; sol(2) = V; sol(3) = solinvs(3); } else if (sens * (ws - wrst) < 0) { // ground on surf decroch = 0; State = Blend_OnRst1; param = ws; Arc->Value(solinvs(3)).Coord(U, V); sol(1) = U; sol(2) = V; sol(3) = solinvs(2); } else { // ground on rst State = Blend_OnRst2; param = wrst; sol(1) = U; sol(2) = V; sol(3) = trst; } Func.Set(param); } else if (recads) { // ground on surf State = Blend_OnRst1; param = ws; Arc->Value(solinvs(3)).Coord(U, V); sol(1) = U; sol(2) = V; sol(3) = solinvs(2); Func.Set(param); } else if (recadrst) { // ground on rst State = Blend_OnRst2; param = wrst; sol(1) = U; sol(2) = V; sol(3) = trst; Func.Set(param); } else { State = Blend_OK; } State = TestArret(Func, Standard_True, State); } else { // Failed reframing. Leave with PointsConfondus #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder : failed reframing" << std::endl; #endif State = Blend_SamePoints; } } switch (State) { case Blend_OK: { #ifdef OCCT_DEBUG if (Blend_GettraceDRAWSECT()) { Drawsect(param, Func); } #endif // Update the line. if (sens > 0.) { line->Append(previousP); } else { line->Prepend(previousP); } parinit = sol; parprec = param; if (param == Bound) { Arrive = Standard_True; Exts.SetValue(previousP.PointOnS(), sol(1), sol(2), previousP.Parameter(), tolpoint3d); MakeExtremity(Extrst, Standard_False, rst, sol(3), IsVtxrst, Vtxrst); // Indicate end on Bound. } else { param = param + sens * stepw; if (sens * (param - Bound) > -tolgui) { param = Bound; } } } break; case Blend_StepTooLarge: { stepw = stepw / 2.; if (Abs(stepw) < tolgui) { previousP.ParametersOnS(U, V); Exts.SetValue(previousP.PointOnS(), U, V, previousP.Parameter(), tolpoint3d); Extrst.SetValue(previousP.PointOnC(), previousP.ParameterOnC(), previousP.Parameter(), tolpoint3d); Arrive = Standard_True; if (line->NbPoints() >= 2) { // Indicate that one stops during the processing #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder : No advancement in the processing" << std::endl; #endif } } else { param = parprec + sens * stepw; // no risk to exceed Bound. } } break; case Blend_StepTooSmall: { #ifdef OCCT_DEBUG if (Blend_GettraceDRAWSECT()) { Drawsect(param, Func); } #endif // Update the line. if (sens > 0.) { line->Append(previousP); } else { line->Prepend(previousP); } parinit = sol; parprec = param; stepw = Min(1.5 * stepw, pasmax); if (param == Bound) { Arrive = Standard_True; Exts.SetValue(previousP.PointOnS(), sol(1), sol(2), previousP.Parameter(), tolpoint3d); MakeExtremity(Extrst, Standard_False, rst, sol(3), IsVtxrst, Vtxrst); // Indicate end on Bound. } else { param = param + sens * stepw; if (sens * (param - Bound) > -tolgui) { param = Bound; } } } break; case Blend_OnRst1: { #ifdef OCCT_DEBUG if (Blend_GettraceDRAWSECT()) { Drawsect(param, Func); } #endif if (sens > 0.) { line->Append(previousP); } else { line->Prepend(previousP); } MakeExtremity(Exts, Standard_True, Arc, solinvs(3), IsVtxs, Vtxs); MakeExtremity(Extrst, Standard_False, rst, sol(3), IsVtxrst, Vtxrst); Arrive = Standard_True; } break; case Blend_OnRst2: { #ifdef OCCT_DEBUG if (Blend_GettraceDRAWSECT()) { Drawsect(param, Func); } #endif if (sens > 0.) { line->Append(previousP); } else { line->Prepend(previousP); } Exts.SetValue(previousP.PointOnS(), sol(1), sol(2), previousP.Parameter(), tolpoint3d); MakeExtremity(Extrst, Standard_False, rst, sol(3), IsVtxrst, Vtxrst); Arrive = Standard_True; } break; case Blend_OnRst12: { #ifdef OCCT_DEBUG if (Blend_GettraceDRAWSECT()) { Drawsect(param, Func); } #endif if (sens > 0.) { line->Append(previousP); } else { line->Prepend(previousP); } MakeExtremity(Exts, Standard_True, Arc, solinvs(1), IsVtxs, Vtxs); MakeExtremity(Extrst, Standard_False, rst, sol(3), IsVtxrst, Vtxrst); Arrive = Standard_True; } break; case Blend_SamePoints: { // Stop #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder Points mixed in the processing" << std::endl; #endif previousP.ParametersOnS(U, V); Exts.SetValue(previousP.PointOnS(), U, V, previousP.Parameter(), tolpoint3d); Extrst.SetValue(previousP.PointOnC(), previousP.ParameterOnC(), previousP.Parameter(), tolpoint3d); Arrive = Standard_True; } break; default: break; } if (Arrive) { if (sens > 0.) { line->SetEndPoints(Exts, Extrst); decrochfin = decroch; } else { line->SetStartPoints(Exts, Extrst); decrochdeb = decroch; } } } } //======================================================================= // function : Recadre // purpose : Reframe section Surface / Restriction //======================================================================= Standard_Boolean BRepBlend_SurfRstLineBuilder::Recadre(Blend_SurfCurvFuncInv& FinvC, math_Vector& Solinv, Handle(Adaptor2d_Curve2d)& Arc, Standard_Boolean& IsVtx, Handle(Adaptor3d_HVertex)& Vtx) { Standard_Boolean recadre = Standard_False; gp_Pnt2d pt2d, lastpt2d; Standard_Integer IndexSol, nbarc; Standard_Real pmin; IndexSol = ArcToRecadre(sol, 0, lastpt2d, pt2d, pmin); IsVtx = Standard_False; if (IndexSol == 0) { return Standard_False; } domain1->Init(); nbarc = 1; while (nbarc < IndexSol) { nbarc++; domain1->Next(); } Arc = domain1->Value(); FinvC.Set(Arc); math_Vector toler(1, 3), infb(1, 3), supb(1, 3); // use reduced Tol argument value to pass testcase // blend complex A6 with scale factor of model 0.1 (base scale = 1000) // So, here we using 1.0e-5 rather than 1.0e-4 of tolerance of point in 3d FinvC.GetTolerance(toler, 0.1 * tolpoint3d); FinvC.GetBounds(infb, supb); Solinv(1) = param; Solinv(2) = sol(3); Solinv(3) = pmin; math_FunctionSetRoot rsnld(FinvC, toler, 30); rsnld.Perform(FinvC, Solinv, infb, supb); if (!rsnld.IsDone()) { #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder : RSNLD not done " << std::endl << std::endl; #endif } else { // It is necessary to check the value of the function rsnld.Root(Solinv); recadre = FinvC.IsSolution(Solinv, tolpoint3d); } // In case of fail, it is checked if another arc // can be useful (case of output at the proximity of a vertex) if (!recadre) { IndexSol = ArcToRecadre(sol, IndexSol, lastpt2d, pt2d, pmin); if (IndexSol == 0) { return Standard_False; // No other solution } domain1->Init(); nbarc = 1; while (nbarc < IndexSol) { nbarc++; domain1->Next(); } Arc = domain1->Value(); FinvC.Set(Arc); FinvC.GetTolerance(toler, tolpoint3d); FinvC.GetBounds(infb, supb); Solinv(3) = pmin; math_FunctionSetRoot aRsnld(FinvC, toler, 30); aRsnld.Perform(FinvC, Solinv, infb, supb); if (!aRsnld.IsDone()) { #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder : RSNLD not done " << std::endl << std::endl; #endif } else { // It is necessary to check the value of the function aRsnld.Root(Solinv); recadre = FinvC.IsSolution(Solinv, tolpoint3d); } } if (recadre) { Standard_Real w = Solinv(2); if (w < rst->FirstParameter() - toler(2) || w > rst->LastParameter() + toler(2)) { return Standard_False; } domain1->Initialize(Arc); domain1->InitVertexIterator(); IsVtx = !domain1->MoreVertex(); while (!IsVtx) { Vtx = domain1->Vertex(); if (Abs(BRepBlend_BlendTool::Parameter(Vtx, Arc) - Solinv(3)) <= BRepBlend_BlendTool::Tolerance(Vtx, Arc)) { IsVtx = Standard_True; } else { domain1->NextVertex(); IsVtx = !domain1->MoreVertex(); } } if (!domain1->MoreVertex()) { IsVtx = Standard_False; } return Standard_True; } return Standard_False; } //================================================================================================= Standard_Boolean BRepBlend_SurfRstLineBuilder::Recadre(Blend_SurfRstFunction& Func, Blend_FuncInv& Finv, math_Vector& Solinv, Standard_Boolean& IsVtx, Handle(Adaptor3d_HVertex)& Vtx) { math_Vector toler(1, 4), infb(1, 4), supb(1, 4); Finv.GetTolerance(toler, tolpoint3d); Finv.GetBounds(infb, supb); Solinv(1) = sol(3); Solinv(2) = param; Solinv(3) = sol(1); Solinv(4) = sol(2); math_FunctionSetRoot rsnld(Finv, toler, 30); rsnld.Perform(Finv, Solinv, infb, supb); if (!rsnld.IsDone()) { #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder :RSNLD not done " << std::endl; #endif return Standard_False; } rsnld.Root(Solinv); if (Finv.IsSolution(Solinv, tolpoint3d)) { gp_Pnt2d p2d(Solinv(3), Solinv(4)); TopAbs_State situ = domain1->Classify(p2d, tolpoint2d, 0); if ((situ != TopAbs_IN) && (situ != TopAbs_ON)) { return Standard_False; } domain2->Initialize(rst); domain2->InitVertexIterator(); IsVtx = !domain2->MoreVertex(); while (!IsVtx) { Vtx = domain2->Vertex(); if (Abs(BRepBlend_BlendTool::Parameter(Vtx, rst) - Solinv(1)) <= BRepBlend_BlendTool::Tolerance(Vtx, rst)) { IsVtx = Standard_True; } else { domain2->NextVertex(); IsVtx = !domain2->MoreVertex(); } } if (!domain2->MoreVertex()) { IsVtx = Standard_False; } // The section is recalculated by direct resolution, otherwise // incoherences between the parameter and the ground caused by yawn are returned. math_Vector infbound(1, 3), supbound(1, 3); math_Vector parinit(1, 3), tolerance(1, 3); Func.GetTolerance(tolerance, tolpoint3d); Func.GetBounds(infbound, supbound); math_FunctionSetRoot rsnld2(Func, tolerance, 30); parinit(1) = Solinv(3); parinit(2) = Solinv(4); parinit(3) = Solinv(1); Func.Set(Solinv(2)); rsnld2.Perform(Func, parinit, infbound, supbound); if (!rsnld2.IsDone()) return Standard_False; rsnld2.Root(parinit); Solinv(3) = parinit(1); Solinv(4) = parinit(2); Solinv(1) = parinit(3); return Standard_True; } return Standard_False; } //================================================================================================= Standard_Boolean BRepBlend_SurfRstLineBuilder::Recadre(Blend_SurfPointFuncInv& FinvP, math_Vector& Solinv, Standard_Boolean& IsVtx, Handle(Adaptor3d_HVertex)& Vtx) { // Le point. gp_Pnt2d p2drst; Standard_Real firstrst = rst->FirstParameter(); Standard_Real lastrst = rst->LastParameter(); Standard_Real wpoint = firstrst; if ((sol(3) - firstrst) > (lastrst - sol(3))) wpoint = lastrst; p2drst = rst->Value(wpoint); gp_Pnt thepoint = surf2->Value(p2drst.X(), p2drst.Y()); FinvP.Set(thepoint); math_Vector toler(1, 3), infb(1, 3), supb(1, 3); FinvP.GetTolerance(toler, tolpoint3d); FinvP.GetBounds(infb, supb); Solinv(1) = param; Solinv(2) = sol(1); Solinv(3) = sol(2); math_FunctionSetRoot rsnld(FinvP, toler, 30); rsnld.Perform(FinvP, Solinv, infb, supb); if (!rsnld.IsDone()) { #ifdef OCCT_DEBUG std::cout << "SurfRstLineBuilder :RSNLD not done " << std::endl; #endif return Standard_False; } rsnld.Root(Solinv); if (FinvP.IsSolution(Solinv, tolpoint3d)) { gp_Pnt2d p2d(Solinv(2), Solinv(3)); TopAbs_State situ = domain1->Classify(p2d, tolpoint2d, 0); if ((situ != TopAbs_IN) && (situ != TopAbs_ON)) { return Standard_False; } domain2->Initialize(rst); domain2->InitVertexIterator(); IsVtx = !domain2->MoreVertex(); while (!IsVtx) { Vtx = domain2->Vertex(); if (Abs(BRepBlend_BlendTool::Parameter(Vtx, rst) - wpoint) <= BRepBlend_BlendTool::Tolerance(Vtx, rst)) { IsVtx = Standard_True; } else { domain2->NextVertex(); IsVtx = !domain2->MoreVertex(); } } if (!domain2->MoreVertex()) { IsVtx = Standard_False; } return Standard_True; } return Standard_False; } //================================================================================================= void BRepBlend_SurfRstLineBuilder::Transition(const Standard_Boolean OnFirst, const Handle(Adaptor2d_Curve2d)& Arc, const Standard_Real Param, IntSurf_Transition& TLine, IntSurf_Transition& TArc) { Standard_Boolean computetranstionaveclacorde = 0; gp_Vec tgline; Blend_Point prevprev; if (previousP.IsTangencyPoint()) { if (line->NbPoints() < 2) return; computetranstionaveclacorde = 1; if (sens < 0) { prevprev = line->Point(2); } else { prevprev = line->Point(line->NbPoints() - 1); } } gp_Pnt2d p2d; gp_Vec2d dp2d; gp_Pnt pbid; gp_Vec d1u, d1v, normale, tgrst; Arc->D1(Param, p2d, dp2d); if (OnFirst) { surf1->D1(p2d.X(), p2d.Y(), pbid, d1u, d1v); if (!computetranstionaveclacorde) tgline = previousP.TangentOnS1(); else tgline = gp_Vec(prevprev.PointOnS(), previousP.PointOnS()); } else { surf2->D1(p2d.X(), p2d.Y(), pbid, d1u, d1v); if (!computetranstionaveclacorde) tgline = previousP.TangentOnS2(); else tgline = gp_Vec(prevprev.PointOnC(), previousP.PointOnC()); } tgrst.SetLinearForm(dp2d.X(), d1u, dp2d.Y(), d1v); normale = d1u.Crossed(d1v); IntSurf::MakeTransition(tgline, tgrst, normale, TLine, TArc); } //================================================================================================= void BRepBlend_SurfRstLineBuilder::MakeExtremity(BRepBlend_Extremity& Extrem, const Standard_Boolean OnFirst, const Handle(Adaptor2d_Curve2d)& Arc, const Standard_Real Param, const Standard_Boolean IsVtx, const Handle(Adaptor3d_HVertex)& Vtx) { IntSurf_Transition Tline, Tarc; Standard_Real prm; Handle(Adaptor3d_TopolTool) Iter; if (OnFirst) { Extrem.SetValue(previousP.PointOnS(), sol(1), sol(2), previousP.Parameter(), tolpoint3d); if (!previousP.IsTangencyPoint()) Extrem.SetTangent(previousP.TangentOnS()); Iter = domain1; } else { Extrem.SetValue(previousP.PointOnC(), sol(3), previousP.Parameter(), tolpoint3d); if (!previousP.IsTangencyPoint()) Extrem.SetTangent(previousP.TangentOnC()); Iter = domain2; } Iter->Init(); if (!IsVtx) { Transition(OnFirst, Arc, Param, Tline, Tarc); Extrem.AddArc(Arc, Param, Tline, Tarc); } else { Extrem.SetVertex(Vtx); while (Iter->More()) { Handle(Adaptor2d_Curve2d) arc = Iter->Value(); if (arc != Arc) { Iter->Initialize(arc); Iter->InitVertexIterator(); while (Iter->MoreVertex()) { if (Iter->Identical(Vtx, Iter->Vertex())) { prm = BRepBlend_BlendTool::Parameter(Vtx, arc); Transition(OnFirst, arc, prm, Tline, Tarc); Extrem.AddArc(arc, prm, Tline, Tarc); } Iter->NextVertex(); } } else { Transition(OnFirst, arc, Param, Tline, Tarc); Extrem.AddArc(arc, Param, Tline, Tarc); } Iter->Next(); } } } //================================================================================================= Blend_Status BRepBlend_SurfRstLineBuilder::CheckDeflectionOnSurf(const Blend_Point& CurPoint) { // Controls 3d of Blend_CSWalking. // rule by tests in U4 corresponds to 11.478 d const Standard_Real CosRef3D = 0.98; Standard_Real Cosi = 0, Cosi2 = 0; Standard_Boolean curpointistangent = CurPoint.IsTangencyPoint(); Standard_Boolean prevpointistangent = previousP.IsTangencyPoint(); gp_Pnt Psurf = CurPoint.PointOnS(); gp_Vec Tgsurf; if (!curpointistangent) { Tgsurf = CurPoint.TangentOnS(); } gp_Pnt prevP = previousP.PointOnS(); gp_Vec prevTg; if (!prevpointistangent) { prevTg = previousP.TangentOnS(); } Standard_Real Norme, prevNorme = 0.; gp_Vec Corde(prevP, Psurf); Norme = Corde.SquareMagnitude(); // if(!curpointistangent) curNorme = Tgsurf.SquareMagnitude(); if (!prevpointistangent) prevNorme = prevTg.SquareMagnitude(); const Standard_Real toler3d = 0.01 * tolpoint3d; if (Norme <= toler3d * toler3d) { // it can be necessary to force same point return Blend_SamePoints; } if (!prevpointistangent) { if (prevNorme <= toler3d * toler3d) { return Blend_SamePoints; } Cosi = sens * Corde * prevTg; if (Cosi < 0.) { // angle 3d>pi/2. --> return back return Blend_Backward; } Cosi2 = Cosi * Cosi / prevNorme / Norme; if (Cosi2 < CosRef3D) { return Blend_StepTooLarge; } } if (!curpointistangent) { // Check if it is necessary to control the sign of prevtg*Tgsurf Cosi = sens * Corde * Tgsurf; Cosi2 = Cosi * Cosi / Tgsurf.SquareMagnitude() / Norme; if (Cosi2 < CosRef3D || Cosi < 0.) { return Blend_StepTooLarge; } } if (!curpointistangent && !prevpointistangent) { // Estimation of the current arrow Standard_Real FlecheCourante = (prevTg.Normalized().XYZ() - Tgsurf.Normalized().XYZ()).SquareModulus() * Norme / 64.; if (FlecheCourante <= 0.25 * fleche * fleche) { return Blend_StepTooSmall; } if (FlecheCourante > fleche * fleche) { // not too great : return Blend_StepTooLarge; } } return Blend_OK; } //================================================================================================= Blend_Status BRepBlend_SurfRstLineBuilder::CheckDeflectionOnRst(const Blend_Point& CurPoint) { // Controls 3D of Blend_CSWalking. // rule by tests in U4 corresponds to 11.478 d const Standard_Real CosRef3D = 0.98; Standard_Real Cosi, Cosi2; Standard_Boolean curpointistangent = CurPoint.IsTangencyPoint(); Standard_Boolean prevpointistangent = previousP.IsTangencyPoint(); gp_Pnt Psurf = CurPoint.PointOnC(); gp_Vec Tgsurf; if (!curpointistangent) { Tgsurf = CurPoint.TangentOnC(); } gp_Pnt prevP = previousP.PointOnC(); gp_Vec prevTg; if (!prevpointistangent) { prevTg = previousP.TangentOnC(); } Standard_Real Norme, prevNorme = 0.; gp_Vec Corde(prevP, Psurf); Norme = Corde.SquareMagnitude(); // if(!curpointistangent) curNorme = Tgsurf.SquareMagnitude(); if (!prevpointistangent) prevNorme = prevTg.SquareMagnitude(); const Standard_Real toler3d = 0.01 * tolpoint3d; if (Norme <= toler3d * toler3d) { // it can be necessary to force same point return Blend_SamePoints; } if (!prevpointistangent) { if (prevNorme <= toler3d * toler3d) { return Blend_SamePoints; } Cosi = sens * Corde * prevTg; if (Cosi < 0.) { // angle 3d>pi/2. --> return back return Blend_Backward; } Cosi2 = Cosi * Cosi / prevNorme / Norme; if (Cosi2 < CosRef3D) { return Blend_StepTooLarge; } } if (!curpointistangent) { // Check if it is necessary to control the sign of prevtg*Tgsurf Cosi = sens * Corde * Tgsurf; Cosi2 = Cosi * Cosi / Tgsurf.SquareMagnitude() / Norme; if (Cosi2 < CosRef3D || Cosi < 0.) { return Blend_StepTooLarge; } } if (!curpointistangent && !prevpointistangent) { // Estimation of the current arrow Standard_Real FlecheCourante = (prevTg.Normalized().XYZ() - Tgsurf.Normalized().XYZ()).SquareModulus() * Norme / 64.; if (FlecheCourante <= 0.25 * fleche * fleche) { return Blend_StepTooSmall; } if (FlecheCourante > fleche * fleche) { // not too great return Blend_StepTooLarge; } } return Blend_OK; } static IntSurf_TypeTrans ConvOrToTra(const TopAbs_Orientation O) { if (O == TopAbs_FORWARD) return IntSurf_In; return IntSurf_Out; } //================================================================================================= Blend_Status BRepBlend_SurfRstLineBuilder::TestArret(Blend_SurfRstFunction& Func, const Standard_Boolean TestDeflection, const Blend_Status State) { gp_Pnt pts, ptrst; gp_Pnt2d pt2drst; gp_Vec tgs, tgrst; gp_Vec2d tg2ds, tg2drst; Blend_Status StateS, StateRst; IntSurf_TypeTrans tras = IntSurf_Undecided, trarst = IntSurf_Undecided; Blend_Point curpoint; if (Func.IsSolution(sol, tolpoint3d)) { Standard_Boolean curpointistangent = Func.IsTangencyPoint(); pts = Func.PointOnS(); ptrst = Func.PointOnRst(); pt2drst = Func.Pnt2dOnRst(); if (curpointistangent) { curpoint.SetValue(pts, ptrst, param, sol(1), sol(2), pt2drst.X(), pt2drst.Y(), sol(3)); } else { tgs = Func.TangentOnS(); tgrst = Func.TangentOnRst(); tg2ds = Func.Tangent2dOnS(); tg2drst = Func.Tangent2dOnRst(); curpoint.SetValue(pts, ptrst, param, sol(1), sol(2), pt2drst.X(), pt2drst.Y(), sol(3), tgs, tgrst, tg2ds, tg2drst); } if (TestDeflection) { StateS = CheckDeflectionOnSurf(curpoint); StateRst = CheckDeflectionOnRst(curpoint); } else { StateS = StateRst = Blend_OK; } if (StateS == Blend_Backward) { StateS = Blend_StepTooLarge; rebrou = Standard_True; } if (StateRst == Blend_Backward) { StateRst = Blend_StepTooLarge; rebrou = Standard_True; } if (StateS == Blend_StepTooLarge || StateRst == Blend_StepTooLarge) { return Blend_StepTooLarge; } if (!comptra && !curpointistangent) { gp_Vec tgsecs, nors; Func.Decroch(sol, nors, tgsecs); nors.Normalize(); Standard_Real testra = tgsecs.Dot(nors.Crossed(tgs)); if (Abs(testra) > tolpoint3d) { if (testra < 0.) { tras = IntSurf_In; } else if (testra > 0.) { tras = IntSurf_Out; } gp_Pnt2d p2drstref; gp_Vec2d tg2drstref; rst->D1(sol(3), p2drstref, tg2drstref); testra = tg2drst.Dot(tg2drstref); TopAbs_Orientation Or = domain2->Orientation(rst); if (Abs(testra) > 1.e-8) { if (testra < 0.) { trarst = ConvOrToTra(TopAbs::Reverse(Or)); } else if (testra > 0.) { trarst = ConvOrToTra(Or); } comptra = Standard_True; line->Set(tras, trarst); } } } if (StateS == Blend_OK || StateRst == Blend_OK) { previousP = curpoint; return State; } if (StateS == Blend_StepTooSmall && StateRst == Blend_StepTooSmall) { previousP = curpoint; if (State == Blend_OK) { return Blend_StepTooSmall; } else { return State; } } if (State == Blend_OK) { return Blend_SamePoints; } else { return State; } } return Blend_StepTooLarge; } //================================================================================================= Standard_Boolean BRepBlend_SurfRstLineBuilder::CheckInside(Blend_SurfRstFunction& Func, TopAbs_State& SituOnC, TopAbs_State& SituOnS, Standard_Boolean& Decroch) { math_Vector tolerance(1, 3); Func.GetTolerance(tolerance, tolpoint3d); // face pcurve. Standard_Real w = sol(3); if (w < rst->FirstParameter() - tolerance(3) || w > rst->LastParameter() + tolerance(3)) { SituOnC = TopAbs_OUT; } else if (w > rst->FirstParameter() && w < rst->LastParameter()) { SituOnC = TopAbs_IN; } else SituOnC = TopAbs_ON; // face surface gp_Pnt2d p2d(sol(1), sol(2)); SituOnS = domain1->Classify(p2d, tolpoint2d, 0); // lost contact gp_Vec tgs, nors; Decroch = Func.Decroch(sol, tgs, nors); return (SituOnC == TopAbs_IN && SituOnS == TopAbs_IN && !Decroch); }