1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0028102: Problem cutting a plate with several holes (670)

Algorithm of processing cases when point of splitting Walking-line is near to the boundary of the intersection domain but does not match this boundary has been improved.
This commit is contained in:
nbv 2018-01-19 18:07:06 +03:00 committed by apn
parent 93445088d8
commit 779d6bc6a5
3 changed files with 232 additions and 36 deletions

View File

@ -2415,6 +2415,109 @@ static Standard_Boolean SplitOnSegments(Handle(IntPatch_WLine)& WLine,
return result; return result;
} }
//=======================================================================
//function : IsPointOnBoundary
//purpose : Returns TRUE if point <theParam> matches <theBoundary +/- thePeriod>
// with given tolerance criterion.
// For not-periodic case, thePeriod must be equal to 0.0.
//=======================================================================
static Standard_Boolean IsPointOnBoundary(const Standard_Real theToler2D,
const Standard_Real theBoundary,
const Standard_Real thePeriod,
const Standard_Real theParam)
{
Standard_Real aDelta = Abs(theParam - theBoundary);
if (thePeriod != 0.0)
{
aDelta = fmod(aDelta, thePeriod);
// 0 <= aDelta < thePeriod
return ((aDelta < theToler2D) || ((thePeriod - aDelta) < theToler2D));
}
// Here, thePeriod == 0.0, aDelta > 0.0
return (aDelta < theToler2D);
}
//=======================================================================
//function : DetectOfBoundaryAchievement
//purpose : Can change values of theNewLine (by adding the computed point on boundary,
// which parameter will be adjusted) and theIsOnBoundary variables.
//=======================================================================
static void DetectOfBoundaryAchievement(const Handle(Adaptor3d_HSurface)& theQSurf, // quadric
const Standard_Boolean theIsReversed,
const Handle(IntSurf_LineOn2S)& theSourceLine,
const Standard_Integer thePointIndex,
const Standard_Real theToler2D,
Handle(IntSurf_LineOn2S)& theNewLine,
Standard_Boolean& theIsOnBoundary)
{
const Standard_Real aUPeriod = theQSurf->IsUPeriodic() ? theQSurf->UPeriod() : 0.0,
aVPeriod = theQSurf->IsVPeriodic() ? theQSurf->VPeriod() : 0.0;
const Standard_Real aUf = theQSurf->FirstUParameter(),
aUl = theQSurf->LastUParameter(),
aVf = theQSurf->FirstVParameter(),
aVl = theQSurf->LastVParameter();
const IntSurf_PntOn2S &aPPrev = theSourceLine->Value(thePointIndex - 1),
&aPCurr = theSourceLine->Value(thePointIndex);
Standard_Real aUPrev, aVPrev, aUCurr, aVCurr;
if (theIsReversed)
{
aPPrev.ParametersOnS2(aUPrev, aVPrev); // S2 - quadric, set U,V by Pnt3D
aPCurr.ParametersOnS2(aUCurr, aVCurr); // S2 - quadric, set U,V by Pnt3D
}
else
{
aPPrev.ParametersOnS1(aUPrev, aVPrev); // S1 - quadric, set U,V by Pnt3D
aPCurr.ParametersOnS1(aUCurr, aVCurr); // S1 - quadric, set U,V by Pnt3D
}
// Ignore cases when the WLine goes along the surface boundary completely.
if (IsPointOnBoundary(theToler2D, aUf, aUPeriod, aUCurr) &&
!IsPointOnBoundary(theToler2D, aUf, aUPeriod, aUPrev))
{
theIsOnBoundary = Standard_True;
}
else if (IsPointOnBoundary(theToler2D, aUl, aUPeriod, aUCurr) &&
!IsPointOnBoundary(theToler2D, aUl, aUPeriod, aUPrev))
{
theIsOnBoundary = Standard_True;
}
else if (IsPointOnBoundary(theToler2D, aVf, aVPeriod, aVCurr) &&
!IsPointOnBoundary(theToler2D, aVf, aVPeriod, aVPrev))
{
theIsOnBoundary = Standard_True;
}
else if (IsPointOnBoundary(theToler2D, aVl, aVPeriod, aVCurr) &&
!IsPointOnBoundary(theToler2D, aVl, aVPeriod, aVPrev))
{
theIsOnBoundary = Standard_True;
}
if (theIsOnBoundary)
{
// Adjust, to avoid bad jumping of the WLine.
const Standard_Real aDu = (aUPrev - aUCurr);
const Standard_Real aDv = (aVPrev - aVCurr);
if (aUPeriod > 0.0 && (2.0*Abs(aDu) > aUPeriod))
{
aUCurr += Sign(aUPeriod, aDu);
}
if (aVPeriod > 0.0 && (2.0*Abs(aDv) > aVPeriod))
{
aVCurr += Sign(aVPeriod, aDv);
}
IntSurf_PntOn2S aPoint = aPCurr;
aPoint.SetValue(!theIsReversed, aUCurr, aVCurr);
theNewLine->Add(aPoint);
}
}
//======================================================================= //=======================================================================
//function : DecomposeResult //function : DecomposeResult
//purpose : Split <theLine> in the places where it passes through seam edge //purpose : Split <theLine> in the places where it passes through seam edge
@ -2499,7 +2602,6 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
// reset variables // reset variables
flNextLine = Standard_False; flNextLine = Standard_False;
Standard_Boolean isDecomposited = Standard_False; Standard_Boolean isDecomposited = Standard_False;
Standard_Real U1 = 0., U2 = 0., V1 = 0., V2 = 0.;
Handle(IntSurf_LineOn2S) sline = new IntSurf_LineOn2S(); Handle(IntSurf_LineOn2S) sline = new IntSurf_LineOn2S();
@ -2546,17 +2648,32 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
continue; continue;
} }
if(IsReversed) //Check whether the current point is on the boundary of theQSurf.
{ //If that is TRUE then the Walking-line will be decomposed in this point.
aSSLine->Value(k).ParametersOnS2(U1,V1); // S2 - quadric, set U,V by Pnt3D //However, this boundary is not singular-point (like seam or pole of sphere).
} //Therefore, its processing will be simplified.
else Standard_Boolean isOnBoundary = Standard_False;
{
aSSLine->Value(k).ParametersOnS1(U1,V1); // S1 - quadric, set U,V by Pnt3D // Values of sline and isOnBoundary can be changed by this function
} DetectOfBoundaryAchievement(theQSurf, IsReversed, aSSLine,
k, aTOL2D, sline, isOnBoundary);
aPrePointExist = IsSeamOrPole(theQSurf, aSSLine, IsReversed, k - 1, aDeltaUmax); aPrePointExist = IsSeamOrPole(theQSurf, aSSLine, IsReversed, k - 1, aDeltaUmax);
if (isOnBoundary && (aPrePointExist != IntPatch_SPntPoleSeamU))
{
// If the considered point is on seam then its UV-parameters
// are defined to within the surface period. Therefore, we can
// trust already computed parameters of this point.
// However, if this point (which is on the surface boundary) is
// a sphere pole or cone apex then its (point's) parameters
// have to be recomputed in the code below
// (see IntPatch_SpecialPoints::AddSingularPole() method).
// E.g. see "bugs modalg_6 bug26684_2" test case.
aPrePointExist = IntPatch_SPntNone;
}
if (aPrePointExist != IntPatch_SPntNone) if (aPrePointExist != IntPatch_SPntNone)
{ {
aBindex = k; aBindex = k;
@ -2601,14 +2718,14 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
anInfBound(1, 3), aSupBound(1, 3); anInfBound(1, 3), aSupBound(1, 3);
//Parameters on parametric surface //Parameters on parametric surface
Standard_Real aUp = 0.0, aVp = 0.0; Standard_Real aUp = 0.0, aVp = 0.0, aUq = 0.0, aVq = 0.0;
if(IsReversed) if(IsReversed)
{ {
aSSLine->Value(k).ParametersOnS1(aUp, aVp); aSSLine->Value(k).Parameters(aUp, aVp, aUq, aVq);
} }
else else
{ {
aSSLine->Value(k).ParametersOnS2(aUp, aVp); aSSLine->Value(k).Parameters(aUq, aVq, aUp, aVp);
} }
aTol(1) = thePSurf->UResolution(theArcTol); aTol(1) = thePSurf->UResolution(theArcTol);
@ -2616,7 +2733,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
aTol(3) = theQSurf->UResolution(theArcTol); aTol(3) = theQSurf->UResolution(theArcTol);
aStartPoint(1) = 0.5*(aU0 + aUp); aStartPoint(1) = 0.5*(aU0 + aUp);
aStartPoint(2) = 0.5*(aV0 + aVp); aStartPoint(2) = 0.5*(aV0 + aVp);
aStartPoint(3) = 0.5*(aUQuadRef + U1); aStartPoint(3) = 0.5*(aUQuadRef + aUq);
anInfBound(1) = thePSurf->FirstUParameter(); anInfBound(1) = thePSurf->FirstUParameter();
anInfBound(2) = thePSurf->FirstVParameter(); anInfBound(2) = thePSurf->FirstVParameter();
anInfBound(3) = theQSurf->FirstUParameter(); anInfBound(3) = theQSurf->FirstUParameter();
@ -2642,6 +2759,15 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
{ {
aPrePointExist = IntPatch_SPntPole; aPrePointExist = IntPatch_SPntPole;
aLastType = IntPatch_SPntPole; aLastType = IntPatch_SPntPole;
if (isOnBoundary)
{
// It is necessary to replace earlier added point on
// the surface boundary with the pole. For that,
// here we delete excess point. New point will be added later.
isOnBoundary = Standard_False;
sline->RemovePoint(sline->NbPoints());
}
aCompareTol2D = -1.0; aCompareTol2D = -1.0;
} //if(IntPatch_AddSpecialPoints::AddSingularPole(...)) } //if(IntPatch_AddSpecialPoints::AddSingularPole(...))
else else
@ -2673,14 +2799,14 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
anInfBound(1, 3), aSupBound(1, 3); anInfBound(1, 3), aSupBound(1, 3);
//Parameters on parametric surface //Parameters on parametric surface
Standard_Real aUp = 0.0, aVp = 0.0; Standard_Real aUp = 0.0, aVp = 0.0, aUq = 0.0, aVq = 0.0;
if (IsReversed) if (IsReversed)
{ {
aSSLine->Value(k).ParametersOnS1(aUp, aVp); aSSLine->Value(k).Parameters(aUp, aVp, aUq, aVq);
} }
else else
{ {
aSSLine->Value(k).ParametersOnS2(aUp, aVp); aSSLine->Value(k).Parameters(aUq, aVq, aUp, aVp);
} }
aTol(1) = thePSurf->UResolution(theArcTol); aTol(1) = thePSurf->UResolution(theArcTol);
@ -2688,7 +2814,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
aTol(3) = theQSurf->VResolution(theArcTol); aTol(3) = theQSurf->VResolution(theArcTol);
aStartPoint(1) = 0.5*(aU0 + aUp); aStartPoint(1) = 0.5*(aU0 + aUp);
aStartPoint(2) = 0.5*(aV0 + aVp); aStartPoint(2) = 0.5*(aV0 + aVp);
aStartPoint(3) = 0.5*(aVQuadRef + V1); aStartPoint(3) = 0.5*(aVQuadRef + aVq);
anInfBound(1) = thePSurf->FirstUParameter(); anInfBound(1) = thePSurf->FirstUParameter();
anInfBound(2) = thePSurf->FirstVParameter(); anInfBound(2) = thePSurf->FirstVParameter();
anInfBound(3) = theQSurf->FirstVParameter(); anInfBound(3) = theQSurf->FirstVParameter();
@ -2704,28 +2830,46 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
if(!aNewPoint.IsSame(aRefPt, aCompareTol3D, aCompareTol2D)) if(!aNewPoint.IsSame(aRefPt, aCompareTol3D, aCompareTol2D))
{ {
if (isOnBoundary)
break;
sline->Add(aNewPoint); sline->Add(aNewPoint);
aPrePointExist = aLastType; aPrePointExist = aLastType;
PrePoint = aNewPoint; PrePoint = aNewPoint;
} }
else else
{ {
if(sline->NbPoints() == 1) if (isOnBoundary || (sline->NbPoints() == 1))
{ {
//FIRST point of the sline is the pole of the quadric. //FIRST point of the sline is the pole of the quadric.
//Therefore, there is no point in decomposition. //Therefore, there is no point in decomposition.
// If the considered point is on surface boundary then
// it is already marked as vertex. So, decomposition is
// not required, too.
PrePoint = aRefPt; PrePoint = aRefPt;
aPrePointExist = aLastType; aPrePointExist = isOnBoundary ? IntPatch_SPntNone : aLastType;
} }
} }
//// ////
break; break;
} //if(Abs(U1-AnU1) > aDeltaUmax) } //if (aPrePointExist != IntPatch_SPntNone) cond.
sline->Add(aSSLine->Value(k));
PrePoint = aSSLine->Value(k); PrePoint = aSSLine->Value(k);
if (isOnBoundary)
{
aBindex = k;
isDecomposited = Standard_True;
aPrePointExist = IntPatch_SPntNone;
break;
}
else
{
sline->Add(aSSLine->Value(k));
}
} //for(Standard_Integer k = aFindex; k <= aLindex; k++) } //for(Standard_Integer k = aFindex; k <= aLindex; k++)
//Creation of new line as part of existing theLine. //Creation of new line as part of existing theLine.
@ -2780,12 +2924,12 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
new IntPatch_WLine(sline,Standard_False, new IntPatch_WLine(sline,Standard_False,
theLine->TransitionOnS1(),theLine->TransitionOnS2()); theLine->TransitionOnS1(),theLine->TransitionOnS2());
Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
gp_Pnt aSPnt(sline->Value(1).Value()); gp_Pnt aSPnt(sline->Value(1).Value());
sline->Value(1).ParametersOnS1(U1,V1); sline->Value(1).Parameters(aU1, aV1, aU2, aV2);
sline->Value(1).ParametersOnS2(U2,V2);
aTPntF.SetValue(aSPnt,theArcTol,Standard_False); aTPntF.SetValue(aSPnt,theArcTol,Standard_False);
aTPntF.SetParameters(U1,V1,U2,V2); aTPntF.SetParameters(aU1, aV1, aU2, aV2);
aTPntF.SetParameter(1.); aTPntF.SetParameter(1.0);
wline->AddVertex(aTPntF); wline->AddVertex(aTPntF);
wline->SetFirstPoint(1); wline->SetFirstPoint(1);
@ -2795,10 +2939,9 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
} }
aSPnt = sline->Value(sline->NbPoints()).Value(); aSPnt = sline->Value(sline->NbPoints()).Value();
sline->Value(sline->NbPoints()).ParametersOnS1(U1,V1); sline->Value(sline->NbPoints()).Parameters(aU1, aV1, aU2, aV2);
sline->Value(sline->NbPoints()).ParametersOnS2(U2,V2);
aTPntL.SetValue(aSPnt,theArcTol,Standard_False); aTPntL.SetValue(aSPnt,theArcTol,Standard_False);
aTPntL.SetParameters(U1,V1,U2,V2); aTPntL.SetParameters(aU1, aV1, aU2, aV2);
aTPntL.SetParameter(sline->NbPoints()); aTPntL.SetParameter(sline->NbPoints());
wline->AddVertex(aTPntL); wline->AddVertex(aTPntL);
wline->SetLastPoint(wline->NbVertex()); wline->SetLastPoint(wline->NbVertex());
@ -2856,24 +2999,25 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
for(Standard_Integer aFLIndex = 0; aFLIndex < 2; aFLIndex++) for(Standard_Integer aFLIndex = 0; aFLIndex < 2; aFLIndex++)
{ {
Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
if(aFLIndex == 0) if(aFLIndex == 0)
{ {
aRFirst.Parameters(U1, V1, U2, V2); aRFirst.Parameters(aU1, aV1, aU2, aV2);
aSPnt.SetXYZ(aRFirst.Value().XYZ()); aSPnt.SetXYZ(aRFirst.Value().XYZ());
} }
else else
{ {
aRLast.Parameters(U1, V1, U2, V2); aRLast.Parameters(aU1, aV1, aU2, aV2);
aSPnt.SetXYZ(aRLast.Value().XYZ()); aSPnt.SetXYZ(aRLast.Value().XYZ());
} }
if(IsReversed) if(IsReversed)
{ {
aPSurf.SetCoord(U1, V1); aPSurf.SetCoord(aU1, aV1);
} }
else else
{ {
aPSurf.SetCoord(U2, V2); aPSurf.SetCoord(aU2, aV2);
} }
Standard_Real aPar = ElCLib::Parameter(aLin, aPSurf); Standard_Real aPar = ElCLib::Parameter(aLin, aPSurf);
@ -2891,7 +3035,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
aTPnt.SetParameter(aPar); aTPnt.SetParameter(aPar);
aTPnt.SetValue(aSPnt,theArcTol,Standard_False); aTPnt.SetValue(aSPnt,theArcTol,Standard_False);
aTPnt.SetParameters(U1, V1, U2, V2); aTPnt.SetParameters(aU1, aV1, aU2, aV2);
aRLine->AddVertex(aTPnt); aRLine->AddVertex(aTPnt);
} }

View File

@ -0,0 +1,28 @@
puts "========"
puts "OCC28102"
puts "========"
puts ""
#######################################################
# Problem cutting a plate with several holes (670)
#######################################################
restore [locate_data_file bug28102_plate.brep] pl0
restore [locate_data_file bug28102_holes.brep] hl
# Incomplete section
bsection result pl0 hl
regexp {nb alone Vertices : ([-0-9.+eE]+)} [checksection result] full nbv
if { $nbv != 0 } { puts "Error : Section is incorrect" }
checknbshapes result -vertex 268 -edge 268
checkprops result -l 11.5694
regexp {Tolerance MAX=([-0-9.+eE]+)} [tolerance result] full toler
if {$toler > 1.0e-5} {
puts "Error: Tolerance of section is too large"
}
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@ -0,0 +1,24 @@
puts "========"
puts "OCC28102"
puts "========"
puts ""
#######################################################
# Problem cutting a plate with several holes (670)
#######################################################
restore [locate_data_file bug28102_plate.brep] pl0
restore [locate_data_file bug28102_holes.brep] hl
bclearobjects
bcleartools
baddobjects pl0
baddtools hl
bfillds
bbop result 2
checknbshapes result -vertex 274 -edge 275 -face 2 -shell 1
checkprops result -s 13.3806
checkview -display result -2d -path ${imagedir}/${test_image}.png