1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0027135: Incorrect result of the normal projection algorithm

New check for possible local traps was added to build correct projection cache.
test case added.
This commit is contained in:
aml
2016-02-11 14:42:04 +03:00
parent b3b55601fb
commit 7c53747c3e
3 changed files with 114 additions and 41 deletions

View File

@@ -192,6 +192,9 @@ is
raises
OutOfRange from Standard
is private;
UpdateTripleByTrapCriteria(me; thePoint : out Pnt from gp)
is private;
MaxDistance(me; Index: Integer)
---Purpose: returns the maximum distance between

View File

@@ -14,20 +14,33 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <ProjLib_CompProjectedCurve.ixx>
#include <ProjLib_HCompProjectedCurve.hxx>
#include <gp_XY.hxx>
#include <gp_Mat2d.hxx>
#include <Extrema_ExtPS.hxx>
#include <Precision.hxx>
#include <Adaptor2d_HCurve2d.hxx>
#include <Adaptor3d_HCurve.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <Extrema_ExtCS.hxx>
#include <TColgp_HSequenceOfPnt.hxx>
#include <Extrema_ExtPS.hxx>
#include <Extrema_GenLocateExtPS.hxx>
#include <Extrema_POnSurf.hxx>
#include <Extrema_POnCurv.hxx>
#include <ProjLib_PrjResolve.hxx>
#include <Extrema_POnSurf.hxx>
#include <GeomAbs_CurveType.hxx>
#include <GeomLib.hxx>
#include <gp_Mat2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec2d.hxx>
#include <gp_XY.hxx>
#include <Precision.hxx>
#include <ProjLib_CompProjectedCurve.hxx>
#include <ProjLib_HCompProjectedCurve.hxx>
#include <ProjLib_PrjResolve.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_NoSuchObject.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_OutOfRange.hxx>
#include <TColgp_HSequenceOfPnt.hxx>
#include <ProjLib_HSequenceOfHSequenceOfPnt.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColStd_HArray1OfBoolean.hxx>
#define FuncTol 1.e-10
@@ -614,8 +627,8 @@ void ProjLib_CompProjectedCurve::Init()
//Basic loop
while(t <= LastU)
{
//Search for the begining a new continuous part
//To avoid infinite computation in some difficult cases
// Search for the beginning of a new continuous part
// to avoid infinite computation in some difficult cases.
new_part = Standard_False;
if(t > FirstU && Abs(t-prevDeb) <= Precision::PConfusion()) SameDeb=Standard_True;
while(t <= LastU && !new_part && !FromLastU && !SameDeb)
@@ -627,7 +640,7 @@ void ProjLib_CompProjectedCurve::Init()
gp_Pnt CPoint;
Standard_Real ParT,ParU,ParV;
// Search an initpoint in the list of Extrema Curve-Surface
// Search an initial point in the list of Extrema Curve-Surface
if(Nend != 0 && !CExt.IsParallel())
{
for (i=1;i<=Nend;i++)
@@ -725,9 +738,9 @@ void ProjLib_CompProjectedCurve::Init()
{
//Search for exact boundary point
Tol = Min(myTolU, myTolV);
gp_Vec2d D;
d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
Tol /= Max(Abs(D.X()), Abs(D.Y()));
gp_Vec2d aD;
d1(Triple.X(), Triple.Y(), Triple.Z(), aD, myCurve, mySurface);
Tol /= Max(Abs(aD.X()), Abs(aD.Y()));
if(!ExactBound(Triple, t - Step, Tol,
myTolU, myTolV, myCurve, mySurface))
@@ -851,27 +864,13 @@ void ProjLib_CompProjectedCurve::Init()
prevStep = Step;
Triple = gp_Pnt(t, aPrjPS.Solution().X(), aPrjPS.Solution().Y());
if (mySurface->GetType() == GeomAbs_SurfaceOfRevolution &&
(Abs (Triple.Z() - mySurface->FirstVParameter()) < Precision::Confusion() ||
Abs (Triple.Z() - mySurface->LastVParameter() ) < Precision::Confusion() ))
{
// Go out from possible attraktor.
Standard_Real U,V;
InitialPoint(myCurve->Value(t), t, myCurve, mySurface, myTolU, myTolV, U, V);
if (Abs (Abs(U - Triple.Y()) - mySurface->UPeriod()) < Precision::Confusion())
{
// Handle period jump.
U = Triple.Y();
}
Triple.SetY(U);
Triple.SetZ(V);
}
// Check local traps.
UpdateTripleByTrapCriteria(Triple);
if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
mySequence->Value(myNbCurves)->Append(Triple);
if (t == LastU) {t = LastU + 1; break;}//return;
if (t == LastU) {t = LastU + 1; break;}//return;
//Computation of WalkStep
d2CurvOnSurf(Triple.X(), Triple.Y(), Triple.Z(), D1, D2, myCurve, mySurface);
MagnD1 = D1.Magnitude();
@@ -889,7 +888,7 @@ void ProjLib_CompProjectedCurve::Init()
}
}
}
// Sequence postproceeding
// Sequence post-proceeding.
Standard_Integer j;
// 1. Removing poor parts
@@ -921,11 +920,11 @@ void ProjLib_CompProjectedCurve::Init()
for(i = 1; i <= myNbCurves; i++)
for(j = 1; j <= mySequence->Value(i)->Length(); j++)
{
gp_Pnt POnC, POnS, Triple;
gp_Pnt POnC, POnS, aTriple;
Standard_Real Distance;
Triple = mySequence->Value(i)->Value(j);
myCurve->D0(Triple.X(), POnC);
mySurface->D0(Triple.Y(), Triple.Z(), POnS);
aTriple = mySequence->Value(i)->Value(j);
myCurve->D0(aTriple.X(), POnC);
mySurface->D0(aTriple.Y(), aTriple.Z(), POnS);
Distance = POnC.Distance(POnS);
if (myMaxDistance->Value(i) < Distance)
myMaxDistance->ChangeValue(i) = Distance;
@@ -1235,12 +1234,12 @@ void ProjLib_CompProjectedCurve::D0(const Standard_Real U,gp_Pnt2d& P) const
Extrema_ExtPS aExtPS(thePoint, mySurface->Surface(), myTolU, myTolV);
if (aExtPS.IsDone() && aExtPS.NbExt())
{
Standard_Integer i, Nend, imin = 1;
Standard_Integer k, Nend, imin = 1;
// Search for the nearest solution which is also a normal projection
Nend = aExtPS.NbExt();
for(i = 2; i <= Nend; i++)
if (aExtPS.SquareDistance(i) < aExtPS.SquareDistance(imin))
imin = i;
for(k = 2; k <= Nend; k++)
if (aExtPS.SquareDistance(k) < aExtPS.SquareDistance(imin))
imin = k;
const Extrema_POnSurf& POnS = aExtPS.Point(imin);
Standard_Real ParU,ParV;
POnS.Parameter(ParU, ParV);
@@ -1612,3 +1611,51 @@ GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const
{
return GeomAbs_OtherCurve;
}
//=======================================================================
//function : UpdateTripleByTrapCriteria
//purpose :
//=======================================================================
void ProjLib_CompProjectedCurve::UpdateTripleByTrapCriteria(gp_Pnt &thePoint) const
{
Standard_Boolean isProblemsPossible = Standard_False;
// Check possible traps cases:
// 25892 bug.
if (mySurface->GetType() == GeomAbs_SurfaceOfRevolution &&
(Abs (thePoint.Z() - mySurface->FirstVParameter()) < Precision::PConfusion() ||
Abs (thePoint.Z() - mySurface->LastVParameter() ) < Precision::PConfusion() ))
{
isProblemsPossible = Standard_True;
}
// 27135 bug. Trap on degenerated edge.
if (mySurface->GetType() == GeomAbs_Sphere &&
(Abs (thePoint.Z() - mySurface->FirstVParameter()) < Precision::PConfusion() ||
Abs (thePoint.Z() - mySurface->LastVParameter() ) < Precision::PConfusion() ||
Abs (thePoint.Y() - mySurface->FirstUParameter()) < Precision::PConfusion() ||
Abs (thePoint.Y() - mySurface->LastUParameter() ) < Precision::PConfusion() ))
{
isProblemsPossible = Standard_True;
}
if (!isProblemsPossible)
return;
Standard_Real U,V;
InitialPoint(myCurve->Value(thePoint.X()), thePoint.X(), myCurve, mySurface, myTolU, myTolV, U, V);
// Restore original position in case of period jump.
if (mySurface->IsUPeriodic() &&
Abs (Abs(U - thePoint.Y()) - mySurface->UPeriod()) < Precision::PConfusion())
{
U = thePoint.Y();
}
if (mySurface->IsVPeriodic() &&
Abs (Abs(V - thePoint.Z()) - mySurface->VPeriod()) < Precision::PConfusion())
{
V = thePoint.Z();
}
thePoint.SetY(U);
thePoint.SetZ(V);
}

View File

@@ -0,0 +1,23 @@
puts "================"
puts "0027135"
puts "================"
puts ""
##############################################################
# Incorrect result of the normal projection algorithm
# Degenerated edge in result
##############################################################
restore [locate_data_file bug27135.brep] aShape
explode aShape
nproject result aShape_1 aShape_2
# Result length check.
checkprops result -l 5.74501
# Visual check.
donly result
smallview
fit
display aShape_2
checkview -screenshot -2d -path ${imagedir}/${test_image}.png