1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

0025701: Problem with the symmetry of fillet on two perpendicular cylinders

Test case for issue CR25701
This commit is contained in:
jgv
2015-02-19 16:09:37 +03:00
committed by bugmaster
parent bd28b2afac
commit af99433e4e
13 changed files with 441 additions and 84 deletions

View File

@@ -160,6 +160,11 @@ is
PC1,PC2 : Real from Standard);
---Purpose: Creates a point on two curves.
SetParameter(me : in out;
Param : Real from Standard);
---C++: inline
---Purpose: Changes parameter on existing point
Parameter(me)
returns Real from Standard
---C++: inline

View File

@@ -15,6 +15,11 @@
#include <Standard_DomainError.hxx>
#include <gp_Vec2d.hxx>
inline void Blend_Point::SetParameter(const Standard_Real Param)
{
prm = Param;
}
inline const gp_Pnt& Blend_Point::PointOnS1 () const
{
return pt1;

View File

@@ -54,8 +54,9 @@ raises NotDone from StdFail
is
Create(Surf1,Surf2: TheSurface; Domain1,Domain2: TheTopolTool)
Create(Surf1,Surf2: TheSurface;
Domain1,Domain2: TheTopolTool;
HGuide : HElSpine from ChFiDS)
returns Walking from Blend;
@@ -67,7 +68,6 @@ is
Perform(me: in out; F : in out Function from Blend;
FInv : in out FuncInv from Blend;
HGuide : HElSpine from ChFiDS;
Pdep : Real from Standard;
Pmax : Real from Standard;
MaxStep : Real from Standard;
@@ -166,11 +166,22 @@ is
InternalPerform (me: in out;F : in out Function from Blend;
FInv : in out FuncInv from Blend;
HGuide : HElSpine from ChFiDS;
Bound : Real from Standard)
is static private;
CorrectExtremityOnOneRst (me; IndexOfRst : Integer from Standard;
theU : Real from Standard;
theV : Real from Standard;
theParam : Real from Standard;
thePntOnRst : Pnt from gp;
NewU : out Real from Standard;
NewV : out Real from Standard;
NewPoint : out Pnt from gp;
NewParam : out Real from Standard)
returns Boolean from Standard
is static private;
IsDone(me)
@@ -266,6 +277,10 @@ fields
domain2 : TheTopolTool;
recdomain1 : TheTopolTool;
recdomain2 : TheTopolTool;
hguide : HElSpine from ChFiDS;
ToCorrectOnRst1 : Boolean from Standard;
ToCorrectOnRst2 : Boolean from Standard;
CorrectedParam : Real from Standard;
tolesp : Real from Standard;
tolgui : Real from Standard;

View File

@@ -15,8 +15,10 @@
Blend_Walking::Blend_Walking(const TheSurface& Surf1,
const TheSurface& Surf2,
const Handle(TheTopolTool)& Domain1,
const Handle(TheTopolTool)& Domain2):
const Handle(TheTopolTool)& Domain2,
const Handle(ChFiDS_HElSpine)& HGuide):
sol(1,4),surf1(Surf1),surf2(Surf2),
ToCorrectOnRst1(Standard_False),ToCorrectOnRst2(Standard_False),
done(Standard_False),
clasonS1(Standard_True),clasonS2(Standard_True),
check2d(Standard_True),check(Standard_True),
@@ -26,7 +28,8 @@ Blend_Walking::Blend_Walking(const TheSurface& Surf1,
domain1 = Domain1;
domain2 = Domain2;
recdomain1 = Domain1;
recdomain2 = Domain2;
recdomain2 = Domain2;
hguide = HGuide;
}
void Blend_Walking::SetDomainsToRecadre(const Handle(TheTopolTool)& Domain1,
@@ -56,7 +59,6 @@ void Blend_Walking::AddSingularPoint(const Blend_Point& P)
void Blend_Walking::Perform(Blend_Function& Func,
Blend_FuncInv& FuncInv,
const Handle(ChFiDS_HElSpine)& HGuide,
const Standard_Real Pdep,
const Standard_Real Pmax,
const Standard_Real MaxStep,
@@ -135,6 +137,9 @@ void Blend_Walking::Perform(Blend_Function& Func,
nbcomputedsection = 1;
#endif
// Mettre a jour la ligne.
//Correct first parameter if needed
if (ToCorrectOnRst1 || ToCorrectOnRst2)
previousP.SetParameter(CorrectedParam);
line->Append(previousP);
if(doextremities){
@@ -155,7 +160,7 @@ void Blend_Walking::Perform(Blend_Function& Func,
}
}
InternalPerform(Func,FuncInv,HGuide,Pmax);
InternalPerform(Func,FuncInv,Pmax);
done = Standard_True;
}
@@ -255,6 +260,8 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False;
TheVertex Vtx1, Vtx2;
gp_Pnt2d p2d;
Standard_Real CorrectedU = 0., CorrectedV = 0.;
gp_Pnt CorrectedPnt;
Func.GetTolerance(tolerance, tolesp);
Func.GetBounds(infbound, supbound);
@@ -358,6 +365,10 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
ParSol(2) = p2d.Y();
ParSol(3) = solrst1(3);
ParSol(4) = solrst1(4);
gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,ParSol(1),ParSol(2));
if (CorrectExtremityOnOneRst(1, ParSol(3), ParSol(4), param, thePntOnRst,
CorrectedU,CorrectedV,CorrectedPnt,CorrectedParam))
ToCorrectOnRst1 = Standard_True;
}
else
{ //if (recad2) {
@@ -377,6 +388,10 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
ParSol(2) = solrst2(4);
ParSol(3) = p2d.X();
ParSol(4) = p2d.Y();
gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,ParSol(3),ParSol(4));
if (CorrectExtremityOnOneRst(2, ParSol(1), ParSol(2), param, thePntOnRst,
CorrectedU,CorrectedV,CorrectedPnt,CorrectedParam))
ToCorrectOnRst2 = Standard_True;
}
Psol = param;
@@ -387,26 +402,32 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
{
case Blend_OnRst1:
{
#ifdef OCCT_DEBUG
if (Blend_GettraceDRAWSECT())
{
Drawsect(surf1, surf2, sol, param, Func);
}
#endif
#ifdef OCCT_DEBUG
if (Blend_GettraceDRAWSECT())
{
Drawsect(surf1, surf2, sol, param, Func);
}
#endif
MakeExtremity(Ext1, Standard_True, Index1, solrst1(1), Isvtx1, Vtx1);
Ext2.SetValue(previousP.PointOnS2(), sol(3), sol(4), tolesp);
if (ToCorrectOnRst1)
Ext2.SetValue(CorrectedPnt, CorrectedU, CorrectedV, tolesp);
else
Ext2.SetValue(previousP.PointOnS2(), sol(3), sol(4), tolesp);
}
break;
case Blend_OnRst2:
{
#ifdef OCCT_DEBUG
if (Blend_GettraceDRAWSECT())
{
Drawsect(surf1, surf2, sol, param, Func);
}
#endif
Ext1.SetValue(previousP.PointOnS1(), sol(1), sol(2), tolesp);
#ifdef OCCT_DEBUG
if (Blend_GettraceDRAWSECT())
{
Drawsect(surf1, surf2, sol, param, Func);
}
#endif
if (ToCorrectOnRst2)
Ext1.SetValue(CorrectedPnt, CorrectedU, CorrectedV, tolesp);
else
Ext1.SetValue(previousP.PointOnS1(), sol(1), sol(2), tolesp);
MakeExtremity(Ext2, Standard_False, Index2, solrst2(1), Isvtx2, Vtx2);
}
break;
@@ -462,8 +483,7 @@ Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
previousP.ParametersOnS1(sol(1),sol(2));
previousP.ParametersOnS2(sol(3),sol(4));
Handle(ChFiDS_HElSpine) anHGuide;
InternalPerform(Func,FuncInv,anHGuide,P);
InternalPerform(Func,FuncInv,P);
return Standard_True;
}
@@ -504,8 +524,7 @@ Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
if(OnS1) clasonS1 = Standard_False;
else clasonS2 = Standard_False;
Handle(ChFiDS_HElSpine) anHGuide;
InternalPerform(Func,FuncInv,anHGuide,P);
InternalPerform(Func,FuncInv,P);
clasonS1 = Standard_True;
clasonS2 = Standard_True;
@@ -551,8 +570,7 @@ Standard_Boolean Blend_Walking::Complete(Blend_Function& Func,
previousP.ParametersOnS1(sol(1),sol(2));
previousP.ParametersOnS2(sol(3),sol(4));
Handle(ChFiDS_HElSpine) anHGuide;
InternalPerform(Func,FuncInv,anHGuide,Pmin);
InternalPerform(Func,FuncInv,Pmin);
iscomplete = Standard_True;
return Standard_True;

View File

@@ -13,6 +13,29 @@
// commercial license or contractual agreement.
#include <gce_MakePln.hxx>
#include <Extrema_ExtPS.hxx>
#include <Extrema_ExtPC.hxx>
static void RecadreIfPeriodic(Standard_Real& NewU,
Standard_Real& NewV,
const Standard_Real OldU,
const Standard_Real OldV,
const Standard_Real UPeriod,
const Standard_Real VPeriod)
{
if (UPeriod > 0.)
{
Standard_Real sign = (NewU < OldU)? 1 : -1;
while (Abs(NewU - OldU) > UPeriod/2)
NewU += sign * UPeriod;
}
if (VPeriod > 0.)
{
Standard_Real sign = (NewV < OldV)? 1 : -1;
while (Abs(NewV - OldV) > VPeriod/2)
NewV += sign * VPeriod;
}
}
static void evalpinit(math_Vector& parinit,
const Blend_Point& previousP,
@@ -67,7 +90,6 @@ static void evalpinit(math_Vector& parinit,
void Blend_Walking::InternalPerform(Blend_Function& Func,
Blend_FuncInv& FuncInv,
const Handle(ChFiDS_HElSpine)& HGuide,
const Standard_Real Bound)
{
@@ -263,55 +285,62 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
sol(3) = p2d.X();
sol(4) = p2d.Y();
Pnt2 = TheSurfaceTool::Value(surf2,sol(3),sol(4));
if (!HGuide.IsNull())
const Standard_Real TolProd = 1.e-5;
Standard_Real SavedParams [2];
Standard_Boolean SameDirs [2] = {Standard_False, Standard_False};
ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve();
SavedParams[0] = theElSpine.GetSavedFirstParameter();
SavedParams[1] = theElSpine.GetSavedLastParameter();
for (Standard_Integer ind = 0; ind < 2; ind++)
{
const Standard_Real TolProd = 1.e-5;
Standard_Real SavedParams [2];
Standard_Boolean SameDirs [2] = {Standard_False, Standard_False};
ChFiDS_ElSpine& theElSpine = HGuide->ChangeCurve();
SavedParams[0] = theElSpine.GetSavedFirstParameter();
SavedParams[1] = theElSpine.GetSavedLastParameter();
for (Standard_Integer ind = 0; ind < 2; ind++)
if (!Precision::IsInfinite(SavedParams[ind]))
{
if (!Precision::IsInfinite(SavedParams[ind]))
{
//Check the original first and last parameters of guide curve
//for equality to found parameter <param>:
//check equality of tangent to guide curve and
//normal to plane built on 3 points:
//point on guide curve and points on restrictions of adjacent
//surfaces.
gp_Pnt Pnt0;
gp_Vec Dir0;
HGuide->D1(SavedParams[ind], Pnt0, Dir0);
Standard_Real Length = Dir0.Magnitude();
if (Length <= gp::Resolution())
continue;
Dir0 /= Length;
gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2);
if (!PlaneBuilder.IsDone())
continue;
gp_Pln thePlane = PlaneBuilder.Value();
gp_Dir DirPlane = thePlane.Axis().Direction();
gp_Vec theProd = Dir0 ^ DirPlane;
Standard_Real ProdMod = theProd.Magnitude();
if (ProdMod <= TolProd)
SameDirs[ind] = Standard_True;
}
//Check the original first and last parameters of guide curve
//for equality to found parameter <param>:
//check equality of tangent to guide curve and
//normal to plane built on 3 points:
//point on guide curve and points on restrictions of adjacent
//surfaces.
gp_Pnt Pnt0;
gp_Vec Dir0;
hguide->D1(SavedParams[ind], Pnt0, Dir0);
Standard_Real Length = Dir0.Magnitude();
if (Length <= gp::Resolution())
continue;
Dir0 /= Length;
gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2);
if (!PlaneBuilder.IsDone())
continue;
gp_Pln thePlane = PlaneBuilder.Value();
gp_Dir DirPlane = thePlane.Axis().Direction();
gp_Vec theProd = Dir0 ^ DirPlane;
Standard_Real ProdMod = theProd.Magnitude();
if (ProdMod <= TolProd)
SameDirs[ind] = Standard_True;
}
Standard_Real theParam = Precision::Infinite();
//Choose the closest parameter
if (SameDirs[0] && SameDirs[1])
theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))?
SavedParams[0] : SavedParams[1];
else if (SameDirs[0])
theParam = SavedParams[0];
else if (SameDirs[1])
theParam = SavedParams[1];
if (!Precision::IsInfinite(theParam))
param = theParam;
}
Standard_Real theParam = Precision::Infinite();
//Choose the closest parameter
if (SameDirs[0] && SameDirs[1])
theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))?
SavedParams[0] : SavedParams[1];
else if (SameDirs[0])
theParam = SavedParams[0];
else if (SameDirs[1])
theParam = SavedParams[1];
Standard_Real NewU, NewV, NewParam;
gp_Pnt NewPnt;
Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, Pnt1,
NewU, NewV, NewPnt, NewParam);
if (Corrected)
{
if (Abs(param - NewParam) < Abs(param - theParam))
theParam = NewParam;
}
if (!Precision::IsInfinite(theParam))
param = theParam;
}
else if (recad1) {
// sol sur 1
@@ -328,6 +357,17 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
sol(2) = p2d.Y();
sol(3) = solrst1(3);
sol(4) = solrst1(4);
gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,sol(1),sol(2));
Standard_Real NewU, NewV, NewParam;
gp_Pnt NewPnt;
Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, thePntOnRst,
NewU, NewV, NewPnt, NewParam);
if (Corrected)
{
param = NewParam;
sol(3) = NewU;
sol(4) = NewV;
}
}
else if (recad2) {
//sol sur 2
@@ -345,6 +385,17 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
sol(2) = solrst2(4);
sol(3) = p2d.X();
sol(4) = p2d.Y();
gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,sol(3),sol(4));
Standard_Real NewU, NewV, NewParam;
gp_Pnt NewPnt;
Standard_Boolean Corrected = CorrectExtremityOnOneRst(2, sol(1), sol(2), param, thePntOnRst,
NewU, NewV, NewPnt, NewParam);
if (Corrected)
{
param = NewParam;
sol(1) = NewU;
sol(2) = NewV;
}
}
else {
State = Blend_OK;
@@ -610,3 +661,146 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
}
}
Standard_Boolean Blend_Walking::CorrectExtremityOnOneRst(const Standard_Integer IndexOfRst,
const Standard_Real theU,
const Standard_Real theV,
const Standard_Real theParam,
const gp_Pnt& thePntOnRst,
Standard_Real& NewU,
Standard_Real& NewV,
gp_Pnt& NewPoint,
Standard_Real& NewParam) const
{
const Standard_Real TolAng = 0.001; //bug OCC25701
ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve();
if (theElSpine.NbVertices() == 0)
return Standard_False;
Handle(TheTopolTool) DomainOfRst = (IndexOfRst == 1)? recdomain1 : recdomain2;
TheSurface SurfOfRst = (IndexOfRst == 1)? surf1 : surf2;
TheSurface AnotherSurf = (IndexOfRst == 1)? surf2 : surf1;
//Correct point on surface 2
//First we find right <param>
Standard_Real Ends [2];
Ends[0] = TheArcTool::FirstParameter(DomainOfRst->Value());
Ends[1] = TheArcTool::LastParameter(DomainOfRst->Value());
Standard_Real GlobalMinSqDist = Precision::Infinite();
Standard_Real ParamOnGuide = 0;
gp_Pnt PointOnGuide;
for (Standard_Integer k = 0; k < 2; k++)
{
gp_Pnt2d P2dOnEnd = TheArcTool::Value(DomainOfRst->Value(), Ends[k]);
gp_Pnt PntOnEnd = TheSurfaceTool::Value(SurfOfRst, P2dOnEnd.X(), P2dOnEnd.Y());
Extrema_ExtPC projoncurv(PntOnEnd, theElSpine);
if (!projoncurv.IsDone())
continue;
Standard_Real MinSqDist = Precision::Infinite();
Standard_Integer imin = 0;
for (Standard_Integer ind = 1; ind <= projoncurv.NbExt(); ind++)
{
Standard_Real aSqDist = projoncurv.SquareDistance(ind);
if (aSqDist < MinSqDist)
{
MinSqDist = aSqDist;
imin = ind;
}
}
if (MinSqDist < GlobalMinSqDist)
{
GlobalMinSqDist = MinSqDist;
ParamOnGuide = projoncurv.Point(imin).Parameter();
PointOnGuide = projoncurv.Point(imin).Value();
}
}
NewParam = ParamOnGuide;
if (hguide->IsPeriodic())
{
Standard_Real Period = hguide->Period();
Standard_Real sign = (NewParam < theParam)? 1 : -1;
while (Abs(NewParam - theParam) > Period/2)
NewParam += sign *Period;
}
//Second we find right point and tangent on guide
GlobalMinSqDist = Precision::Infinite();
gp_Ax1 theAx1;
for (Standard_Integer ind = 1; ind <= theElSpine.NbVertices(); ind++)
{
const gp_Ax1& anAx1 = theElSpine.VertexWithTangent(ind);
gp_Pnt aPnt = anAx1.Location();
Standard_Real aSqDist = PointOnGuide.SquareDistance(aPnt);
if (aSqDist < GlobalMinSqDist)
{
GlobalMinSqDist = aSqDist;
theAx1 = anAx1;
}
}
const gp_Pnt& Pnt0 = theAx1.Location();
const gp_Dir& Dir0 = theAx1.Direction();
//Check new point: is it real solution?
gp_Pnt OldPonGuide = hguide->Value(theParam);
gp_Pnt PntOnSurf2 = TheSurfaceTool::Value(AnotherSurf,theU,theV); //old point
gce_MakePln PlaneBuilder(thePntOnRst, OldPonGuide, PntOnSurf2);
if (!PlaneBuilder.IsDone())
return Standard_False;
gp_Pln OldPlane = PlaneBuilder.Value();
gp_Dir OldDir = OldPlane.Axis().Direction();
Standard_Real Angle = OldDir.Angle(Dir0);
if (Angle > M_PI/2)
Angle = M_PI - Angle;
if (Angle > TolAng)
return Standard_False;
///////////////////////////////////////
//Project the point(theU,theV) on the plane(Pnt0,Dir0)
gp_Vec aVec(Pnt0, PntOnSurf2);
gp_Vec aTranslation( (aVec.XYZ() * Dir0.XYZ()) * Dir0.XYZ() );
gp_Pnt PntOnPlane = PntOnSurf2.Translated(-aTranslation);
//Check new point again: does point on restriction belong to the plane?
PlaneBuilder = gce_MakePln(thePntOnRst, Pnt0, PntOnPlane);
if (!PlaneBuilder.IsDone())
return Standard_False;
gp_Pln NewPlane = PlaneBuilder.Value();
const gp_Dir& DirOfNewPlane = NewPlane.Axis().Direction();
Angle = Dir0.Angle(DirOfNewPlane);
if (Angle > M_PI/2)
Angle = M_PI - Angle;
if (Angle > TolAng)
return Standard_False;
////////////////////////////////////////////////////////////////////////
//Project the point <PntOnPlane> on the surface 2
Extrema_ExtPS projonsurf(PntOnPlane, AnotherSurf->Surface(),
Precision::PConfusion(), Precision::PConfusion(),
Extrema_ExtFlag_MIN);
if (projonsurf.IsDone())
{
Standard_Real MinSqDist = Precision::Infinite();
Standard_Integer imin = 0;
for (Standard_Integer ind = 1; ind <= projonsurf.NbExt(); ind++)
{
Standard_Real aSqDist = projonsurf.SquareDistance(ind);
if (aSqDist < MinSqDist)
{
MinSqDist = aSqDist;
imin = ind;
}
}
if (imin)
{
Extrema_POnSurf NewPOnSurf2 = projonsurf.Point(imin);
NewPoint = NewPOnSurf2.Value();
NewPOnSurf2.Parameter(NewU, NewV);
Standard_Real uperiod = (AnotherSurf->IsUPeriodic())? AnotherSurf->UPeriod() : 0.;
Standard_Real vperiod = (AnotherSurf->IsVPeriodic())? AnotherSurf->VPeriod() : 0.;
RecadreIfPeriodic(NewU, NewV, theU, theV,
uperiod, vperiod);
return Standard_True;
}
}
return Standard_False;
}