1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-08 18:40:55 +03:00

0027302: Invalid curves number in intersection result

1. In frame of the fix for  issue, we have obtained several prolonged curves, which have common point(s). Fix for this issue joins these curves if it is possible.

2. ElCLib::InPeriod(...) method has been improved. Now it has become more faster (in general cases) and more reliable (in frame of  FLT_OVERFLOW and DIVISION_BY_ZERO cases processing).

Creation of test case for issue 
Test case tests\bugs\modalg_6\bug27282_2 has been adjusted in accordance with its new behavior.
This commit is contained in:
nbv 2016-03-29 16:38:53 +03:00 committed by bugmaster
parent 8b9a309b48
commit b8f67cc236
11 changed files with 645 additions and 278 deletions

@ -48,20 +48,25 @@ static Standard_Real PIPI = M_PI + M_PI;
//=======================================================================
//function : InPeriod
//purpose :
//purpose : Value theULast is never returned.
//=======================================================================
Standard_Real ElCLib::InPeriod(const Standard_Real U,
const Standard_Real UFirst,
const Standard_Real ULast)
Standard_Real ElCLib::InPeriod(const Standard_Real theU,
const Standard_Real theUFirst,
const Standard_Real theULast)
{
Standard_Real u = U, period = ULast - UFirst;
Standard_Real Eps = Epsilon(period);
if( Precision::IsInfinite(theU) ||
Precision::IsInfinite(theUFirst) ||
Precision::IsInfinite(theULast))
{//In order to avoid FLT_Overflow exception
return theU;
}
while (Eps < (UFirst-u)) u += period;
while (Eps > (ULast -u)) u -= period;
if ( u < UFirst) u = UFirst;
return u;
const Standard_Real aPeriod = theULast - theUFirst;
if(aPeriod < Epsilon(theULast))
return theU;
return Max(theUFirst, theU + aPeriod*Ceiling((theUFirst-theU)/aPeriod));
}
//=======================================================================

@ -1442,12 +1442,34 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the
if(isQuadSet)
{
Bnd_Box2d aBx1, aBx2;
const Standard_Real aU1F = theS1->FirstUParameter(),
aU1L = theS1->LastUParameter(),
aV1F = theS1->FirstVParameter(),
aV1L = theS1->LastVParameter(),
aU2F = theS2->FirstUParameter(),
aU2L = theS2->LastUParameter(),
aV2F = theS2->FirstVParameter(),
aV2L = theS2->LastVParameter();
aBx1.Add(gp_Pnt2d(aU1F, aV1F));
aBx1.Add(gp_Pnt2d(aU1L, aV1F));
aBx1.Add(gp_Pnt2d(aU1L, aV1L));
aBx1.Add(gp_Pnt2d(aU1F, aV1L));
aBx2.Add(gp_Pnt2d(aU2F, aV2F));
aBx2.Add(gp_Pnt2d(aU2L, aV2F));
aBx2.Add(gp_Pnt2d(aU2L, aV2L));
aBx2.Add(gp_Pnt2d(aU2F, aV2L));
aBx1.Enlarge(Precision::PConfusion());
aBx2.Enlarge(Precision::PConfusion());
IntPatch_WLineTool::
ExtendTwoWlinesToEachOther(slin, Quad1, Quad2, TolTang,
theS1->IsUPeriodic()? theS1->UPeriod() : 0.0,
theS2->IsUPeriodic()? theS2->UPeriod() : 0.0,
theS1->IsVPeriodic()? theS1->VPeriod() : 0.0,
theS2->IsVPeriodic()? theS2->VPeriod() : 0.0);
theS2->IsVPeriodic()? theS2->VPeriod() : 0.0,
aBx1, aBx2);
}
for (Standard_Integer i = 1; i <= interii.NbPnts(); i++)

@ -45,8 +45,12 @@ class IntPatch_PointLine : public IntPatch_Line
public:
//! Adds a vertex in the list.
Standard_EXPORT virtual void AddVertex (const IntPatch_Point& Pnt) = 0;
//! Adds a vertex in the list. If theIsPrepend == TRUE the new
//! vertex will be added before the first element of vertices sequence.
//! Otherwise, to the end of the sequence
Standard_EXPORT virtual
void AddVertex (const IntPatch_Point& Pnt,
const Standard_Boolean theIsPrepend = Standard_False) = 0;
//! Returns the number of intersection points.
Standard_EXPORT virtual Standard_Integer NbPnts() const = 0;

@ -58,8 +58,11 @@ public:
//! when the transitions are Undecided.
Standard_EXPORT IntPatch_RLine(const Standard_Boolean Tang);
//! To add a vertex in the list.
virtual void AddVertex (const IntPatch_Point& Pnt) Standard_OVERRIDE;
//! Adds a vertex in the list. If theIsPrepend == TRUE the new
//! vertex will be added before the first element of vertices sequence.
//! Otherwise, to the end of the sequence
virtual void AddVertex (const IntPatch_Point& Pnt,
const Standard_Boolean theIsPrepend = Standard_False) Standard_OVERRIDE;
//! Replaces the element of range Index in the list
//! of points.

@ -32,9 +32,13 @@ inline const Handle(Adaptor2d_HCurve2d)& IntPatch_RLine::ArcOnS2() const
//-- Il faut mettre cet include ici , car l include fait un define Handle(Adaptor2d_HCurve2d) ...
//-- et en fin de fichier un undef Handle(Adaptor2d_HCurve2d) ...
inline void IntPatch_RLine::AddVertex (const IntPatch_Point& Pnt)
inline void IntPatch_RLine::AddVertex (const IntPatch_Point& thePnt,
const Standard_Boolean theIsPrepend)
{
svtx.Append(Pnt);
if(theIsPrepend)
svtx.Prepend(thePnt);
else
svtx.Append(thePnt);
}
inline void IntPatch_RLine::Replace (const Standard_Integer Index,

@ -62,8 +62,11 @@ public:
//! transitions are Undecided.
Standard_EXPORT IntPatch_WLine(const Handle(IntSurf_LineOn2S)& Line, const Standard_Boolean Tang);
//! Adds a vertex in the list.
virtual void AddVertex (const IntPatch_Point& Pnt) Standard_OVERRIDE;
//! Adds a vertex in the list. If theIsPrepend == TRUE the new
//! vertex will be added before the first element of vertices sequence.
//! Otherwise, to the end of the sequence
virtual void AddVertex (const IntPatch_Point& Pnt,
const Standard_Boolean theIsPrepend = Standard_False) Standard_OVERRIDE;
//! Set the Point of index <Index> in the LineOn2S
Standard_EXPORT void SetPoint (const Standard_Integer Index, const IntPatch_Point& Pnt);

@ -19,9 +19,13 @@
#include <IntPatch_Point.hxx>
inline void IntPatch_WLine::AddVertex (const IntPatch_Point& Pnt)
inline void IntPatch_WLine::AddVertex (const IntPatch_Point& thePnt,
const Standard_Boolean theIsPrepend)
{
svtx.Append(Pnt);
if(theIsPrepend)
svtx.Prepend(thePnt);
else
svtx.Append(thePnt);
}
inline void IntPatch_WLine::Replace (const Standard_Integer Index,

@ -15,6 +15,19 @@
#include <Adaptor3d_HSurface.hxx>
#include <Adaptor3d_TopolTool.hxx>
#include <ElCLib.hxx>
//Bit-mask is used for information about
//the operation made in
//IntPatch_WLineTool::ExtendTwoWlinesToEachOther() method.
enum
{
IntPatchWT_EnAll = 0x00,
IntPatchWT_DisLastLast = 0x01,
IntPatchWT_DisLastFirst = 0x02,
IntPatchWT_DisFirstLast = 0x04,
IntPatchWT_DisFirstFirst = 0x08
};
//=======================================================================
//function : MinMax
@ -458,23 +471,24 @@ static Handle(IntPatch_WLine)
}
//=======================================================================
//function : IsSeam
//purpose : Returns:
// 0 - if interval [theU1, theU2] does not intersect the "seam-edge"
// or if "seam-edge" do not exist;
// 1 - if interval (theU1, theU2) intersect the "seam-edge".
// 2 - if theU1 or/and theU2 lie ON the "seam-edge"
//function : IsOnPeriod
//purpose : Checks, if [theU1, theU2] intersects the period-value
// (k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...).
//
// Returns:
// 0 - if interval [theU1, theU2] does not intersect the "period-value"
// or if thePeriod == 0.0;
// 1 - if interval (theU1, theU2) intersect the "period-value".
// 2 - if theU1 or/and theU2 lie ON the "period-value"
//
//ATTENTION!!!
// If (theU1 == theU2) then this function will return only both 0 or 2.
//
// Static subfunction in IsSeamOrBound.
//=======================================================================
static Standard_Integer IsSeam( const Standard_Real theU1,
static Standard_Integer IsOnPeriod(const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Real thePeriod)
{
if(IsEqual(thePeriod, 0.0))
if(thePeriod < RealSmall())
return 0;
//If interval [theU1, theU2] intersect seam-edge then there exists an integer
@ -590,16 +604,16 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
return Standard_True;
}
if(IsSeam(aU11, aU21, theU1Period))
if(IsOnPeriod(aU11, aU21, theU1Period))
return Standard_True;
if(IsSeam(aV11, aV21, theV1Period))
if(IsOnPeriod(aV11, aV21, theV1Period))
return Standard_True;
if(IsSeam(aU12, aU22, theU2Period))
if(IsOnPeriod(aU12, aU22, theU2Period))
return Standard_True;
if(IsSeam(aV12, aV22, theV2Period))
if(IsOnPeriod(aV12, aV22, theV2Period))
return Standard_True;
/*
@ -634,16 +648,16 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
return Standard_True;
if(IsSeam(aU1, aU1, theU1Period))
if(IsOnPeriod(aU1, aU1, theU1Period))
return Standard_True;
if(IsSeam(aU2, aU2, theU2Period))
if(IsOnPeriod(aU2, aU2, theU2Period))
return Standard_True;
if(IsSeam(aV1, aV1, theV1Period))
if(IsOnPeriod(aV1, aV1, theV1Period))
return Standard_True;
if(IsSeam(aV2, aV2, theV2Period))
if(IsOnPeriod(aV2, aV2, theV2Period))
return Standard_True;
return Standard_False;
@ -712,22 +726,42 @@ static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
//purpose : Adds thePOn2S to the begin of theWline
//=======================================================================
static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
const IntSurf_PntOn2S &thePOn2S)
const IntSurf_PntOn2S& theAddedPt)
{
theWline->Curve()->InsertBefore(1, thePOn2S);
IntPatch_Point &aVert = theWline->ChangeVertex(1);
Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
thePOn2S.Parameters(aU1, aV1, aU2, aV2);
theAddedPt.Parameters(aU1, aV1, aU2, aV2);
if(theAddedPt.IsSame(theWline->Point(1), Precision::Confusion()))
{
theWline->Curve()->Value(1, theAddedPt);
for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
{
IntPatch_Point &aVert = theWline->ChangeVertex(i);
if(aVert.ParameterOnLine() != 1)
break;
aVert.SetParameters(aU1, aV1, aU2, aV2);
aVert.SetValue(thePOn2S.Value());
aVert.SetValue(theAddedPt.Value());
}
for(Standard_Integer i = 2; i <= theWline->NbVertex(); i++)
return;
}
theWline->Curve()->InsertBefore(1, theAddedPt);
for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
{
IntPatch_Point &aV = theWline->ChangeVertex(i);
aV.SetParameter(aV.ParameterOnLine()+1);
IntPatch_Point &aVert = theWline->ChangeVertex(i);
if(aVert.ParameterOnLine() == 1)
{
aVert.SetParameters(aU1, aV1, aU2, aV2);
aVert.SetValue(theAddedPt.Value());
}
else
{
aVert.SetParameter(aVert.ParameterOnLine()+1);
}
}
}
@ -736,19 +770,422 @@ static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
//purpose : Adds thePOn2S to the end of theWline
//=======================================================================
static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
const IntSurf_PntOn2S &thePOn2S)
const IntSurf_PntOn2S& theAddedPt)
{
theWline->Curve()->Add(thePOn2S);
IntPatch_Point &aVert = theWline->ChangeVertex(theWline->NbVertex());
Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
thePOn2S.Parameters(aU1, aV1, aU2, aV2);
theAddedPt.Parameters(aU1, aV1, aU2, aV2);
const Standard_Integer aNbPnts = theWline->NbPnts();
if(theAddedPt.IsSame(theWline->Point(aNbPnts), Precision::Confusion()))
{
theWline->Curve()->Value(aNbPnts, theAddedPt);
}
else
{
theWline->Curve()->Add(theAddedPt);
}
for(Standard_Integer i = theWline->NbVertex(); i >= 1; i--)
{
IntPatch_Point &aVert = theWline->ChangeVertex(i);
if(aVert.ParameterOnLine() != aNbPnts)
break;
aVert.SetParameters(aU1, aV1, aU2, aV2);
aVert.SetValue(thePOn2S.Value());
aVert.SetValue(theAddedPt.Value());
aVert.SetParameter(theWline->NbPnts());
}
}
//=========================================================================
// function: IsOutOfDomain
// purpose : Checks, if 2D-representation of thePOn2S is in surfaces domain,
// defined by bounding-boxes theBoxS1 and theBoxS2
//=========================================================================
static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const IntSurf_PntOn2S &thePOn2S,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period)
{
Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0;
Standard_Real aU2min = 0.0, aU2max = 0.0, aV2min = 0.0, aV2max = 0.0;
thePOn2S.Parameters(aU1, aV1, aU2, aV2);
theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theU1Period);
aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theV1Period);
aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theU2Period);
aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theV2Period);
return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
}
//=======================================================================
//function : CheckArguments
//purpose : Check if extending is possible
// (see IntPatch_WLineTool::ExtendTwoWlinesToEachOther)
//=======================================================================
static Standard_Boolean CheckArguments(const IntSurf_Quadric& theS1,
const IntSurf_Quadric& theS2,
const IntSurf_PntOn2S& thePtWL1,
const IntSurf_PntOn2S& thePtWL2,
IntSurf_PntOn2S& theNewPoint,
const gp_Vec& theVec1,
const gp_Vec& theVec2,
const gp_Vec& theVec3,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const Standard_Real theToler3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period)
{
const Standard_Real aMaxAngle = M_PI/6; //30 degree
const Standard_Real aSqToler = theToler3D*theToler3D;
if(theVec3.SquareMagnitude() <= aSqToler)
{
return Standard_False;
}
if((theVec1.Angle(theVec2) > aMaxAngle) ||
(theVec1.Angle(theVec3) > aMaxAngle) ||
(theVec2.Angle(theVec3) > aMaxAngle))
{
return Standard_False;
}
const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0;
theBoxS1.Get(aU1, aV1, aU2, aV2);
const Standard_Real aU1f = aU1, aV1f = aV1;
theBoxS2.Get(aU1, aV1, aU2, aV2);
const Standard_Real aU2f = aU1, aV2f = aV1;
if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period,
aU1, aV1, aU2, aV2))
{
return Standard_False;
}
theNewPoint.SetValue(aPmid, aU1, aV1, aU2, aV2);
if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint,
theU1Period, theU2Period,
theV1Period, theV2Period))
{
return Standard_False;
}
Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
thePtWL1.Parameters(aU11, aV11, aU21, aV21);
thePtWL2.Parameters(aU12, aV12, aU22, aV22);
if(IsOnPeriod(aU11 - aU1f, aU12 - aU1f, theU1Period) ||
IsOnPeriod(aV11 - aV1f, aV12 - aV1f, theV1Period) ||
IsOnPeriod(aU21 - aU2f, aU22 - aU2f, theU2Period) ||
IsOnPeriod(aV21 - aV2f, aV22 - aV2f, theV2Period))
{
return Standard_False;
}
return Standard_True;
}
//=======================================================================
//function : ExtendTwoWLFirstFirst
//purpose : Performs extending theWLine1 and theWLine2 through their
// respecting start point.
//=======================================================================
static void ExtendTwoWLFirstFirst(const IntSurf_Quadric& theS1,
const IntSurf_Quadric& theS2,
const Handle(IntPatch_WLine)& theWLine1,
const Handle(IntPatch_WLine)& theWLine2,
const IntSurf_PntOn2S& thePtWL1,
const IntSurf_PntOn2S& thePtWL2,
const gp_Vec& theVec1,
const gp_Vec& theVec2,
const gp_Vec& theVec3,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const Standard_Real theToler3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
unsigned int &theCheckResult,
Standard_Boolean &theHasBeenJoined)
{
IntSurf_PntOn2S aPOn2S;
if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
theVec1, theVec2, theVec3,
theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period))
{
return;
}
theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst);
ExtendFirst(theWLine1, aPOn2S);
ExtendFirst(theWLine2, aPOn2S);
if(theHasBeenJoined)
return;
Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
theWLine1->RemoveVertex(1);
aPrm = theWLine2->Vertex(1).ParameterOnLine();
while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
theWLine2->RemoveVertex(1);
const Standard_Integer aNbPts = theWLine2->NbPnts();
for(Standard_Integer aNPt = 2; aNPt <= aNbPts; aNPt++)
{
const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
theWLine1->Curve()->InsertBefore(1, aPt);
}
for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
{
IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
const Standard_Real aCurParam = aVert.ParameterOnLine();
aVert.SetParameter(aNbPts+aCurParam-1);
}
for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
{
IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
const Standard_Real aCurParam = aVert.ParameterOnLine();
aVert.SetParameter(aNbPts-aCurParam+1);
theWLine1->AddVertex(aVert, Standard_True);
}
theHasBeenJoined = Standard_True;
}
//=======================================================================
//function : ExtendTwoWLFirstLast
//purpose : Performs extending theWLine1 through its start point and theWLine2
// through its end point.
//=======================================================================
static void ExtendTwoWLFirstLast(const IntSurf_Quadric& theS1,
const IntSurf_Quadric& theS2,
const Handle(IntPatch_WLine)& theWLine1,
const Handle(IntPatch_WLine)& theWLine2,
const IntSurf_PntOn2S& thePtWL1,
const IntSurf_PntOn2S& thePtWL2,
const gp_Vec& theVec1,
const gp_Vec& theVec2,
const gp_Vec& theVec3,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const Standard_Real theToler3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
unsigned int &theCheckResult,
Standard_Boolean &theHasBeenJoined)
{
IntSurf_PntOn2S aPOn2S;
if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
theVec1, theVec2, theVec3,
theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period))
{
return;
}
theCheckResult |= IntPatchWT_DisLastLast;
ExtendFirst(theWLine1, aPOn2S);
ExtendLast (theWLine2, aPOn2S);
if(theHasBeenJoined)
return;
Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
theWLine1->RemoveVertex(1);
aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
theWLine2->RemoveVertex(theWLine2->NbVertex());
const Standard_Integer aNbPts = theWLine2->NbPnts();
for(Standard_Integer aNPt = aNbPts - 1; aNPt >= 1; aNPt--)
{
const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
theWLine1->Curve()->InsertBefore(1, aPt);
}
for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
{
IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
const Standard_Real aCurParam = aVert.ParameterOnLine();
aVert.SetParameter(aNbPts+aCurParam-1);
}
for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
{
const IntPatch_Point &aVert = theWLine2->Vertex(aNVtx);
theWLine1->AddVertex(aVert, Standard_True);
}
theHasBeenJoined = Standard_True;
}
//=======================================================================
//function : ExtendTwoWLLastFirst
//purpose : Performs extending theWLine1 through its end point and theWLine2
// through its start point.
//=======================================================================
static void ExtendTwoWLLastFirst(const IntSurf_Quadric& theS1,
const IntSurf_Quadric& theS2,
const Handle(IntPatch_WLine)& theWLine1,
const Handle(IntPatch_WLine)& theWLine2,
const IntSurf_PntOn2S& thePtWL1,
const IntSurf_PntOn2S& thePtWL2,
const gp_Vec& theVec1,
const gp_Vec& theVec2,
const gp_Vec& theVec3,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const Standard_Real theToler3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
unsigned int &theCheckResult,
Standard_Boolean &theHasBeenJoined)
{
IntSurf_PntOn2S aPOn2S;
if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
theVec1, theVec2, theVec3,
theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period))
{
return;
}
theCheckResult |= IntPatchWT_DisLastLast;
ExtendLast (theWLine1, aPOn2S);
ExtendFirst(theWLine2, aPOn2S);
if(theHasBeenJoined)
{
return;
}
Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
theWLine1->RemoveVertex(theWLine1->NbVertex());
aPrm = theWLine2->Vertex(1).ParameterOnLine();
while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
theWLine2->RemoveVertex(1);
const Standard_Integer aNbPts = theWLine1->NbPnts();
for(Standard_Integer aNPt = 2; aNPt <= theWLine2->NbPnts(); aNPt++)
{
const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
theWLine1->Curve()->Add(aPt);
}
for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
{
IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
const Standard_Real aCurParam = aVert.ParameterOnLine();
aVert.SetParameter(aNbPts+aCurParam-1);
theWLine1->AddVertex(aVert, Standard_False);
}
theHasBeenJoined = Standard_True;
}
//=======================================================================
//function : ExtendTwoWLLastLast
//purpose :
//=======================================================================
static void ExtendTwoWLLastLast(const IntSurf_Quadric& theS1,
const IntSurf_Quadric& theS2,
const Handle(IntPatch_WLine)& theWLine1,
const Handle(IntPatch_WLine)& theWLine2,
const IntSurf_PntOn2S& thePtWL1,
const IntSurf_PntOn2S& thePtWL2,
const gp_Vec& theVec1,
const gp_Vec& theVec2,
const gp_Vec& theVec3,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const Standard_Real theToler3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
unsigned int &/*theCheckResult*/,
Standard_Boolean &theHasBeenJoined)
{
IntSurf_PntOn2S aPOn2S;
if(!CheckArguments(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
theVec1, theVec2, theVec3,
theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period))
{
return;
}
//theCheckResult |= IntPatchWT_DisLastLast;
ExtendLast(theWLine1, aPOn2S);
ExtendLast(theWLine2, aPOn2S);
if(theHasBeenJoined)
return;
Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
theWLine1->RemoveVertex(theWLine1->NbVertex());
aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
theWLine2->RemoveVertex(theWLine2->NbVertex());
const Standard_Integer aNbPts = theWLine1->NbPnts() + theWLine2->NbPnts();
for(Standard_Integer aNPt = theWLine2->NbPnts()-1; aNPt >= 1; aNPt--)
{
const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
theWLine1->Curve()->Add(aPt);
}
for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
{
IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
const Standard_Real aCurParam = aVert.ParameterOnLine();
aVert.SetParameter(aNbPts - aCurParam);
theWLine1->AddVertex(aVert, Standard_False);
}
theHasBeenJoined = Standard_True;
}
//=========================================================================
// function : ComputePurgedWLine
@ -1054,7 +1491,8 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
//=======================================================================
//function : ExtendTwoWlinesToEachOther
//purpose :
//purpose : Performs extending theWLine1 and theWLine2 through their
// respecting end point.
//=======================================================================
void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& theSlin,
const IntSurf_Quadric& theS1,
@ -1063,15 +1501,13 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period)
const Standard_Real theV2Period,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2)
{
if(theSlin.Length() < 2)
return;
const Standard_Real aMaxAngle = M_PI/6; //30 degree
const Standard_Real aSqToler = theToler3D*theToler3D;
Standard_Real aU1=0.0, aV1=0.0, aU2=0.0, aV2=0.0;
gp_Pnt aPmid;
gp_Vec aVec1, aVec2, aVec3;
for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
@ -1086,6 +1522,12 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
if(aWLine1->Vertex(1).ParameterOnLine() != 1)
continue;
if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
continue;
for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
{
@ -1095,21 +1537,20 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
if(aWLine2.IsNull())
continue;
if(aWLine2->Vertex(1).ParameterOnLine() != 1)
continue;
if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
continue;
//Enable/Disable of some ckeck. Bit-mask is used for it.
//E.g. if 1st point of aWLine1 matches with
//1st point of aWLine2 then we do not need in check
//1st point of aWLine1 and last point of aWLine2 etc.
enum
{
IntPatchWT_EnAll = 0x00,
IntPatchWT_DisLastLast = 0x01,
IntPatchWT_DisLastFirst = 0x02,
IntPatchWT_DisFirstLast = 0x04,
IntPatchWT_DisFirstFirst = 0x08
};
unsigned int aCheckResult = IntPatchWT_EnAll;
Standard_Boolean hasBeenJoined = Standard_False;
const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
@ -1130,55 +1571,11 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
if(aVec3.SquareMagnitude() > aSqToler)
{
if( (aVec1.Angle(aVec2) < aMaxAngle) &&
(aVec1.Angle(aVec3) < aMaxAngle) &&
(aVec2.Angle(aVec3) < aMaxAngle))
{
aPmid.SetXYZ(0.5*(aPntFWL1.Value().XYZ()+aPntFWL2.Value().XYZ()));
if(IsIntersectionPoint(aPmid, theS1, theS2, aPntFWL1, theToler3D,
ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period,
aU1, aV1, aU2, aV2))
{
IntSurf_PntOn2S aPOn2S;
aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
aPntFWL1.Parameters(aU11, aV11, aU21, aV21);
aPntFWL2.Parameters(aU12, aV12, aU22, aV22);
if(!IsSeam(aU11, aU12, theU1Period) &&
!IsSeam(aV11, aV12, theV1Period) &&
!IsSeam(aU21, aU22, theU2Period) &&
!IsSeam(aV21, aV22, theV2Period))
{
aCheckResult |= (IntPatchWT_DisFirstLast |
IntPatchWT_DisLastFirst);
if(!aPOn2S.IsSame(aPntFWL1, Precision::Confusion()))
{
ExtendFirst(aWLine1, aPOn2S);
aCheckResult, hasBeenJoined);
}
else
{
aWLine1->Curve()->Value(1, aPOn2S);
}
if(!aPOn2S.IsSame(aPntFWL2, Precision::Confusion()))
{
ExtendFirst(aWLine2, aPOn2S);
}
else
{
aWLine2->Curve()->Value(1, aPOn2S);
}
}
}
}
}//if(aVec3.SquareMagnitude() > aSqToler) cond.
}//if(!(aCheckResult & 0x08)) cond.
if(!(aCheckResult & IntPatchWT_DisFirstLast))
{// First/Last
@ -1186,54 +1583,11 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
if(aVec3.SquareMagnitude() > aSqToler)
{
if((aVec1.Angle(aVec2) < aMaxAngle) &&
(aVec1.Angle(aVec3) < aMaxAngle) &&
(aVec2.Angle(aVec3) < aMaxAngle))
{
aPmid.SetXYZ(0.5*(aPntFWL1.Value().XYZ()+aPntLWL2.Value().XYZ()));
if(IsIntersectionPoint(aPmid, theS1, theS2, aPntFWL1, theToler3D,
ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period,
aU1, aV1, aU2, aV2))
{
IntSurf_PntOn2S aPOn2S;
aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
aPntFWL1.Parameters(aU11, aV11, aU21, aV21);
aPntLWL2.Parameters(aU12, aV12, aU22, aV22);
if(!IsSeam(aU11, aU12, theU1Period) &&
!IsSeam(aV11, aV12, theV1Period) &&
!IsSeam(aU21, aU22, theU2Period) &&
!IsSeam(aV21, aV22, theV2Period))
{
aCheckResult |= IntPatchWT_DisLastLast;
if(!aPOn2S.IsSame(aPntFWL1, Precision::Confusion()))
{
ExtendFirst(aWLine1, aPOn2S);
aCheckResult, hasBeenJoined);
}
else
{
aWLine1->Curve()->Value(1, aPOn2S);
}
if(!aPOn2S.IsSame(aPntLWL2, Precision::Confusion()))
{
ExtendLast(aWLine2, aPOn2S);
}
else
{
aWLine2->Curve()->Value(aWLine2->NbPnts(), aPOn2S);
}
}
}
}
}//if(aVec3.SquareMagnitude() > aSqToler) cond.
}//if(!(aCheckResult & 0x04)) cond.
if(!(aCheckResult & IntPatchWT_DisLastFirst))
{// Last/First
@ -1241,54 +1595,11 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
if(aVec3.SquareMagnitude() > aSqToler)
{
if((aVec1.Angle(aVec2) < aMaxAngle) &&
(aVec1.Angle(aVec3) < aMaxAngle) &&
(aVec2.Angle(aVec3) < aMaxAngle))
{
aPmid.SetXYZ(0.5*(aPntLWL1.Value().XYZ()+aPntFWL2.Value().XYZ()));
if(IsIntersectionPoint(aPmid, theS1, theS2, aPntLWL1, theToler3D,
ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period,
aU1, aV1, aU2, aV2))
{
IntSurf_PntOn2S aPOn2S;
aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
aPntLWL1.Parameters(aU11, aV11, aU21, aV21);
aPntFWL2.Parameters(aU12, aV12, aU22, aV22);
if(!IsSeam(aU11, aU12, theU1Period) &&
!IsSeam(aV11, aV12, theV1Period) &&
!IsSeam(aU21, aU22, theU2Period) &&
!IsSeam(aV21, aV22, theV2Period))
{
aCheckResult |= IntPatchWT_DisLastLast;
if(!aPOn2S.IsSame(aPntLWL1, Precision::Confusion()))
{
ExtendLast(aWLine1, aPOn2S);
aCheckResult, hasBeenJoined);
}
else
{
aWLine1->Curve()->Value(aWLine1->NbPnts(), aPOn2S);
}
if(!aPOn2S.IsSame(aPntFWL2, Precision::Confusion()))
{
ExtendFirst(aWLine2, aPOn2S);
}
else
{
aWLine2->Curve()->Value(1, aPOn2S);
}
}
}
}
}//if(aVec3.SquareMagnitude() > aSqToler) cond.
}//if(!(aCheckResult & 0x02)) cond.
if(!(aCheckResult & IntPatchWT_DisLastLast))
{// Last/Last
@ -1296,52 +1607,17 @@ void IntPatch_WLineTool::ExtendTwoWlinesToEachOther(IntPatch_SequenceOfLine& the
aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
if(aVec3.SquareMagnitude() > aSqToler)
{
if((aVec1.Angle(aVec2) < aMaxAngle) &&
(aVec1.Angle(aVec3) < aMaxAngle) &&
(aVec2.Angle(aVec3) < aMaxAngle))
{
aPmid.SetXYZ(0.5*(aPntLWL1.Value().XYZ()+aPntLWL2.Value().XYZ()));
if(IsIntersectionPoint(aPmid, theS1, theS2, aPntLWL1, theToler3D,
ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
theU1Period, theU2Period, theV1Period, theV2Period,
aU1, aV1, aU2, aV2))
{
IntSurf_PntOn2S aPOn2S;
aPOn2S.SetValue(aPmid, aU1, aV1, aU2, aV2);
Standard_Real aU11 = 0.0, aV11 = 0.0, aU21 = 0.0, aV21 = 0.0,
aU12 = 0.0, aV12 = 0.0, aU22 = 0.0, aV22 = 0.0;
aPntLWL1.Parameters(aU11, aV11, aU21, aV21);
aPntLWL2.Parameters(aU12, aV12, aU22, aV22);
if(!IsSeam(aU11, aU12, theU1Period) &&
!IsSeam(aV11, aV12, theV1Period) &&
!IsSeam(aU21, aU22, theU2Period) &&
!IsSeam(aV21, aV22, theV2Period))
{
if(!aPOn2S.IsSame(aPntLWL1, Precision::Confusion()))
{
ExtendLast(aWLine1, aPOn2S);
}
else
{
aWLine1->Curve()->Value(aWLine1->NbPnts(), aPOn2S);
aCheckResult, hasBeenJoined);
}
if(!aPOn2S.IsSame(aPntLWL2, Precision::Confusion()))
if(hasBeenJoined)
{
ExtendLast(aWLine2, aPOn2S);
}
else
{
aWLine2->Curve()->Value(aWLine2->NbPnts(), aPOn2S);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
}
}
}
}
}//if(aVec3.SquareMagnitude() > aSqToler) cond.
}//if(!(aCheckResult & 0x01)) cond.
}
}
}

@ -78,11 +78,9 @@ public:
const Standard_Real theVlSurf2);
//! Concatenates two some Walking lines from theSlin if it is possible.
//! This method does not create single line from several. It allows every
//! extended line to be started/finished in strictly determined point
//! (in the place of joint of two lines). As result, some gaps between two lines
//! will vanish.
//! Extends every line from theSlin (if it is possible) to be started/finished
//! in strictly determined point (in the place of joint of two lines).
//! As result, some gaps between two lines will vanish.
//! The Walking lines are supposed (algorithm will do nothing for not-Walking line)
//! to be computed as a result of intersection of two quadrics.
//! The quadrics definition is accepted in input parameters.
@ -93,7 +91,9 @@ public:
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period);
const Standard_Real theV2Period,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2);
};
#endif

@ -1,5 +1,3 @@
puts "TODO OCC27302 ALL: Error: Curve Number is bad!"
puts "============"
puts "OCC27282"
puts "============"
@ -8,7 +6,7 @@ puts ""
## [Regression to 6.9.1] smesh/bugs_00/A6: Cut produces an empty shape
###############################
set MaxTol 4.8106951786435371e-006
set MaxTol 4.8106952270863644e-006
set GoodNbCurv 1
restore [locate_data_file bug27282_cmpd.brep] a
@ -27,7 +25,7 @@ checkreal ToleranceReached ${Toler} ${MaxTol} 0.0 0.1
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
if {${NbCurv} != ${GoodNbCurv}} {
puts "Error: Curve Number is bad!"
puts "Error: Number of curves is bad!"
for {set i 1} {$i < ${NbCurv}} {incr i} {
for {set j [expr $i+1]} {$j <= $NbCurv} {incr j} {
@ -43,5 +41,5 @@ if {${NbCurv} != ${GoodNbCurv}} {
}
}
} else {
checklength c_1 -l 833.56846559428755
checklength c_1 -l 833.56846557106064
}

@ -0,0 +1,48 @@
puts "============"
puts "OCC27302"
puts "============"
puts ""
###############################
## Invalid curves number in intersection result
###############################
set MaxTol 9.9579577516847715e-005
set GoodNbCurv 1
restore [locate_data_file CTO900_pro12913a.rle] a
restore [locate_data_file CTO900_pro12913b.rle] b
explode a f
explode b f
smallview
don a_34 b_9
fit
set log [bopcurves a_34 b_9 -2d]
regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv
checkreal ToleranceReached ${Toler} ${MaxTol} 0.0 0.1
checkview -screenshot -2d -path ${imagedir}/${test_image}.png
if {${NbCurv} != ${GoodNbCurv}} {
puts "Error: Number of curves is bad!"
for {set i 1} {$i < ${NbCurv}} {incr i} {
for {set j [expr $i+1]} {$j <= $NbCurv} {incr j} {
mkedge e1 c_$i
mkedge e2 c_$j
dset dd_val 100.0*${Toler}
distmini dd e1 e2
if { [dval dd_val] > ${Toler} } {
puts "Error: Intersection result is not closed"
}
}
}
} else {
checklength c_1 -l 86.536841230136204
}