mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
test bugs modalg_7 bug22821 failed on fillet shape with 5-th edge. Experimentally has been found that reducing of parameter ChFi3d_Builder::tolesp for this task solves the issue. So, as soluton it is proposed to link parameter toleps with parameter range of spine curve. So, production coefficient has been set to pass all tests and 2 teset was extended: tests/blend/complex/A6, tests/bugs/modalg_7/bug22821 first has been extended to test different scaling factors, second has been extended to make fillet on all edges from 12. Additionally: - fixed misusage of tolesp in contexts where tolerance of point in 3d is excepted; In some context usage of tol_esp is irrelevant, because its essentiality - tolerance of the parameter on the 3d curve. So, in such context it has been replaced with new parameter tol3d (with fix value 1.0e-4). Get rid of tolapp3d duplication constant - tol_3d - tolesp = 5.0e-5 * (umax - umin) - tolesp replaced by tolpoint2d/tolpoint3d in several classes. Blend_Walking BRepBlend_SurfRstLineBuilder BRepBlend_RstRstLineBuilder Blend_CSWalking Instead `tolesp` - `tolgui` is employed in contexts where tolerance of guide curve parameter is excepted. Instead `tolesp` - `tolpoint2d` or `tolpoint3d` is employed in contexts where tolerance of point in 2d or 3d space is excepted. - Replace tolesp with tolpoint2d/tolpoint3d in BBPP function argument. - Use tolapp3d instead tolesp in BonVoisin function,
530 lines
14 KiB
Plaintext
530 lines
14 KiB
Plaintext
// Copyright (c) 1995-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.
|
|
|
|
//26-04-1997 modified by pmn : Initialisation plus fine de la resolution
|
|
|
|
Standard_Integer Blend_Walking::ArcToRecadre(const Standard_Boolean OnFirst,
|
|
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.;
|
|
Handle(TheTopolTool) Iter;
|
|
|
|
if (OnFirst) {
|
|
if(byinter) previousP.ParametersOnS1(uprev,vprev);
|
|
pt2d.SetCoord(theSol(1),theSol(2));
|
|
Iter = recdomain1;
|
|
}
|
|
else {
|
|
if(byinter) previousP.ParametersOnS2(uprev,vprev);
|
|
pt2d.SetCoord(theSol(3),theSol(4));
|
|
Iter = recdomain2;
|
|
}
|
|
lastpt2d.SetCoord(uprev,vprev);
|
|
Iter->Init();
|
|
while (Iter->More()) {
|
|
nbarc++; ok = 0;
|
|
if (OnFirst) {
|
|
if(byinter) {
|
|
ok = okinter = TheBlendTool::Inters(pt2d,lastpt2d,
|
|
surf1,Iter->Value(),prm,dist);
|
|
}
|
|
if(!ok) ok = TheBlendTool::Project(pt2d,surf1,Iter->Value(),prm,dist);
|
|
}
|
|
else {
|
|
if(byinter) {
|
|
ok = okinter = TheBlendTool::Inters(pt2d,lastpt2d,
|
|
surf2,Iter->Value(),prm,dist);
|
|
}
|
|
if(!ok) ok = TheBlendTool::Project(pt2d,surf2,Iter->Value(),prm,dist);
|
|
}
|
|
if (ok && (nbarc != PrevIndex) ) {
|
|
if (dist<distmin || okinter) {
|
|
distmin = dist;
|
|
ponarc = prm;
|
|
IndexSol = nbarc;
|
|
if(okinter && (PrevIndex==0)) break;
|
|
}
|
|
}
|
|
Iter->Next();
|
|
}
|
|
return IndexSol;
|
|
}
|
|
|
|
Standard_Boolean Blend_Walking::Recadre(Blend_FuncInv& FuncInv,
|
|
const Standard_Boolean OnFirst,
|
|
const math_Vector& theSol,
|
|
math_Vector& solrst,
|
|
Standard_Integer& Indexsol,
|
|
Standard_Boolean& IsVtx,
|
|
TheVertex& Vtx,
|
|
const Standard_Real Extrap)
|
|
|
|
{
|
|
Standard_Boolean jalons_Trouve = Standard_False;
|
|
Standard_Boolean recadre = Standard_True, ok;
|
|
Standard_Boolean byinter = (line->NbPoints() != 0);
|
|
Standard_Integer LeJalon = 0;
|
|
|
|
Standard_Integer nbarc;
|
|
Standard_Real dist,prm,pmin, vtol;
|
|
gp_Pnt2d pt2d, lastpt2d;
|
|
|
|
math_Vector toler(1,4),infb(1,4),supb(1,4),valsol(1,4);
|
|
|
|
Handle(Adaptor2d_Curve2d) thecur;
|
|
Handle(TheTopolTool) Iter;
|
|
|
|
if (OnFirst) Iter = recdomain1;
|
|
else Iter = recdomain2;
|
|
|
|
Indexsol = ArcToRecadre(OnFirst, theSol, 0,
|
|
lastpt2d, pt2d, pmin);
|
|
IsVtx = Standard_False;
|
|
if (Indexsol == 0) {
|
|
return Standard_False;
|
|
}
|
|
|
|
Iter->Init();
|
|
nbarc = 1;
|
|
while (nbarc < Indexsol) {
|
|
nbarc++;
|
|
Iter->Next();
|
|
}
|
|
|
|
TheArc thearc = Iter->Value();
|
|
|
|
if (OnFirst) {
|
|
thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
|
|
}
|
|
else {
|
|
thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
|
|
}
|
|
|
|
// Le probleme a resoudre
|
|
FuncInv.Set(OnFirst,thecur);
|
|
FuncInv.GetBounds(infb,supb);
|
|
infb(2) -= Extrap;
|
|
supb(2) += Extrap;
|
|
|
|
FuncInv.GetTolerance(toler,0.1 * tolpoint3d);//Il vaut mieux garder un peu de marge
|
|
math_FunctionSetRoot rsnld(FuncInv,toler,35);
|
|
toler *= 10; // Mais on fait les tests correctements
|
|
|
|
// Calcul d'un point d'init
|
|
Standard_Real ufirst,ulast;
|
|
TheBlendTool::Bounds(thecur, ufirst,ulast);
|
|
// Pour aider a trouver les coins singuliers on recadre eventuelement le paramtere
|
|
if (Abs(pmin-ufirst) < Abs(ulast-ufirst)/1000) {
|
|
pmin = ufirst;
|
|
}
|
|
if (Abs(pmin-ulast) < Abs(ulast-ufirst)/1000) {
|
|
pmin = ulast;
|
|
}
|
|
|
|
if (byinter) {
|
|
Standard_Real lastParam = previousP.Parameter();
|
|
// Verifie que le recadrage n'est pas un jalons
|
|
if (jalons.Length()!=0) {
|
|
Standard_Real t1, t2, t;
|
|
Standard_Boolean Cherche=Standard_True;
|
|
Standard_Integer ii;
|
|
if (lastParam < param) {
|
|
t1 = lastParam; t2 = param;
|
|
}
|
|
else {
|
|
t1 = param; t2 = lastParam;
|
|
}
|
|
for (ii=1; ii<=jalons.Length() && Cherche; ii++) {
|
|
t = jalons.Value(ii).Parameter();
|
|
if (((t1 < t) && (t2 > t)) || (t==param)) {
|
|
jalons_Trouve = Standard_True;
|
|
LeJalon = ii;
|
|
Cherche = Standard_False; //Ne marche que si l'on sort simultanement
|
|
}
|
|
else Cherche = t < t2; // On s'arrete si t>=t2;
|
|
}
|
|
}
|
|
if (!jalons_Trouve) {
|
|
//Initialisation par Interpolation
|
|
Standard_Real lambda, u, v;
|
|
gp_Pnt2d Pnt, Pnt1, Pnt2;//, POnC;
|
|
thecur->D0(pmin, Pnt);
|
|
if (OnFirst) {
|
|
previousP.ParametersOnS2(u,v);
|
|
Pnt1.SetCoord(u, v);
|
|
Pnt2.SetCoord(theSol(3), theSol(4));
|
|
}
|
|
else {
|
|
previousP.ParametersOnS1(u,v);
|
|
Pnt1.SetCoord(u, v);
|
|
Pnt2.SetCoord(theSol(1), theSol(2));
|
|
}
|
|
|
|
lambda = Pnt.Distance(lastpt2d);
|
|
if (lambda > 1.e-12) lambda /= Pnt.Distance(lastpt2d) + Pnt.Distance(pt2d);
|
|
else lambda = 0;
|
|
solrst(1) = pmin;
|
|
solrst(2) = (1-lambda)*lastParam + lambda*param;
|
|
solrst(3) = (1-lambda)*Pnt1.X() + lambda*Pnt2.X();
|
|
solrst(4) = (1-lambda)*Pnt1.Y() + lambda*Pnt2.Y();
|
|
}
|
|
}
|
|
else { // sinon on initialise par le dernier point calcule
|
|
solrst(1) = pmin;
|
|
solrst(2) = param;
|
|
if (OnFirst) {
|
|
solrst(3) = theSol(3);
|
|
solrst(4) = theSol(4);
|
|
}
|
|
else {
|
|
solrst(3) = theSol(1);
|
|
solrst(4) = theSol(2);
|
|
}
|
|
}
|
|
|
|
if (jalons_Trouve) { // On recupere le jalon
|
|
Blend_Point MonJalon;
|
|
Standard_Boolean periodic;
|
|
Standard_Real uperiod = 0, vperiod = 0;
|
|
gp_Pnt2d Pnt;
|
|
Standard_Real distaux;
|
|
MonJalon = jalons.Value(LeJalon);
|
|
solrst(2) = MonJalon.Parameter();
|
|
if (OnFirst) {
|
|
MonJalon.ParametersOnS2(solrst(3), solrst(4));
|
|
periodic = (surf2->IsUPeriodic() || surf2->IsVPeriodic());
|
|
}
|
|
else {
|
|
MonJalon.ParametersOnS1(solrst(3), solrst(4));
|
|
periodic = (surf1->IsUPeriodic() || surf1->IsVPeriodic());
|
|
}
|
|
|
|
// Recadrage eventuelle pour le cas periodique
|
|
if (periodic) {
|
|
Handle(Adaptor3d_Surface) surf;
|
|
if (OnFirst) surf = surf2;
|
|
else surf = surf1;
|
|
|
|
lastpt2d = thecur->Value(pmin);
|
|
|
|
if (surf->IsUPeriodic()) {
|
|
uperiod = surf->UPeriod();
|
|
if (solrst(3)-lastpt2d.X() > uperiod*0.6) solrst(3) -= uperiod;
|
|
if (solrst(3)-lastpt2d.X() < -uperiod*0.6) solrst(3) += uperiod;
|
|
}
|
|
if (surf->IsVPeriodic()) {
|
|
vperiod = surf->VPeriod();
|
|
if (solrst(4)-lastpt2d.Y() > vperiod*0.6) solrst(4) -= vperiod;
|
|
if (solrst(4)-lastpt2d.Y() < -vperiod*0.6) solrst(4) += vperiod;
|
|
}
|
|
}
|
|
|
|
// Pour le parametre sur arc il faut projeter...
|
|
pt2d.SetCoord(solrst(3), solrst(4));
|
|
Pnt = thecur->Value(ufirst);
|
|
dist = pt2d.Distance(Pnt);
|
|
solrst(1) = ufirst;
|
|
Pnt = thecur->Value(ulast);
|
|
distaux = pt2d.Distance(Pnt);
|
|
if ( distaux < dist) {
|
|
solrst(1) = ulast;
|
|
dist = distaux;
|
|
}
|
|
|
|
if (dist>Precision::PConfusion()) {
|
|
prm = pmin;
|
|
if (OnFirst) {
|
|
ok = TheBlendTool::Project(pt2d,surf1,thearc,prm,distaux);
|
|
}
|
|
else {
|
|
ok = TheBlendTool::Project(pt2d,surf2,thearc,prm,distaux);
|
|
}
|
|
if (ok && (pt2d.Distance(thecur->Value(prm)) < dist)) solrst(1) = prm;
|
|
else solrst(1) = pmin;
|
|
}
|
|
// On verifie le jalon
|
|
jalons_Trouve = (FuncInv.IsSolution(solrst,tolpoint3d));
|
|
}
|
|
|
|
if (!jalons_Trouve) {
|
|
// Resolution...
|
|
rsnld.Perform(FuncInv,solrst,infb,supb);
|
|
if (!rsnld.IsDone()) {
|
|
#ifdef OCCT_DEBUG
|
|
std::cout << "Walking::Recadre : RSNLD not done " << std::endl;
|
|
#endif
|
|
recadre = Standard_False;
|
|
}
|
|
else {
|
|
rsnld.Root(solrst);
|
|
recadre = FuncInv.IsSolution(solrst,tolpoint3d);
|
|
}
|
|
}
|
|
|
|
// En cas d'echecs, on regarde si un autre arc
|
|
// peut faire l'affaire (cas des sorties a proximite d'un vertex)
|
|
dist = (ulast - ufirst)/100;
|
|
if ((!recadre) &&
|
|
((Abs(pmin-ulast) < dist) || (Abs(pmin-ufirst) < dist)) ) {
|
|
|
|
Indexsol = ArcToRecadre(OnFirst, theSol, Indexsol,
|
|
lastpt2d, pt2d, pmin);
|
|
if (Indexsol == 0) {
|
|
return Standard_False;
|
|
}
|
|
|
|
Iter->Init();
|
|
nbarc = 1;
|
|
while (nbarc < Indexsol) {
|
|
nbarc++;
|
|
Iter->Next();
|
|
}
|
|
thearc = Iter->Value();
|
|
|
|
if (OnFirst) {
|
|
thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
|
|
}
|
|
else {
|
|
thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
|
|
}
|
|
solrst(1) = pmin;
|
|
// Le probleme a resoudre
|
|
FuncInv.Set(OnFirst,thecur);
|
|
FuncInv.GetBounds(infb,supb);
|
|
FuncInv.GetTolerance(toler,0.1 * tolpoint3d);//Il vaut mieux garder un peu de marge
|
|
math_FunctionSetRoot aRsnld(FuncInv,toler,35);
|
|
toler *= 10; // Mais on fait les tests correctements
|
|
// Resolution...
|
|
aRsnld.Perform(FuncInv,solrst,infb,supb);
|
|
|
|
if (!aRsnld.IsDone()) {
|
|
#ifdef OCCT_DEBUG
|
|
std::cout << "Walking::Recadre : RSNLD not done " << std::endl;
|
|
#endif
|
|
recadre = Standard_False;
|
|
}
|
|
else {
|
|
aRsnld.Root(solrst);
|
|
recadre = FuncInv.IsSolution(solrst,tolpoint3d);
|
|
}
|
|
}
|
|
|
|
if (recadre) {
|
|
// Classification topologique
|
|
if (OnFirst) {
|
|
thecur = TheBlendTool::CurveOnSurf(thearc,surf1);
|
|
}
|
|
else {
|
|
thecur = TheBlendTool::CurveOnSurf(thearc,surf2);
|
|
}
|
|
TheBlendTool::Bounds(thecur, ufirst,ulast);
|
|
|
|
Iter->Initialize(thearc);
|
|
Iter->InitVertexIterator();
|
|
IsVtx = !Iter->MoreVertex();
|
|
while (!IsVtx) {
|
|
Vtx = Iter->Vertex();
|
|
vtol = 0.4*Abs(ulast-ufirst); // Un majorant de la tolerance
|
|
if (vtol > Max(TheBlendTool::Tolerance(Vtx,thearc), toler(1)))
|
|
vtol = Max(TheBlendTool::Tolerance(Vtx,thearc), toler(1));
|
|
if (Abs(TheBlendTool::Parameter(Vtx,thearc)-solrst(1)) <= vtol) {
|
|
IsVtx = Standard_True; // On est dans la boule du vertex ou
|
|
// le vertex est dans la "boule" du recadrage
|
|
}
|
|
else {
|
|
Iter->NextVertex();
|
|
IsVtx = !Iter->MoreVertex();
|
|
}
|
|
}
|
|
if (!Iter->MoreVertex()) {
|
|
IsVtx = Standard_False;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
|
|
void Blend_Walking::Transition(const Standard_Boolean OnFirst,
|
|
const TheArc& A,
|
|
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;
|
|
gp_Dir thenormal;
|
|
CSLib_NormalStatus stat;
|
|
|
|
TheArcTool::D1(A,Param,p2d,dp2d);
|
|
if (OnFirst) {
|
|
TheSurfaceTool::D1(surf1,p2d.X(),p2d.Y(),pbid,d1u,d1v);
|
|
if(!computetranstionaveclacorde) tgline = previousP.TangentOnS1();
|
|
else tgline = gp_Vec(prevprev.PointOnS1(),previousP.PointOnS1());
|
|
}
|
|
else {
|
|
TheSurfaceTool::D1(surf2,p2d.X(),p2d.Y(),pbid,d1u,d1v);
|
|
if(!computetranstionaveclacorde) tgline = previousP.TangentOnS2();
|
|
else tgline = gp_Vec(prevprev.PointOnS2(),previousP.PointOnS2());
|
|
}
|
|
|
|
tgrst.SetLinearForm(dp2d.X(),d1u,dp2d.Y(),d1v);
|
|
|
|
CSLib::Normal(d1u, d1v, 1.e-9, stat, thenormal);
|
|
if (stat == CSLib_Defined) normale.SetXYZ(thenormal.XYZ());
|
|
else {
|
|
Handle(Adaptor3d_Surface) surf;
|
|
if (OnFirst) surf = surf1;
|
|
else surf = surf2;
|
|
Standard_Integer iu, iv;
|
|
TColgp_Array2OfVec Der(0, 2 , 0, 2);
|
|
TheSurfaceTool::D2(surf,p2d.X(),p2d.Y(),pbid, Der(1,0), Der(0,1),
|
|
Der(2,0), Der(0,2), Der(1,1));
|
|
Der(2,1) = TheSurfaceTool::DN(surf, p2d.X(), p2d.Y(), 2,1);
|
|
Der(1,2) = TheSurfaceTool::DN(surf,p2d.X(),p2d.Y(), 1,2);
|
|
Der(2,2) = TheSurfaceTool::DN(surf,p2d.X(),p2d.Y(), 2,2);
|
|
CSLib::Normal(2, Der, 1.e-9,
|
|
p2d.X(), p2d.Y(),
|
|
TheSurfaceTool::FirstUParameter(surf),
|
|
TheSurfaceTool::LastUParameter(surf),
|
|
TheSurfaceTool::FirstVParameter(surf),
|
|
TheSurfaceTool::LastVParameter(surf),
|
|
stat, thenormal, iu, iv);
|
|
normale.SetXYZ(thenormal.XYZ());
|
|
#ifdef OCCT_DEBUG
|
|
if (stat == CSLib_InfinityOfSolutions)
|
|
std::cout << "Blend_Walking::Transition : Infinite de Normal" << std::endl;
|
|
#endif
|
|
}
|
|
|
|
IntSurf::MakeTransition(tgline,tgrst,normale,TLine,TArc);
|
|
|
|
}
|
|
|
|
|
|
void Blend_Walking::MakeExtremity(TheExtremity& Extrem,
|
|
const Standard_Boolean OnFirst,
|
|
const Standard_Integer Index,
|
|
const Standard_Real Param,
|
|
const Standard_Boolean IsVtx,
|
|
const TheVertex& Vtx)
|
|
{
|
|
|
|
IntSurf_Transition Tline,Tarc;
|
|
Standard_Integer nbarc;
|
|
Handle(TheTopolTool) Iter;
|
|
|
|
if (OnFirst) {
|
|
Extrem.SetValue(previousP.PointOnS1(),
|
|
sol(1),sol(2),
|
|
previousP.Parameter(), tolpoint3d);
|
|
if (!previousP.IsTangencyPoint())
|
|
Extrem.SetTangent(previousP.TangentOnS1());
|
|
Iter = recdomain1;
|
|
}
|
|
else {
|
|
Extrem.SetValue(previousP.PointOnS2(),
|
|
sol(3),sol(4),
|
|
previousP.Parameter(), tolpoint3d);
|
|
if (!previousP.IsTangencyPoint())
|
|
Extrem.SetTangent(previousP.TangentOnS2());
|
|
Iter = recdomain2;
|
|
}
|
|
|
|
Iter->Init();
|
|
nbarc = 1;
|
|
|
|
while (nbarc < Index) {
|
|
nbarc++;
|
|
Iter->Next();
|
|
}
|
|
|
|
Transition(OnFirst,Iter->Value(),Param,Tline,Tarc);
|
|
Extrem.AddArc(Iter->Value(),Param,Tline,Tarc);
|
|
if (IsVtx) Extrem.SetVertex(Vtx);
|
|
}
|
|
|
|
void Blend_Walking::MakeSingularExtremity( TheExtremity& Extrem,
|
|
const Standard_Boolean OnFirst,
|
|
const TheVertex& Vtx)
|
|
{
|
|
IntSurf_Transition Tline,Tarc;
|
|
Handle(TheTopolTool) Iter;
|
|
Standard_Real prm;
|
|
|
|
if (OnFirst) {
|
|
Iter = recdomain1;
|
|
if (!previousP.IsTangencyPoint())
|
|
Extrem.SetTangent(previousP.TangentOnS1());
|
|
}
|
|
else {
|
|
if (!previousP.IsTangencyPoint())
|
|
Extrem.SetTangent(previousP.TangentOnS2());
|
|
Iter = recdomain2;
|
|
}
|
|
|
|
Iter->Init();
|
|
Extrem.SetVertex(Vtx);
|
|
while (Iter->More()) {
|
|
TheArc arc = Iter->Value();
|
|
Iter->Initialize(arc);
|
|
Iter->InitVertexIterator();
|
|
while (Iter->MoreVertex()) {
|
|
if (Iter->Identical(Vtx,Iter->Vertex())) {
|
|
prm = TheBlendTool::Parameter(Vtx,arc);
|
|
Transition(OnFirst,arc,prm,Tline,Tarc);
|
|
Extrem.AddArc(arc,prm,Tline,Tarc);
|
|
}
|
|
Iter->NextVertex();
|
|
}
|
|
Iter->Next();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|