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

0023914: Intersection algorithm produced too many intersection points

Method IntWalk_PWalking::CalculateStepData(...) has been implemented in order to compute the step in parametric space.

Relation between the step of 3D intersection curve and local curvature is described in

   A Practical Algorithm for Surface/Surface Intersection.
    Ling Huang Xinxiong Zhu (School of Mechanical Engineering & Automation, Beijing University of Aeronautics & Astronautics,
    Beijing, 100083)
This commit is contained in:
nbv
2016-01-21 09:40:46 +03:00
parent e085d8a60e
commit bd47f9dff5
4 changed files with 283 additions and 34 deletions

View File

@@ -2341,13 +2341,13 @@ void IntPatch_PrmPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
//Try to extend the intersection line to boundary, if it is possibly
Standard_Boolean hasBeenAdded = PW.PutToBoundary(Surf1, Surf2);
const Standard_Integer aMinNbPoints = 40;
if(iPWNbPoints < aMinNbPoints)
{
hasBeenAdded =
PW.SeekAdditionalPoints(Surf1, Surf2, aMinNbPoints) || hasBeenAdded;
iPWNbPoints = PW.NbPoints();
}
//const Standard_Integer aMinNbPoints = 40;
//if(iPWNbPoints < aMinNbPoints)
//{
// hasBeenAdded =
// PW.SeekAdditionalPoints(Surf1, Surf2, aMinNbPoints) || hasBeenAdded;
// iPWNbPoints = PW.NbPoints();
//}
RejectLine = Standard_False;
Point3dDebut = PW.Value(1).Value();
@@ -2581,11 +2581,11 @@ void IntPatch_PrmPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
{
if(PW.NbPoints()>2)
{
const Standard_Integer aMinNbPoints = 40;
if(PW.NbPoints() < aMinNbPoints)
{
PW.SeekAdditionalPoints(Surf1, Surf2, aMinNbPoints);
}
//const Standard_Integer aMinNbPoints = 40;
//if(PW.NbPoints() < aMinNbPoints)
//{
// PW.SeekAdditionalPoints(Surf1, Surf2, aMinNbPoints);
//}
//-----------------------------------------------
//-- Verification a posteriori :

View File

@@ -819,6 +819,11 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
Standard_Integer LevelOfIterWithoutAppend = -1;
//
const Standard_Real aStepMax[4] = { 0.1*(u1max - u1min),
0.1*(v1max - v1min),
0.1*(u2max - u2min),
0.1*(v2max - v2min)};
const Standard_Real aTol[4] = { Epsilon(u1max - u1min),
Epsilon(v1max - v1min),
Epsilon(u2max - u2min),
@@ -854,15 +859,37 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
//
//--ofv.begin
Standard_Real aIncKey, aEps, dP1, dP2, dP3, dP4;
//
dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
dP3 = sensCheminement * pasuv[2] * previousd2.X() /f;
dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
//
aIncKey=5.*(Standard_Real)IncKey;
aEps=1.e-7;
const Standard_Real aEps = Precision::Confusion();
Standard_Real dP1, dP2, dP3, dP4;
if((Status == IntWalk_OK) && CalculateStepData(Param, aStepMax))
{
#ifdef INTWALK_PWALKING_DEBUG
printf("+++++++ The steps have been recomputed by ADAPTIVE algorith. New value:\n"
" dU1 = %10.20f;\n dV1 = %10.20f;\n dU2 = %10.20f;\n dV2 = %10.20f. -------\n", pasuv[0], pasuv[1], pasuv[2], pasuv[3]);
#endif
dP1 = dP2 = dP3 = dP4 = 1.0;
}
else
{//
#ifdef INTWALK_PWALKING_DEBUG
printf("+++++++ The steps have been kept as PREVIOUS:\n"
" dU1 = %10.20f;\n dV1 = %10.20f;\n dU2 = %10.20f;\n dV2 = %10.20f. -------\n", pasuv[0], pasuv[1], pasuv[2], pasuv[3]);
#endif
dP1 = previousd1.X() /f;
dP2 = previousd1.Y() /f;
dP3 = previousd2.X() /f;
dP4 = previousd2.Y() /f;
}
dP1 *= (sensCheminement * pasuv[0]);
dP2 *= (sensCheminement * pasuv[1]);
dP3 *= (sensCheminement * pasuv[2]);
dP4 *= (sensCheminement * pasuv[3]);
const Standard_Real aIncKey = 5.*(Standard_Real)IncKey;
if(ChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < aEps)
{
dP1 *= aIncKey;
@@ -882,12 +909,48 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
{
dP4 *= aIncKey;
}
//--ofv.end
//
Param(1) += dP1;
Param(2) += dP2;
Param(3) += dP3;
Param(4) += dP4;
//
//if (Param(1) < UFirst1)
//{
// Param(1) = UFirst1;
//}
//if (ULast1 < Param(1))
//{
// Param(1) = ULast1;
//}
//if (Param(2) < VFirst1)
//{
// Param(2) = VFirst1;
//}
//if (VLast1 < Param(2))
//{
// Param(2) = ULast1;
//}
////
//if (Param(3) < UFirst2)
//{
// Param(3) = UFirst2;
//}
//if (ULast2 < Param(3))
//{
// Param(3) = ULast2;
//}
//if (Param(4) < VFirst2)
//{
// Param(4) = VFirst2;
//}
//if (VLast2 < Param(4))
//{
// Param(4) = ULast2;
//}
//==========================
SvParam[0]=Param(1);
SvParam[1]=Param(2);
@@ -1298,6 +1361,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
if(RejectIndex >= RejectIndexMAX)
{
Arrive = Standard_True;
break;
}
@@ -1385,6 +1449,7 @@ void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
if(RejectIndex >= RejectIndexMAX)
{
Arrive = Standard_True;
break;
}
@@ -3250,3 +3315,194 @@ TestArret(const Standard_Boolean DejaReparti,
}
}
//=======================================================================
//function : CalculateStepData
//purpose : Computes new step (in UV-coordinates) which depends on
// the local curvature of the intersection line.
// If the step has been computed successfuly the method
// returns TRUE.
//=======================================================================
Standard_Boolean IntWalk_PWalking::CalculateStepData(const TColStd_Array1OfReal& theParams,
const Standard_Real theArrMaxStep[])
{
//return Standard_False;
const Standard_Real aCoefStepMin = 100.0;
//sqrt(z*(2-z))*(1-z)/(1-2*z*(2-z)), when z = 0.01 maximal relative error while
//approximation the curve by circle
const Standard_Real aCoef = 0.125;
//As same as in approximation (see ApproxInt_ImpPrmSvSurfaces::Compute(...))
const Standard_Real aNullValue = Precision::Approximation()*
Precision::Approximation();
const Handle(Adaptor3d_HSurface) &aSurf1 = myIntersectionOn2S.Function().AuxillarSurface1(),
&aSurf2 = myIntersectionOn2S.Function().AuxillarSurface2();
if((aSurf1->UContinuity() < GeomAbs_C2) || (aSurf2->VContinuity() < GeomAbs_C2))
{
return Standard_False;
}
if((aSurf2->UContinuity() < GeomAbs_C2) || (aSurf2->VContinuity() < GeomAbs_C2))
{
return Standard_False;
}
//if(aSurf1->IsUPeriodic() || aSurf1->IsVPeriodic())
// return Standard_False;
//if(aSurf2->IsUPeriodic() || aSurf2->IsVPeriodic())
// return Standard_False;
gp_Pnt aPt;
gp_Vec aDU1, aDV1, aDUU1, aDUV1, aDVV1;
gp_Vec aDU2, aDV2, aDUU2, aDUV2, aDVV2;
aSurf1->D2(theParams(1), theParams(2), aPt, aDU1, aDV1, aDUU1, aDVV1, aDUV1);
aSurf2->D2(theParams(3), theParams(4), aPt, aDU2, aDV2, aDUU2, aDVV2, aDUV2);
#ifdef INTWALK_PWALKING_DEBUG
int aTestID = 0;
Standard_Real anExpectedSqRad = -1.0;
switch(aTestID)
{
case 1:
//Intersection between two spherical surfaces: O1(0.0, 0.0, 0.0), R1 = 3
//and O2(5.0, 0.0, 0.0), R2 = 5.0.
//Considered point has coordinates: (0.9, 0.0, 0.3*sqrt(91.0)).
aDU1.SetCoord(0.00000000000000000, 0.90000000000000002, 0.00000000000000000);
aDV1.SetCoord(-2.8618176042508372, 0.00000000000000000, 0.90000000000000002);
aDUU1.SetCoord(-0.90000000000000002, 0.00000000000000000, 0.00000000000000000);
aDUV1.SetCoord(0.00000000000000000, -2.8618176042508372, 0.00000000000000000);
aDVV1.SetCoord(-0.90000000000000002, 0.00000000000000000, -2.8618176042508372);
aDU2.SetCoord(0.00000000000000000, -4.0999999999999996, 0.00000000000000000);
aDV2.SetCoord(-2.8618176042508372, 0.00000000000000000, -4.0999999999999996);
aDUU2.SetCoord(4.0999999999999996, 0.00000000000000000, 0.00000000000000000);
aDUV2.SetCoord(0.00000000000000000, -2.8618176042508372, 0.00000000000000000);
aDVV2.SetCoord(4.0999999999999996, 0.00000000000000000, -2.8618176042508372);
anExpectedSqRad = 819.0/100.0;
break;
case 2:
//Intersection between spherical surfaces: O1(0.0, 0.0, 0.0), R1 = 10
//and the plane 3*x+4*y+z=26.
//Considered point has coordinates: (-1.68, 5.76, 8.0).
aDU1.SetCoord(-5.76, -1.68, 0.0);
aDV1.SetCoord(2.24, -7.68, 6.0);
aDUU1.SetCoord(1.68, -5.76, 0.0);
aDUV1.SetCoord(7.68, 2.24, 0.0);
aDVV1.SetCoord(1.68, -5.76, -8.0);
aDU2.SetCoord(1.0, 0.0, -3.0);
aDV2.SetCoord(0.0, 1.0, -4.0);
aDUU2.SetCoord(0.0, 0.0, 0.0);
aDUV2.SetCoord(0.0, 0.0, 0.0);
aDVV2.SetCoord(0.0, 0.0, 0.0);
anExpectedSqRad = 74.0;
break;
default:
aTestID = 0;
break;
}
#endif
const gp_Vec aN1(aDU1.Crossed(aDV1)), aN2(aDU2.Crossed(aDV2));
//Tangent vactor to the intersection curve
const gp_Vec aCTan(aN1.Crossed(aN2));
const Standard_Real aSqMagnFDer = aCTan.SquareMagnitude();
if(aSqMagnFDer < aNullValue)
return Standard_False;
Standard_Real aDuS1 = 0.0, aDvS1 = 0.0, aDuS2 = 0.0, aDvS2 = 1.0;
{
//This algorithm is described in NonSingularProcessing() function
//in ApproxInt_ImpPrmSvSurfaces.gxx file
Standard_Real aSqNMagn = aN1.SquareMagnitude();
gp_Vec aTgU(aCTan.Crossed(aDU1)), aTgV(aCTan.Crossed(aDV1));
Standard_Real aDeltaU = aTgV.SquareMagnitude()/aSqNMagn;
Standard_Real aDeltaV = aTgU.SquareMagnitude()/aSqNMagn;
aDuS1 = Sign(sqrt(aDeltaU), aTgV.Dot(aN1));
aDvS1 = -Sign(sqrt(aDeltaV), aTgU.Dot(aN1));
aSqNMagn = aN2.SquareMagnitude();
aTgU.SetXYZ(aCTan.Crossed(aDU2).XYZ());
aTgV.SetXYZ(aCTan.Crossed(aDV2).XYZ());
aDeltaU = aTgV.SquareMagnitude()/aSqNMagn;
aDeltaV = aTgU.SquareMagnitude()/aSqNMagn;
aDuS2 = Sign(sqrt(aDeltaU), aTgV.Dot(aN2));
aDvS2 = -Sign(sqrt(aDeltaV), aTgU.Dot(aN2));
}
//According to "Marching along surface/surface intersection curves with an adaptive step length"
//by Tz.E.Stoyagov (http://www.sciencedirect.com/science/article/pii/016783969290046R)
//we obtain the system:
// {A*a+B*b=F1
// {B*a+C*b=F2
//where a and b should be found.
//After that, 2nd intersection curve derivative can be computed as
// r''(t)=a*N1+b*N2.
const Standard_Real aA = aN1.Dot(aN1), aB = aN1.Dot(aN2), aC = aN2.Dot(aN2);
const Standard_Real aDetSyst = aB*aB - aA*aC;
if(Abs(aDetSyst) < aNullValue)
{//Indetermined system solution
return Standard_False;
}
const Standard_Real aF1 = aDuS1*aDuS1*aDUU1.Dot(aN1) + 2.0*aDuS1*aDvS1*aDUV1.Dot(aN1) + aDvS1*aDvS1*aDVV1.Dot(aN1);
const Standard_Real aF2 = aDuS2*aDuS2*aDUU2.Dot(aN2) + 2.0*aDuS2*aDvS2*aDUV2.Dot(aN2) + aDvS2*aDvS2*aDVV2.Dot(aN2);
//Principal normal to the intersection curve
const gp_Vec aCNorm((aF1*aC-aF2*aB)/aDetSyst*aN1 + (aA*aF2-aF1*aB)/aDetSyst*aN2);
const Standard_Real aSqMagnSDer = aCNorm.CrossSquareMagnitude(aCTan);
if(aSqMagnSDer < aNullValue)
{//Intersection curve has null curvature in observed point
return Standard_False;
}
#ifdef INTWALK_PWALKING_DEBUG
if(aTestID)
{
//square of curvature radius
const Standard_Real aFactSqRad = aSqMagnFDer*aSqMagnFDer*aSqMagnFDer/aSqMagnSDer;
if(Abs(aFactSqRad - anExpectedSqRad) < Precision::Confusion())
{
printf("OK: Curvature radius is equal to expected (%5.10g)", anExpectedSqRad);
}
else
{
printf("Error: Curvature radius is not equal to expected: %5.10g != %5.10g", aFactSqRad, anExpectedSqRad);
}
return Standard_False;
}
#endif
//Current step-system ([aDuS1 aDvS1 aDuS2 aDvS2]) provides the length of the
//intersection curve tangent to be equal to Lc=sqrt(aSqMagnFDer).
//We need in tangent length to be equal to Ln=aCoef*sqrt((aSqMagnFDer^3)/aSqMagnSDer).
//For that, new step-system step-system should be (Ln/Lc)*[aDuS1 aDvS1 aDuS2 aDvS2].
//(Ln/Lc)
const Standard_Real aRatio = aCoef*aSqMagnFDer/sqrt(aSqMagnSDer);
pasuv[0] = Min(Abs(aDuS1*aRatio), theArrMaxStep[0]);
pasuv[1] = Min(Abs(aDvS1*aRatio), theArrMaxStep[1]);
pasuv[2] = Min(Abs(aDuS2*aRatio), theArrMaxStep[2]);
pasuv[3] = Min(Abs(aDvS2*aRatio), theArrMaxStep[3]);
pasuv[0] = Max(pasuv[0], aCoefStepMin*ResoU1);
pasuv[1] = Max(pasuv[1], aCoefStepMin*ResoV1);
pasuv[2] = Max(pasuv[2], aCoefStepMin*ResoU2);
pasuv[3] = Max(pasuv[3], aCoefStepMin*ResoV2);
return Standard_True;
}

View File

@@ -142,6 +142,7 @@ public:
protected:
Standard_EXPORT Standard_Boolean CalculateStepData(const TColStd_Array1OfReal& theParams, const Standard_Real theArrMaxStep[]);

View File

@@ -62,22 +62,14 @@ inline const gp_Dir& IntWalk_PWalking::TangentAtLine
return tgdir;
}
#define REGLAGE 0
inline void IntWalk_PWalking::AddAPoint(Handle(IntSurf_LineOn2S)& theLine,
const IntSurf_PntOn2S& POn2S) {
#if REGLAGE
Standard_Integer n=theLine->NbPoints();
if(n) {
gp_Vec V(POn2S.Value(),theLine->Value(n).Value());
#ifdef INTWALK_PWALKING_DEBUG
const gp_Pnt& aP = POn2S.Value();
Standard_Real u1,v1,u2,v2;
Standard_Real U1,V1,U2,V2;
POn2S.Parameters(u1,v1,u2,v2);
theLine->Value(n).Parameters(U1,V1,U2,V2);
printf("\n%3d: (%10.5g)(%+12.5g %+12.5g %+12.5g) (%+12.5g %+12.5g) (%+12.5g %+12.5g)",n,
V.Magnitude(),V.X(),V.Y(),V.Z(),U1-u1,V1-v1,U2-u2,V2-v2);
fflush(stdout);
}
printf("Added point: (%+10.20f %+10.20f %+10.20f) (%+10.20f %+10.20f) "
"(%+10.20f %+10.20f)\n", aP.X(), aP.Y(), aP.Z(), u1, v1, u2, v2);
#endif
theLine->Add(POn2S);
}