1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0027079: Bad approximation of intersection curves with variable curvature

1. Method Approx_ComputeLine::Perform is modified: now it contains also recursive calls after new line computation made by new method ApproxInt_MultiLine::MakeMLOneMorePoint.
    2. New method MakeMLOneMorePoint is added to ApproxInt_MultiLine: it builds new sub-line as a part of main line with new point added into the middle of the longest interval between existing points.
    3. Method ShapeConstruct_ProjectCurveOnSurface::ApproxPCurve is modified to avoid regressions: now it takes care of the set of initial points to be enough close to each other so that an interval between two adjacent points is less than half-period of the surface.
    4. Modification in ShapeConstruct_ProjectCurveOnSurface: correction of pcurves of edges which extremities are in the singularities of surface.
This commit is contained in:
jgv
2017-03-20 14:43:32 +03:00
committed by bugmaster
parent 6c060ff2c4
commit 2c26a53d85
29 changed files with 1626 additions and 460 deletions

View File

@@ -45,6 +45,7 @@ static Standard_Boolean mydebug = Standard_False;
#include <Draw.hxx>
#include <Draw_Appli.hxx>
#endif
static void DUMP(const MultiLine& Line)
{
Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
@@ -82,7 +83,6 @@ static void DUMP(const MultiLine& Line)
}
static void DUMP(const AppParCurves_MultiCurve& C) {
static Standard_Integer nbappel = 0;
Standard_Integer i;
@@ -123,9 +123,259 @@ static void DUMP(const AppParCurves_MultiCurve& C) {
#endif
}
#endif
static Standard_Boolean CheckMultiCurve(const AppParCurves_MultiCurve& theMultiCurve,
const MultiLine& theLine,
const Standard_Integer theIndfirst,
const Standard_Integer theIndlast,
Standard_Integer& theIndbad)
{
const Standard_Integer nbp3d = LineTool::NbP3d(theLine);
const Standard_Integer nbp2d = LineTool::NbP2d(theLine);
if (nbp3d > 1) //only simple cases are analysed
return Standard_True;
const Standard_Real MinScalProd = -0.9;
const Standard_Real SqTol3d = Precision::SquareConfusion();
theIndbad = 0;
Standard_Integer indbads [4];
indbads[1] = indbads[2] = indbads[3] = 0;
Standard_Integer NbCur = theMultiCurve.NbCurves();
Standard_Boolean LoopFound = Standard_False;
Standard_Integer aNbP3d = Max(nbp3d, 1);
Standard_Integer aNbP2d = Max(nbp2d, 1);
TColgp_Array1OfPnt tabP(1, aNbP3d);
TColgp_Array1OfPnt2d tabP2d(1, aNbP2d);
#ifdef DRAW
char* name = new char[100];
Standard_Integer nbbc = 1;
Standard_Integer indc = 1;
#endif
if (theMultiCurve.Dimension(1) == 3 /*myNbP3d == 1*/)
{
TColgp_Array1OfPnt aPoles(1, theMultiCurve.NbPoles());
theMultiCurve.Curve(1, aPoles);
#ifdef DRAW
Handle(Geom_Curve) theBezier = new Geom_BezierCurve(aPoles);
sprintf(name, "bc3d_%d_%d", indc, nbbc);
DrawTrSurf::Set(name, theBezier);
#endif
gp_Vec FirstVec, SecondVec;
Standard_Integer indp = 2;
while (indp <= aPoles.Upper())
{
FirstVec = gp_Vec(aPoles(1), aPoles(indp++));
Standard_Real aLength = FirstVec.Magnitude();
if (aLength > gp::Resolution())
{
FirstVec /= aLength;
break;
}
}
gp_Pnt MidPnt = aPoles(indp-1);
//for (Standard_Integer k = 3; k <= aPoles.Upper(); k++)
while (indp <= aPoles.Upper())
{
SecondVec = gp_Vec(MidPnt, aPoles(indp));
Standard_Real aLength = SecondVec.Magnitude();
if (aLength <= gp::Resolution())
{
indp++;
continue;
}
SecondVec /= aLength;
Standard_Real ScalProd = FirstVec * SecondVec;
if (ScalProd < MinScalProd)
{
#ifdef DRAW
cout<<"ScalProd("<<indp-2<<","<<indp-1<<")-("<<indp-1<<","<<indp<<") = "<<ScalProd<<endl;
#endif
LoopFound = Standard_True;
break;
}
FirstVec = SecondVec;
MidPnt = aPoles(indp);
indp++;
}
//Check: may be it is a real loop
if (LoopFound)
{
for (Standard_Integer FirstInd = theIndfirst;
FirstInd <= theIndlast - 2; FirstInd++)
{
LineTool::Value(theLine, FirstInd, tabP);
gp_Pnt FirstPnt = tabP(1);
for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
{
LineTool::Value(theLine, k, tabP);
gp_Pnt Pnt1 = tabP(1);
LineTool::Value(theLine, k+1, tabP);
gp_Pnt Pnt2 = tabP(1);
if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
{
LoopFound = Standard_False;
break;
}
gp_Vec Vec1(FirstPnt, Pnt1);
Vec1.Normalize();
gp_Vec Vec2(FirstPnt, Pnt2);
Vec2.Normalize();
Standard_Real ScalProd = Vec1 * Vec2;
if (ScalProd < MinScalProd)
{
LoopFound = Standard_False;
break;
}
}
if (LoopFound == Standard_False)
break;
}
}
if (LoopFound)
{
//search <indbad>
Standard_Real MaxSqDist = 0.;
for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
{
LineTool::Value(theLine, k-1, tabP);
gp_Pnt PrevPnt = tabP(1);
LineTool::Value(theLine, k, tabP);
gp_Pnt CurPnt = tabP(1);
Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
if (aSqDist > MaxSqDist)
{
MaxSqDist = aSqDist;
indbads[1] = k;
}
}
for (Standard_Integer indcur = 2; indcur <= NbCur; indcur++)
{
MaxSqDist = 0.;
for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
{
LineTool::Value(theLine, k-1, tabP2d);
gp_Pnt2d PrevPnt = tabP2d(indcur-1);
LineTool::Value(theLine, k, tabP2d);
gp_Pnt2d CurPnt = tabP2d(indcur-1);
Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
if (aSqDist > MaxSqDist)
{
MaxSqDist = aSqDist;
indbads[indcur] = k;
}
}
}
}
} //if (myNbP3d == 1)
else //2d case
{
TColgp_Array1OfPnt2d aPoles2d(1, theMultiCurve.NbPoles());
theMultiCurve.Curve(1, aPoles2d);
#ifdef DRAW
Handle(Geom2d_Curve) theBezier2d = new Geom2d_BezierCurve(aPoles2d);
sprintf(name, "bc2d_%d_%d", indc, nbbc);
DrawTrSurf::Set(name, theBezier2d);
#endif
gp_Vec2d FirstVec, SecondVec;
FirstVec = gp_Vec2d(aPoles2d(1), aPoles2d(2));
FirstVec.Normalize();
gp_Pnt2d MidPnt = aPoles2d(2);
for (Standard_Integer k = 3; k <= aPoles2d.Upper(); k++)
{
SecondVec = gp_Vec2d(MidPnt, aPoles2d(k));
SecondVec.Normalize();
Standard_Real ScalProd = FirstVec * SecondVec;
if (ScalProd < MinScalProd)
{
#ifdef DRAW
cout<<"ScalProd("<<k-2<<","<<k-1<<")-("<<k-1<<","<<k<<") = "<<ScalProd<<endl;
#endif
LoopFound = Standard_True;
break;
}
FirstVec = SecondVec;
MidPnt = aPoles2d(k);
}
//Check: may be it is a real loop
if (LoopFound)
{
for (Standard_Integer FirstInd = theIndfirst;
FirstInd <= theIndlast - 2; FirstInd++)
{
LineTool::Value(theLine, FirstInd, tabP2d);
gp_Pnt2d FirstPnt = tabP2d(1);
for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
{
LineTool::Value(theLine, k, tabP2d);
gp_Pnt2d Pnt1 = tabP2d(1);
LineTool::Value(theLine, k+1, tabP2d);
gp_Pnt2d Pnt2 = tabP2d(1);
if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
{
LoopFound = Standard_False;
break;
}
gp_Vec2d Vec1(FirstPnt, Pnt1);
Vec1.Normalize();
gp_Vec2d Vec2(FirstPnt, Pnt2);
Vec2.Normalize();
Standard_Real ScalProd = Vec1 * Vec2;
if (ScalProd < MinScalProd)
{
LoopFound = Standard_False;
break;
}
}
if (LoopFound == Standard_False)
break;
}
}
if (LoopFound)
{
//search <indbad>
for (Standard_Integer indcur = 1; indcur <= NbCur; indcur++)
{
Standard_Real MaxSqDist = 0.;
for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
{
LineTool::Value(theLine, k-1, tabP2d);
gp_Pnt2d PrevPnt = tabP2d(indcur);
LineTool::Value(theLine, k, tabP2d);
gp_Pnt2d CurPnt = tabP2d(indcur);
Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
if (aSqDist > MaxSqDist)
{
MaxSqDist = aSqDist;
indbads[indcur] = k;
}
}
}
}
}
//Define <indbad>
if (indbads[1] != 0 && indbads[2] != 0)
{
if (indbads[1] != indbads[2])
LoopFound = Standard_False;
else if (indbads[3] != 0 && indbads[1] != indbads[3])
LoopFound = Standard_False;
}
if (LoopFound)
theIndbad = indbads[1];
return (!LoopFound);
}
void Approx_ComputeLine::FirstTangencyVector(const MultiLine& Line,
const Standard_Integer index,
math_Vector& V) const
@@ -400,6 +650,7 @@ Approx_ComputeLine::Approx_ComputeLine
const Standard_Boolean cutting,
const Standard_Boolean Squares)
: myMultiLineNb (0),
myNbPlusOnePoint (0),
myIsClear (Standard_False)
{
myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
@@ -433,6 +684,7 @@ Approx_ComputeLine::Approx_ComputeLine
const Standard_Boolean cutting,
const Standard_Boolean Squares)
: myMultiLineNb (0),
myNbPlusOnePoint (0),
myIsClear (Standard_False)
{
myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
@@ -464,6 +716,7 @@ Approx_ComputeLine::Approx_ComputeLine
const Approx_ParametrizationType parametrization,
const Standard_Boolean Squares)
: myMultiLineNb (0),
myNbPlusOnePoint (0),
myIsClear (Standard_False)
{
myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
@@ -492,6 +745,7 @@ Approx_ComputeLine::Approx_ComputeLine
const Approx_ParametrizationType parametrization,
const Standard_Boolean Squares)
: myMultiLineNb (0),
myNbPlusOnePoint (0),
myIsClear (Standard_False)
{
myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
@@ -524,6 +778,7 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
Tolers3d.Clear();
Tolers2d.Clear();
myMultiLineNb = 0;
//myNbPlusOnePoint = 0;
}
else myIsClear = Standard_False;
@@ -558,7 +813,22 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
}
}
TheMultiCurve = AppParCurves_MultiCurve();
alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d);
MultiLine anOtherLine0;
Standard_Boolean isOtherLine0Made = Standard_False;
Standard_Integer indbad = 0;
alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d, indbad);
if (indbad != 0)
{
isOtherLine0Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine0);
}
if (isOtherLine0Made)
{
myIsClear = Standard_True;
//++myMultiLineNb;
myNbPlusOnePoint++;
Perform(anOtherLine0);
alldone = Standard_True;
}
if(!alldone && TheMultiCurve.NbCurves() > 0) {
#ifdef OCCT_DEBUG
if (mydebug) DUMP(TheMultiCurve);
@@ -566,10 +836,13 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
myMultiCurves.Append(TheMultiCurve);
Tolers3d.Append(currenttol3d);
Tolers2d.Append(currenttol2d);
Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, mylastpt);
for (i = myfirstpt; i <= mylastpt; i++) {
ThePar->SetValue(i, myParameters->Value(i));
}
Standard_Integer mylen = mylastpt-myfirstpt+1;
Standard_Integer myParLen = myParameters->Length();
Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
Handle(TColStd_HArray1OfReal) ThePar =
new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
for (i = 0; i < aLen; i++)
ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
myPar.Append(ThePar);
}
}
@@ -622,11 +895,9 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
// Appel recursif du decoupage:
GoUp = Standard_True;
MultiLine OtherLine =LineTool::MakeMLBetween(Line, myfirstpt,
mylastpt, nbp-1);
MultiLine anOtherLine1 = LineTool::MakeMLBetween(Line, myfirstpt, mylastpt, nbp-1);
Standard_Integer nbpdsotherligne = LineTool::FirstPoint(OtherLine)
-LineTool::LastPoint(OtherLine);
Standard_Integer nbpdsotherligne = LineTool::FirstPoint (anOtherLine1) - LineTool::LastPoint (anOtherLine1);
//-- Si MakeML a echoue on retourne une ligne vide
if ((nbpdsotherligne == 0) || myMultiLineNb >= 3)
@@ -644,7 +915,23 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
Par = Approx_IsoParametric;
Parameters(Line, myfirstpt, mylastpt, Param);
TheMultiCurve = AppParCurves_MultiCurve();
Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
MultiLine anOtherLine2;
Standard_Boolean isOtherLine2Made = Standard_False;
Standard_Integer indbad = 0;
Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
if (indbad != 0)
{
isOtherLine2Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine2);
}
if (isOtherLine2Made)
{
myIsClear = Standard_True;
//++myMultiLineNb;
myNbPlusOnePoint++;
Par = SavePar;
Perform(anOtherLine2);
Ok = Standard_True;
}
if (!Ok) {
Standard_Real tt3d = currenttol3d, tt2d = currenttol2d;
@@ -657,7 +944,21 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
Par = Approx_ChordLength;
Parameters(Line, myfirstpt, mylastpt, Param);
Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
isOtherLine2Made = Standard_False;
indbad = 0;
Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
if (indbad != 0)
{
isOtherLine2Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad, anOtherLine2);
}
if (isOtherLine2Made)
{
myIsClear = Standard_True;
//++myMultiLineNb;
myNbPlusOnePoint++;
Perform (anOtherLine2);
Ok = Standard_True;
}
if (!Ok && tt3d <= currenttol3d && tt2d <= currenttol2d) {
currenttol3d = tt3d; currenttol2d = tt2d;
@@ -666,6 +967,12 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
}
}
Par = SavePar;
if (myfirstpt == Thelastpt)
{
Finish = Standard_True;
alldone = Standard_True;
return;
}
oldlastpt = mylastpt;
if (!Ok) {
@@ -675,17 +982,40 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
return;
}
#ifdef OCCT_DEBUG
if (mydebug) DUMP(TheMultiCurve);
if (mydebug) DUMP(TheMultiCurve);
#endif
myMultiCurves.Append(TheMultiCurve);
Tolers3d.Append(currenttol3d);
Tolers2d.Append(currenttol2d);
Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, oldlastpt);
for (i = myfirstpt; i <= oldlastpt; i++) {
ThePar->SetValue(i, myParameters->Value(i));
}
myPar.Append(ThePar);
MultiLine anOtherLine3;
Standard_Boolean isOtherLine3Made = Standard_False;
Standard_Integer indbad2 = 0;
if (!CheckMultiCurve(TheMultiCurve, Line,
myfirstpt, mylastpt,
indbad2))
{
isOtherLine3Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad2, anOtherLine3);
}
if (isOtherLine3Made)
{
myIsClear = Standard_True;
//++myMultiLineNb;
myNbPlusOnePoint++;
Perform(anOtherLine3);
myfirstpt = mylastpt;
mylastpt = Thelastpt;
}
else
{
myMultiCurves.Append(TheMultiCurve);
Tolers3d.Append(currenttol3d);
Tolers2d.Append(currenttol2d);
Standard_Integer mylen = oldlastpt-myfirstpt+1;
Standard_Integer myParLen = myParameters->Length();
Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
Handle(TColStd_HArray1OfReal) ThePar =
new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
for (i = 0; i < aLen; i++)
ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
myPar.Append(ThePar);
}
}
myfirstpt = oldlastpt;
mylastpt = Thelastpt;
@@ -695,7 +1025,7 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
{
myIsClear = Standard_True;
++myMultiLineNb;
Perform(OtherLine);
Perform(anOtherLine1);
myfirstpt = mylastpt;
mylastpt = Thelastpt;
}
@@ -716,11 +1046,13 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
myMultiCurves.Append(TheMultiCurve);
Tolers3d.Append(currenttol3d);
Tolers2d.Append(currenttol2d);
Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(myfirstpt, oldlastpt);
for (i = myfirstpt; i <= oldlastpt; i++) {
ThePar->SetValue(i, myParameters->Value(i));
}
Standard_Integer mylen = oldlastpt-myfirstpt+1;
Standard_Integer myParLen = myParameters->Length();
Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
Handle(TColStd_HArray1OfReal) ThePar =
new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
for (i = 0; i < aLen; i++)
ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
myPar.Append(ThePar);
myfirstpt = oldlastpt;
@@ -776,8 +1108,28 @@ void Approx_ComputeLine::Perform(const MultiLine& Line)
}
TheMultiCurve = AppParCurves_MultiCurve();
Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d);
MultiLine anOtherLine4;
Standard_Boolean isOtherLine4Made = Standard_False;
Standard_Integer indbad = 0;
Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
if (indbad != 0)
{
isOtherLine4Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad, anOtherLine4);
}
if (isOtherLine4Made)
{
myIsClear = Standard_True;
//++myMultiLineNb;
myNbPlusOnePoint++;
Perform (anOtherLine4);
Ok = Standard_True;
}
if (myfirstpt == Thelastpt)
{
Finish = Standard_True;
alldone = Standard_True;
return;
}
}
}
}
@@ -886,9 +1238,10 @@ Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
const Standard_Integer lpt,
math_Vector& Para,
Standard_Real& TheTol3d,
Standard_Real& TheTol2d)
Standard_Real& TheTol2d,
Standard_Integer& indbad)
{
indbad = 0;
Standard_Integer deg, i;
Standard_Boolean mydone;
Standard_Real Fv;
@@ -947,20 +1300,30 @@ Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
// Stockage de la multicurve approximee.
tolreached = Standard_True;
#ifdef OCCT_DEBUG
if (mydebug) DUMP(mySCU);
if (mydebug) DUMP(mySCU);
#endif
myMultiCurves.Append(mySCU);
// Stockage des parametres de la partie de MultiLine approximee:
// A ameliorer !! (bq trop de recopies)
Handle(TColStd_HArray1OfReal) ThePar =
new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
for (i = Para.Lower(); i <= Para.Upper(); i++) {
ThePar->SetValue(i, Para(i));
}
myPar.Append(ThePar);
Tolers3d.Append(TheTol3d);
Tolers2d.Append(TheTol2d);
return Standard_True;
if (myNbPlusOnePoint != 0 &&
!CheckMultiCurve(mySCU, Line,
fpt, lpt,
indbad))
{
return Standard_False;
}
else
{
myMultiCurves.Append(mySCU);
// Stockage des parametres de la partie de MultiLine approximee:
// A ameliorer !! (bq trop de recopies)
Handle(TColStd_HArray1OfReal) ThePar =
new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
for (i = Para.Lower(); i <= Para.Upper(); i++) {
ThePar->SetValue(i, Para(i));
}
myPar.Append(ThePar);
Tolers3d.Append(TheTol3d);
Tolers2d.Append(TheTol2d);
return Standard_True;
}
}
}