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

0029807: [Regression to 7.0.0] Impossible to cut cone from prism

The algorithm has been improved for the cases when the intersection line goes through the cone apex.

<!break>

1. All special points are put to the ALine forcefully (if they are true intersection point). Currently this step has not been implemented yet.

2. Now the tolerance of IntPatch_Point (put into ALine) is computed in order to cover the distance between it and the correspond ALine.

3. Test cases have been created.

4. Procedure of trimming IntAna_Curve has been improved.

5. Criterion when the discriminant of IntAna_Curve can be considered to be equal to 0 has been improved.

6. Methods IntAna_Curve::FindParameter(...) (and IntPatch_ALine::FindParameter(...)) currently returns list of all parameters corresponding the given point (IntAna_Curve can be self-interfered curve). Before the fix, this method always returned only one (randomly chosen) parameter.

7. Interfaces of the following methods have been changed: IntAna_Curve::FindParameter(...), IntPatch_ALine::FindParameter(...), IntPatch_ALine::ChangeVertex(...), IntPatch_SpecialPoints::AddPointOnUorVIso(...), IntPatch_SpecialPoints::AddSingularPole(...), IntPatch_WLineTool::ExtendTwoWLines().

8. Following methods have been added: IntAna_Quadric::SpecialPoints(...), IntPatch_ALineToWLine::GetSectionRadius(...), IntPatch_SpecialPoints::ProcessSphere(...), IntPatch_SpecialPoints::ProcessCone(...), IntPatch_SpecialPoints::GetTangentToIntLineForCone(...).

------------------
1) tests/boolean/volumemaker/C5
   tests/boolean/volumemaker/C6
   tests/boolean/volumemaker/E7

They are real IMPROVEMENTS. In the FIX (in compare with MASTER), section result between pairs of faces f2&f6 (C5), f3&f7 (C6) and f1&f5 (E7) is closed. Separated test cases have been created in order to focus on the problem with section. Bug #28503 has been fixed.

Correction in test cases.
This commit is contained in:
nbv
2018-05-25 11:05:58 +03:00
committed by bugmaster
parent d9d3107d8d
commit 3306fdd954
81 changed files with 3490 additions and 1091 deletions

View File

@@ -17,31 +17,21 @@
#ifndef _IntPatch_ALine_HeaderFile
#define _IntPatch_ALine_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <Standard_Handle.hxx>
#include <IntAna_Curve.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Integer.hxx>
#include <IntPatch_SequenceOfPoint.hxx>
#include <IntPatch_Line.hxx>
#include <IntSurf_TypeTrans.hxx>
#include <IntSurf_Situation.hxx>
#include <Standard_Real.hxx>
#include <gp_Pnt.hxx>
class Standard_DomainError;
class Standard_OutOfRange;
#include <IntPatch_SequenceOfPoint.hxx>
#include <TColStd_ListOfReal.hxx>
class IntAna_Curve;
class IntPatch_Point;
class gp_Pnt;
class gp_Vec;
class IntPatch_ALine;
DEFINE_STANDARD_HANDLE(IntPatch_ALine, IntPatch_Line)
//! Implementation of an intersection line described by a
//! parametrised curve.
//! parametrized curve.
class IntPatch_ALine : public IntPatch_Line
{
@@ -97,13 +87,13 @@ public:
//! intersection.
Standard_Boolean D1 (const Standard_Real U, gp_Pnt& P, gp_Vec& Du);
//! Tries to find the parameter of the point P on the curve.
//! Tries to find the parameters of the point P on the curve.
//! If the method returns False, the "projection" is
//! impossible, and the value of Para is not significant.
//! If the method returns True, Para is the parameter of the
//! nearest intersection between the curve and the iso-theta
//! containing P.
Standard_Boolean FindParameter (const gp_Pnt& P, Standard_Real& Para) const;
//! impossible.
//! If the method returns True at least one parameter has been found.
//! theParams is always sorted in ascending order.
void FindParameter(const gp_Pnt& P,
TColStd_ListOfReal& theParams) const;
//! Returns True if the line has a known First point.
//! This point is given by the method FirstPoint().
@@ -126,6 +116,12 @@ public:
//! Returns the vertex of range Index on the line.
const IntPatch_Point& Vertex (const Standard_Integer Index) const;
//! Allows modifying the vertex with index theIndex on the line.
IntPatch_Point& ChangeVertex(const Standard_Integer theIndex)
{
return svtx.ChangeValue(theIndex);
}
//! Set the parameters of all the vertex on the line.
//! if a vertex is already in the line,
//! its parameter is modified

View File

@@ -62,9 +62,10 @@ inline Standard_Boolean IntPatch_ALine::D1(const Standard_Real U, gp_Pnt& P, gp_
return curv.D1u(U,P,Du); // D1u leve l exception DomainError
}
inline Standard_Boolean IntPatch_ALine::FindParameter(const gp_Pnt& P, Standard_Real& Para) const
inline void IntPatch_ALine::FindParameter(const gp_Pnt& theP,
TColStd_ListOfReal& theParams) const
{
return curv.FindParameter(P,Para);
curv.FindParameter(theP, theParams);
}
inline Standard_Boolean IntPatch_ALine::HasFirstPoint () const

View File

@@ -62,21 +62,20 @@ static void AddVertexPoint(Handle(IntSurf_LineOn2S)& theLine,
//function : IsPoleOrSeam
//purpose : Processes theVertex depending on its type
// (pole/apex/point on boundary etc.) and adds it in theLine.
// thePIsoRef is the reference point using in case when the
// value of correspond parameter cannot be precise.
// theSingularSurfaceID contains the ID of surface with
// special point (0 - none, 1 - theS1, 2 - theS2)
//=======================================================================
static IntPatch_SpecPntType IsPoleOrSeam(const Handle(Adaptor3d_HSurface)& theS1,
const Handle(Adaptor3d_HSurface)& theS2,
const IntSurf_PntOn2S& thePIsoRef,
Handle(IntSurf_LineOn2S)& theLine,
IntPatch_Point &theVertex,
const Standard_Real* const theArrPeriods,
const Standard_Real theArrPeriods[4],
const Standard_Real theTol3d,
Standard_Integer& theSingularSurfaceID)
{
const Standard_Integer aNbPnts = theLine->NbPoints();
if(aNbPnts == 0)
return IntPatch_SPntNone;
theSingularSurfaceID = 0;
for(Standard_Integer i = 0; i < 2; i++)
@@ -94,8 +93,8 @@ static IntPatch_SpecPntType IsPoleOrSeam(const Handle(Adaptor3d_HSurface)& theS1
{
if(IntPatch_SpecialPoints::
AddSingularPole((isReversed? theS2 : theS1), (isReversed? theS1 : theS2),
theLine->Value(aNbPnts), theTol3d, theVertex,
anApexPoint, isReversed, Standard_True))
thePIsoRef, theVertex, anApexPoint,
isReversed, Standard_True))
{
anAddedPType = IntPatch_SPntPole;
break;
@@ -107,8 +106,8 @@ static IntPatch_SpecPntType IsPoleOrSeam(const Handle(Adaptor3d_HSurface)& theS1
{
if(IntPatch_SpecialPoints::
AddCrossUVIsoPoint((isReversed? theS2 : theS1), (isReversed? theS1 : theS2),
theLine->Value(aNbPnts), theTol3d,
anApexPoint, isReversed))
thePIsoRef, theTol3d,
anApexPoint, isReversed))
{
anAddedPType = IntPatch_SPntSeamUV;
break;
@@ -208,7 +207,7 @@ IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& t
//function : SetTol3D
//purpose :
//=======================================================================
void IntPatch_ALineToWLine::SetTol3D(const Standard_Real aTol)
void IntPatch_ALineToWLine::SetTol3D(const Standard_Real aTol)
{
myTol3D = aTol;
}
@@ -216,7 +215,7 @@ IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& t
//function : Tol3D
//purpose :
//=======================================================================
Standard_Real IntPatch_ALineToWLine::Tol3D()const
Standard_Real IntPatch_ALineToWLine::Tol3D()const
{
return myTol3D;
}
@@ -224,7 +223,7 @@ IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& t
//function : SetTolTransition
//purpose :
//=======================================================================
void IntPatch_ALineToWLine::SetTolTransition(const Standard_Real aTol)
void IntPatch_ALineToWLine::SetTolTransition(const Standard_Real aTol)
{
myTolTransition = aTol;
}
@@ -232,7 +231,7 @@ IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& t
//function : TolTransition
//purpose :
//=======================================================================
Standard_Real IntPatch_ALineToWLine::TolTransition()const
Standard_Real IntPatch_ALineToWLine::TolTransition()const
{
return myTolTransition;
}
@@ -240,7 +239,7 @@ IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& t
//function : SetTolOpenDomain
//purpose :
//=======================================================================
void IntPatch_ALineToWLine::SetTolOpenDomain(const Standard_Real aTol)
void IntPatch_ALineToWLine::SetTolOpenDomain(const Standard_Real aTol)
{
myTolOpenDomain = aTol;
}
@@ -252,6 +251,48 @@ IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& t
{
return myTolOpenDomain;
}
//=======================================================================
//function : GetSectionRadius
//purpose :
//=======================================================================
Standard_Real IntPatch_ALineToWLine::GetSectionRadius(const gp_Pnt& thePnt3d) const
{
Standard_Real aRetVal = RealLast();
for (Standard_Integer i = 0; i < 2; i++)
{
const IntSurf_Quadric& aQuad = i ? myQuad2 : myQuad1;
if (aQuad.TypeQuadric() == GeomAbs_Cone)
{
const gp_Cone aCone = aQuad.Cone();
const gp_XYZ aRVec = thePnt3d.XYZ() - aCone.Apex().XYZ();
const gp_XYZ &aDir = aCone.Axis().Direction().XYZ();
aRetVal = Min(aRetVal, Abs(aRVec.Dot(aDir)*Tan(aCone.SemiAngle())));
}
else if (aQuad.TypeQuadric() == GeomAbs_Sphere)
{
const gp_Sphere aSphere = aQuad.Sphere();
const gp_XYZ aRVec = thePnt3d.XYZ() - aSphere.Location().XYZ();
const gp_XYZ &aDir = aSphere.Position().Direction().XYZ();
const Standard_Real aR = aSphere.Radius();
const Standard_Real aD = aRVec.Dot(aDir);
const Standard_Real aDelta = aR*aR - aD*aD;
if (aDelta <= 0.0)
{
aRetVal = 0.0;
break;
}
else
{
aRetVal = Min(aRetVal, Sqrt(aDelta));
}
}
}
return aRetVal;
}
//=======================================================================
//function : MakeWLine
//purpose :
@@ -282,10 +323,81 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
IntPatch_SequenceOfLine& theLines) const
{
const Standard_Integer aNbVert = theALine->NbVertex();
if (!aNbVert) {
if (aNbVert == 0)
{
return;
}
#if 0
//To draw ALine as a wire DRAW-object use the following code.
{
static int zzz = 0;
zzz++;
bool flShow = /*(zzz == 1)*/false;
if (flShow)
{
std::cout << " +++ DUMP ALine (begin) +++++" << std::endl;
Standard_Integer aI = 0;
const Standard_Real aStep = (theLPar - theFPar) / 9999.0;
for (Standard_Real aPrm = theFPar; aPrm < theLPar; aPrm += aStep)
{
const gp_Pnt aPP(theALine->Value(aPrm));
std::cout << "vertex v" << ++aI << " " << aPP.X() << " " << aPP.Y() << " " << aPP.Z() << std::endl;
}
gp_Pnt aPP(theALine->Value(theLPar));
std::cout << "vertex v" << ++aI << " " << aPP.X() << " " << aPP.Y() << " " << aPP.Z() << std::endl;
std::cout << " --- DUMP ALine (end) -----" << std::endl;
}
}
//Copy all output information and apply it as a TCL-code in DRAW.
//After that, use TCL-script below:
/* ********************************* Script (begin)
shape ww w
copy v1 vprev
for {set i 2} {$i <= 10000} {incr i} {
distmini dd vprev v$i;
if { [dval dd_val] > 1.0e-7} {
edge ee vprev v$i;
add ee ww;
copy v$i vprev;
}
}
********************************** Script (end) */
#endif
//The same points can be marked by different vertices.
//The code below unifies tolerances of all vertices
//marking the same points.
for (Standard_Integer i = 1; i < aNbVert; i++)
{
IntPatch_Point &aCurVert = theALine->ChangeVertex(i);
const IntSurf_PntOn2S &aCurrPt = aCurVert.PntOn2S();
const Standard_Real aCurToler = aCurVert.Tolerance();
for (Standard_Integer j = i + 1; j <= aNbVert; j++)
{
IntPatch_Point &aVert = theALine->ChangeVertex(j);
const IntSurf_PntOn2S &aNewPt = aVert.PntOn2S();
const Standard_Real aToler = aVert.Tolerance();
const Standard_Real aSumTol = aCurToler + aToler;
if (aCurrPt.IsSame(aNewPt, aSumTol))
{
aCurVert.SetTolerance(aSumTol);
aVert.SetTolerance(aSumTol);
}
}
}
const Standard_Real aTol = 2.0*myTol3D+Precision::Confusion();
const Standard_Real aPrmTol = Max(1.0e-4*(theLPar - theFPar), Precision::PConfusion());
IntPatch_SpecPntType aPrePointExist = IntPatch_SPntNone;
NCollection_Array1<Standard_Real> aVertexParams(1, aNbVert);
@@ -299,7 +411,8 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++)
{
const Standard_Real aPar = theALine->Vertex(i).ParameterOnLine();
const IntPatch_Point& aVert = theALine->Vertex(i);
const Standard_Real aPar = aVert.ParameterOnLine();
aVertexParams(i) = aPar;
hasVertexBeenChecked(i) = Standard_False;
}
@@ -344,11 +457,24 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
}
}
Standard_Boolean isPointValid = Standard_False;
Standard_Real aTgMagn = 0.0;
{
gp_Pnt aPnt3d;
gp_Vec aTg;
theALine->D1(aParameter, aPnt3d, aTg);
if (GetSectionRadius(aPnt3d) < 5.0e-6)
{
// We cannot compute 2D-parameters of
// aPOn2S correctly.
isPointValid = Standard_False;
}
else
{
isPointValid = Standard_True;
}
aTgMagn = aTg.Magnitude();
Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
myQuad1.Parameters(aPnt3d, u1, v1);
@@ -372,13 +498,25 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
if (aPrePointExist == IntPatch_SPntPole)
{
Standard_Real aPrt = 0.5*(aPrevParam + theLPar);
for (Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++)
for (Standard_Integer i = aVertexParams.Lower();
i <= aVertexParams.Upper(); i++)
{
const Standard_Real aParam = aVertexParams(i);
if (aParam <= aPrevParam)
continue;
if ((aParam - aPrevParam) < aPrmTol)
{
const gp_Pnt aPnt3d(theALine->Value(aParam));
if (aPOn2S.Value().SquareDistance(aPnt3d) < Precision::SquareConfusion())
{
// i-th vertex is the same as a Pole/Apex.
// So, it should be ignored.
continue;
}
}
aPrt = 0.5*(aParam + aPrevParam);
break;
}
@@ -426,10 +564,17 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
if(hasVertexBeenChecked(i))
continue;
const IntPatch_Point &aVP = theALine->Vertex(i);
const Standard_Real aParam = aVertexParams(i);
if( ((aPrevParam < aParam) && (aParam <= aParameter)) ||
((aPrevParam == aParameter) && (aParam == aParameter)))
((aPrevParam == aParameter) && (aParam == aParameter))||
(aPOn2S.IsSame(aVP.PntOn2S(), aVP.Tolerance()) &&
(Abs(aVP.ParameterOnLine() - aParameter) < aPrmTol)))
{
//We have either jumped over the vertex or "fell" on the vertex.
//However, ALine can be self-interfered. Therefore, we need to check
//vertex parameter and 3D-distance together.
aVertexNumber = i;
break;
}
@@ -439,10 +584,14 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
if(aVertexNumber < 0)
{
StepComputing(theALine, aPOn2S, theLPar, aParameter, aTgMagn,
aStepMin, aStepMax, myTol3D, aStep);
AddPointIntoLine(aLinOn2S, anArrPeriods, aPOn2S);
aPrevLPoint = aPOn2S;
if (isPointValid)
{
StepComputing(theALine, aPOn2S, theLPar, aParameter, aTgMagn,
aStepMin, aStepMax, myTol3D, aStep);
AddPointIntoLine(aLinOn2S, anArrPeriods, aPOn2S);
aPrevLPoint = aPOn2S;
}
continue;
}
@@ -453,7 +602,33 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
// IsPoleOrSeam inserts new point in aLinOn2S if aVtx respects
//to some special point. Otherwise, aLinOn2S is not changed.
aPrePointExist = IsPoleOrSeam(myS1, myS2, aLinOn2S, aVtx,
// Find a point for reference parameter. It will be used
// if real parameter value cannot be precise (see comment to
// IsPoleOrSeam(...) function).
IntSurf_PntOn2S aPrefIso = aVtx.PntOn2S();
if (aLinOn2S->NbPoints() < 1)
{
for (Standard_Integer i = aVertexNumber + 1; i <= aVertexParams.Upper(); i++)
{
const Standard_Real aParam = aVertexParams(i);
if ((aParam - aVertexParams(aVertexNumber)) > Precision::PConfusion())
{
const Standard_Real aPrm = 0.5*(aParam + aVertexParams(aVertexNumber));
const gp_Pnt aPnt3d(theALine->Value(aPrm));
Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
myQuad1.Parameters(aPnt3d, u1, v1);
myQuad2.Parameters(aPnt3d, u2, v2);
aPrefIso.SetValue(aPnt3d, u1, v1, u2, v2);
break;
}
}
}
else
{
aPrefIso = aLinOn2S->Value(aLinOn2S->NbPoints());
}
aPrePointExist = IsPoleOrSeam(myS1, myS2, aPrefIso, aLinOn2S, aVtx,
anArrPeriods, aTol, aSingularSurfaceID);
const Standard_Real aCurVertParam = aVtx.ParameterOnLine();
@@ -463,6 +638,12 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
}
else
{
if (!isPointValid)
{
//Take a farther point of ALine (with greater parameter)
continue;
}
if(aVtx.Tolerance() > aTol)
{
aVtx.SetValue(aPOn2S);
@@ -507,7 +688,7 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
}
}
if(aPrePointExist != IntPatch_SPntNone)
if ((aPrePointExist != IntPatch_SPntNone) && (aLinOn2S->NbPoints() > 1))
break;
}//for(; !isLast; aParameter += aStep)
@@ -586,6 +767,9 @@ void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
if (aWLine->NbPnts() > 1)
{
aWLine->EnablePurging(Standard_False);
#ifdef INTPATCH_ALINETOWLINE_DEBUG
aWLine->Dump(0);
#endif
theLines.Append(aWLine);
}
}//while(aParameter < theLPar)
@@ -653,6 +837,19 @@ Standard_Boolean IntPatch_ALineToWLine::
const Standard_Real aR = IntPatch_PointLine::
CurvatureRadiusOfIntersLine(myS1, myS2, thePOn2S);
#if 0
{
static int zzz = 0;
zzz++;
std::cout << "*** R" << zzz << " (begin)" << std::endl;
Standard_Real aU1, aV1, aU2, aV2;
thePOn2S.Parameters(aU1, aV1, aU2, aV2);
std::cout << "Prms: " << aU1 << ", " << aV1 << ", " << aU2 << ", " << aV2 << std::endl;
std::cout << "Radius = " << aR << std::endl;
std::cout << "*** R" << zzz << " (end)" << std::endl;
}
#endif
if(aR < 0.0)
{
return Standard_False;

View File

@@ -80,11 +80,18 @@ protected:
const Standard_Real theMaxDeflection,
Standard_Real& theStep) const;
//! Compares distances from theMidPt to every quadrics with theMaxDeflection
//! (maximal distance of two ones is taken into account).
//! Returns the result of this comparison: -1 - small distance, +1 - big distance,
//! 0 - Dist == theMaxDeflection. Comparisons are done with internal tolerances.
Standard_EXPORT Standard_Integer CheckDeflection(const gp_XYZ& theMidPt,
const Standard_Real theMaxDeflection) const;
//! Returns radius of a circle obtained by intersection the quadric with a plane
//! goes through thePnt3d perpendicular to the quadric axis. This radius is computed
//! for both quadrics and minimal value is returned.
//! This check is made for cone and sphere only.
Standard_EXPORT Standard_Real GetSectionRadius(const gp_Pnt& thePnt3d) const;
private:

View File

@@ -42,24 +42,26 @@ static void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
const Standard_Boolean,
const Standard_Real);
static Standard_Boolean MultiplePoint (const IntPatch_SequenceOfPathPointOfTheSOnBounds&,
const Handle(Adaptor3d_TopolTool)&,
const IntSurf_Quadric&,
const gp_Vec&,
const IntPatch_SequenceOfLine&,
TColStd_Array1OfInteger&,
TColStd_Array1OfInteger&,
const Standard_Integer,
const Standard_Boolean);
static Standard_Boolean MultiplePoint(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
const Handle(Adaptor3d_TopolTool)& Domain,
const IntSurf_Quadric& QuadSurf,
const gp_Vec& Normale,
const IntPatch_SequenceOfLine& slin,
TColStd_Array1OfInteger& Done,
TColStd_Array1OfInteger& UsedLine,
const Standard_Integer Index,
const Standard_Boolean OnFirst,
const Standard_Real theToler);
static Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBounds&,
const Handle(Adaptor3d_TopolTool)&,
const IntSurf_Quadric&,
const gp_Vec&,
const gp_Vec&,
const Handle(IntPatch_Line)&,
TColStd_Array1OfInteger&,
const Standard_Integer);
static Standard_Boolean PointOnSecondDom(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt,
const Handle(Adaptor3d_TopolTool)& Domain,
const IntSurf_Quadric& QuadSurf,
const gp_Vec& Normale,
const gp_Vec& Vtgint,
const Handle(IntPatch_Line)& lin,
TColStd_Array1OfInteger& Done,
const Standard_Integer Index,
const Standard_Real theToler);
static Standard_Boolean SingleLine (const gp_Pnt&,
const Handle(IntPatch_Line)&,
@@ -68,17 +70,19 @@ static Standard_Boolean SingleLine (const gp_Pnt&,
gp_Vec&);
static Standard_Boolean FindLine (gp_Pnt&,
const IntPatch_SequenceOfLine&,
const Standard_Real,
Standard_Real&,
gp_Vec&,
Standard_Integer&,
Standard_Integer,
const Handle(Adaptor2d_HCurve2d)&,
Standard_Real&,
gp_Pnt& pointonarc,
const IntSurf_Quadric&);
static Standard_Boolean FindLine(gp_Pnt& Psurf,
const IntPatch_SequenceOfLine& slin,
const Standard_Real Tol,
TColStd_ListOfReal& theLParams,
gp_Vec& Vtgtint,
Standard_Integer& theLineIdx,
Standard_Integer OnlyThisLine,
const Handle(Adaptor2d_HCurve2d)& thearc,
Standard_Real& theparameteronarc,
gp_Pnt& thepointonarc,
const IntSurf_Quadric& QuadSurf1,
const IntSurf_Quadric& QuadSurf2,
Standard_Real& theOutputToler);
static void ProcessSegments (const IntPatch_SequenceOfSegmentOfTheSOnBounds&,
IntPatch_SequenceOfLine&,
@@ -102,8 +106,7 @@ Standard_Boolean IntersectionWithAnArc(gp_Pnt& PSurf,
gp_Pnt& thepointonarc,
const IntSurf_Quadric& QuadSurf,
const Standard_Real u0alin,
const Standard_Real u1alin,
Standard_Real& actualdist) {
const Standard_Real u1alin) {
Standard_Real dtheta,theta;
#ifdef OCCT_DEBUG
//Standard_Real u,v,A,B,C,cost,sint,sign;
@@ -221,7 +224,6 @@ Standard_Boolean IntersectionWithAnArc(gp_Pnt& PSurf,
thepointonarc = alin->Value(para);
cpasok=Standard_False;
//-- printf("\nt:%d",nbiter);
actualdist = bestdist;
return(Standard_True);
}
else {
@@ -249,7 +251,6 @@ Standard_Boolean IntersectionWithAnArc(gp_Pnt& PSurf,
_theparameteronarc=bestpara;
thepointonarc = alin->Value(para);
//-- printf("\nT:%d",nbiter);
actualdist=bestdist;
return(Standard_True);
}
//-- printf("\nF:%d",nbiter);
@@ -383,7 +384,7 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
//
Standard_Integer i,k;
Standard_Integer linenumber;
Standard_Real paraint = 0.,currentparameter,tolerance;
Standard_Real currentparameter,tolerance;
Standard_Real U1,V1,U2,V2;
Standard_Boolean goon;
@@ -429,10 +430,10 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
#endif
goon = MultiplePoint(listpnt,Domain,QuadSurf,Normale,slin,Done, UsedLine,
i,OnFirst);
i, OnFirst, Tolarc);
}
if (goon) {
Standard_Boolean linefound;
Standard_Boolean linefound = Standard_False;
for(Standard_Integer indiceline = 1; indiceline <=slin.Length(); indiceline++) {
if( UsedLine(indiceline) != 0 )
@@ -470,8 +471,11 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
// Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 End
gp_Pnt pointonarc;
Vtgint.SetCoord(0,0,0);
linefound = FindLine(Psurf,slin,tolerance,paraint,Vtgint,linenumber,indiceline,
currentarc,currentparameter,pointonarc,QuadSurf);
Standard_Real aVertTol = Tolarc;
TColStd_ListOfReal aLParams;
linefound = FindLine(Psurf, slin, tolerance, aLParams, Vtgint, linenumber,
indiceline, currentarc, currentparameter,
pointonarc, QuadSurf, OtherQuad, aVertTol);
if (linefound) {
#if 1
@@ -493,14 +497,14 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
// deuxieme surface
goon = PointOnSecondDom (listpnt, Domain, QuadSurf, Normale,
Vtgint, lin, Done, i);
Vtgint, lin, Done, i, aVertTol);
}
if (goon) {
//-- Modification du 4 avril 97 tolerance->Tolarc
//-- on replace sur le vertex la tolerance d entree et
//-- non la tolerance qui a servi au FindLine
solpnt.SetValue(Psurf,Tolarc,Standard_False);
solpnt.SetValue(Psurf, aVertTol, Standard_False);
U1 = p2d.X(); V1 = p2d.Y();
OtherQuad.Parameters(Psurf,U2,V2);
@@ -513,7 +517,6 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
Recadre(S1,S2,U2,V2,U1,V1);
solpnt.SetParameters(U2,V2,U1,V1);
}
solpnt.SetParameter(paraint);
if (! currentpointonrst.IsNew()) {
vtx = currentpointonrst.Vertex();
@@ -532,12 +535,21 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
}
solpnt.SetArc(OnFirst,currentarc, currentparameter,
Transline,Transarc);
if (TheType == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (lin)->AddVertex(solpnt);
}
else {
Handle(IntPatch_GLine)::DownCast (lin)->AddVertex(solpnt);
}
for (TColStd_ListIteratorOfListOfReal anItr(aLParams);
anItr.More(); anItr.Next())
{
solpnt.SetParameter(anItr.Value());
if (TheType == IntPatch_Analytic)
{
Handle(IntPatch_ALine)::DownCast(lin)->AddVertex(solpnt);
}
else
{
Handle(IntPatch_GLine)::DownCast(lin)->AddVertex(solpnt);
}
}
Done(i) = 1;
if (goon) {
@@ -550,6 +562,7 @@ void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1,
}
else if (Domain->Identical(vtx, vtxbis)) {
solpnt.SetVertex(OnFirst,vtxbis);
solpnt.SetTolerance(Tolarc);
currentarc = currentpointonrst.Arc();
currentparameter = currentpointonrst.Parameter();
@@ -599,7 +612,8 @@ Standard_Boolean MultiplePoint (const IntPatch_SequenceOfPathPointOfTheSOnBound
TColStd_Array1OfInteger& Done,
TColStd_Array1OfInteger& UsedLine,
const Standard_Integer Index,
const Standard_Boolean OnFirst) {
const Standard_Boolean OnFirst,
const Standard_Real theToler) {
// Traitement des points "multiples".
@@ -696,7 +710,7 @@ Standard_Boolean MultiplePoint (const IntPatch_SequenceOfPathPointOfTheSOnBound
intpt.SetArc(OnFirst,currentarc,currentparameter,
Transline,Transarc);
intpt.SetTolerance(theToler);
if (TheType == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (slinValueii)->Replace(jj,intpt);
@@ -728,6 +742,7 @@ Standard_Boolean MultiplePoint (const IntPatch_SequenceOfPathPointOfTheSOnBound
}
intpt.SetArc(OnFirst,currentarc,currentparameter,
Transline,Transarc);
intpt.SetTolerance(theToler);
if (TheType == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (slinValueii)->AddVertex(intpt);
}
@@ -770,7 +785,8 @@ Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBou
const gp_Vec& Vtgint,
const Handle(IntPatch_Line)& lin,
TColStd_Array1OfInteger& Done,
const Standard_Integer Index)
const Standard_Integer Index,
const Standard_Real theToler)
// Duplication des points sur domaine de l autre surface.
@@ -841,6 +857,8 @@ Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBou
}
intpt.SetArc(Standard_False,currentarc,currentparameter,
Transline,Transarc);
intpt.SetTolerance(theToler);
if (TheType == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (lin)->Replace(jj,intpt);
}
@@ -871,6 +889,7 @@ Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBou
}
intpt.SetArc(Standard_False,currentarc,currentparameter,
Transline,Transarc);
intpt.SetTolerance(theToler);
if (TheType == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (lin)->AddVertex(intpt);
}
@@ -905,31 +924,36 @@ Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBou
Standard_Boolean FindLine (gp_Pnt& Psurf,
const IntPatch_SequenceOfLine& slin,
const Standard_Real Tol,
Standard_Real& Paraint,
gp_Vec& Vtgtint,
Standard_Integer& Range,
Standard_Integer OnlyThisLine,
const Handle(Adaptor2d_HCurve2d)& thearc,
Standard_Real& theparameteronarc,
gp_Pnt& thepointonarc,
const IntSurf_Quadric& QuadSurf)
{
Standard_Boolean FindLine(gp_Pnt& Psurf,
const IntPatch_SequenceOfLine& slin,
const Standard_Real Tol,
TColStd_ListOfReal& theLParams,
gp_Vec& Vtgtint,
Standard_Integer& theLineIdx,
Standard_Integer OnlyThisLine,
const Handle(Adaptor2d_HCurve2d)& thearc,
Standard_Real& theparameteronarc,
gp_Pnt& thepointonarc,
const IntSurf_Quadric& QuadSurf1,
const IntSurf_Quadric& QuadSurf2,
Standard_Real& theOutputToler)
{
if ((QuadSurf1.Distance(Psurf) > Tol) || (QuadSurf2.Distance(Psurf) > Tol))
return Standard_False;
// Traitement du point de depart ayant pour representation Psurf
// dans l espace. On recherche la ligne d intersection contenant ce point.
// On a en sortie la ligne, et le parametre et sa tangente du point sur
// la ligne d intersection.
Standard_Real distmin = RealLast();
Standard_Real dist,para;
const Standard_Real aSqTol = Tol*Tol;
Standard_Real aSqDistMin = RealLast();
Standard_Real aSqDist, para;
Standard_Real lower,upper;
gp_Pnt pt;
Standard_Integer i;
IntPatch_IType typarc;
Standard_Real aParaInt = RealLast();
Standard_Integer nblin = slin.Length();
for (i=1; i<=nblin; i++) {
if(OnlyThisLine) { i=OnlyThisLine; nblin=0; }
@@ -961,11 +985,12 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Line(),Psurf);
if (para <= upper && para >= lower) {
pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Line());
dist = Psurf.Distance(pt);
if (dist< distmin) {
distmin = dist;
Paraint = para;
Range = i;
aSqDist = Psurf.SquareDistance(pt);
if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
{
aSqDistMin = aSqDist;
aParaInt = para;
theLineIdx = i;
}
}
}
@@ -977,11 +1002,12 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
(para + 2.*M_PI <=upper && para + 2.*M_PI >= lower) ||
(para - 2.*M_PI <=upper && para - 2.*M_PI >= lower)) {
pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Circle());
dist = Psurf.Distance(pt);
if (dist< distmin) {
distmin = dist;
Paraint = para;
Range = i;
aSqDist = Psurf.SquareDistance(pt);
if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
{
aSqDistMin = aSqDist;
aParaInt = para;
theLineIdx = i;
}
}
}
@@ -993,11 +1019,12 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
(para + 2.*M_PI <=upper && para + 2.*M_PI >= lower) ||
(para - 2.*M_PI <=upper && para - 2.*M_PI >= lower)) {
pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Ellipse());
dist = Psurf.Distance(pt);
if (dist< distmin) {
distmin = dist;
Paraint = para;
Range = i;
aSqDist = Psurf.SquareDistance(pt);
if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
{
aSqDistMin = aSqDist;
aParaInt = para;
theLineIdx = i;
}
}
}
@@ -1030,24 +1057,28 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
Standard_Real parabis = para+0.0000001;
pt = ElCLib::Value(para,Parab);
dist = Psurf.Distance(pt);
aSqDist = Psurf.SquareDistance(pt);
gp_Pnt ptbis = ElCLib::Value(parabis,Parab);
Standard_Real distbis = Psurf.Distance(ptbis);
Standard_Real ddist = distbis-dist;
const gp_Pnt ptbis = ElCLib::Value(parabis,Parab);
const Standard_Real distbis = Psurf.Distance(ptbis);
const Standard_Real aDist = Sqrt(aSqDist);
const Standard_Real ddist = distbis - aDist;
//--cout<<" para: "<<para<<" dist:"<<dist<<" ddist:"<<ddist<<endl;
if (dist< distmin) {
distmin = dist;
Paraint = para;
Range = i;
if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
{
aSqDistMin = aSqDist;
aParaInt = para;
theLineIdx = i;
}
if(dist<1.0e-9 && dist>-1.0e-9) { amelioration=100; }
if (aSqDist < Precision::SquarePConfusion())
{
amelioration = 100;
}
if(ddist>1.0e-9 || ddist<-1.0e-9 ) {
para=para-dist*(parabis-para)/ddist;
para = para - aDist*(parabis - para) / ddist;
}
else {
amelioration=100;
@@ -1065,11 +1096,12 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),Psurf);
if (para <= upper && para >= lower) {
pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola());
dist = Psurf.Distance(pt);
if (dist< distmin) {
distmin = dist;
Paraint = para;
Range = i;
aSqDist = Psurf.SquareDistance(pt);
if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin))
{
aSqDistMin = aSqDist;
aParaInt = para;
theLineIdx = i;
}
}
}
@@ -1077,17 +1109,33 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
case IntPatch_Analytic :
{
Handle(IntPatch_ALine) alin (Handle(IntPatch_ALine)::DownCast (lin));
Standard_Boolean FindIsOk = alin->FindParameter(Psurf,para);
if (FindIsOk) {
pt = alin->Value(para);
dist = Psurf.Distance(pt);
if (dist< distmin) {
distmin = dist;
Paraint = para;
Range = i;
}
}
Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin));
TColStd_ListOfReal aLParams;
alin->FindParameter(Psurf, aLParams);
if (!aLParams.IsEmpty())
{
// All found distances are already in some internal tolerance
// set in alin->FindParameter(...) method.
aSqDist = RealLast();
for (TColStd_ListIteratorOfListOfReal anItr(aLParams);
anItr.More(); anItr.Next())
{
pt = alin->Value(anItr.Value());
const Standard_Real aSqD = Psurf.SquareDistance(pt);
if (aSqD < aSqDist)
{
aSqDist = aSqD;
}
}
if (aSqDist < aSqDistMin)
{
aSqDistMin = aSqDist;
theLParams = aLParams;
theLineIdx = i;
}
}
else {
//-- le point n a pas ete trouve par bete projection.
//-- on essaie l intersection avec la restriction en 2d
@@ -1096,19 +1144,20 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
// Standard_Real anpara=para;
//#endif
gp_Pnt CopiePsurf=Psurf;
Standard_Boolean IntersectIsOk=IntersectionWithAnArc(CopiePsurf,alin,para,thearc,theparamonarc,thepointonarc,QuadSurf,lower,upper,dist);
//--printf("\nIntersectionWithAnArc %d \n Psurf(%g,%g,%g)->(%g,%g,%g) dist=%g\n para(%g)->(%g)\n paraonarc(%g)->(%g)",
//-- ok,Psurf.X(),Psurf.Y(),Psurf.Z(),thepointonarc.X(),thepointonarc.Y(),thepointonarc.Z(),dist,
//-- anpara,para,theparameteronarc,theparamonarc);
dist = CopiePsurf.Distance(Psurf);
Standard_Boolean IntersectIsOk = IntersectionWithAnArc(CopiePsurf, alin, para,
thearc, theparamonarc,
thepointonarc,
QuadSurf1,
lower, upper);
aSqDist = CopiePsurf.SquareDistance(Psurf);
if(IntersectIsOk) {
if(dist<Tol) {
if (aSqDist < aSqTol)
{
theparameteronarc = theparamonarc;
Psurf = thepointonarc;
distmin = dist;
Paraint = para;
Range = i;
aSqDistMin = aSqDist;
theLParams.Append(para);
theLineIdx = i;
}
}
}
@@ -1124,86 +1173,47 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
}
}
if (distmin > Tol) {
if (aSqDistMin == RealLast())
return Standard_False;
}
typarc = slin.Value(Range)->ArcType();
theOutputToler = Max(theOutputToler, Sqrt(aSqDistMin));
// Calcul de la tangente.
typarc = slin.Value(theLineIdx)->ArcType();
// Computation of tangent vector
switch (typarc) {
case IntPatch_Lin :
Vtgtint = (*((Handle(IntPatch_GLine)*)&slin(Range)))->Line().Direction();
theLParams.Append(aParaInt);
Vtgtint = (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Line().Direction();
break;
case IntPatch_Circle :
Vtgtint = ElCLib::DN(Paraint,(*((Handle(IntPatch_GLine)*)&slin(Range)))->Circle(),1);
theLParams.Append(aParaInt);
Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Circle(), 1);
break;
case IntPatch_Ellipse :
Vtgtint = ElCLib::DN(Paraint,(*((Handle(IntPatch_GLine)*)&slin(Range)))->Ellipse(),1);
theLParams.Append(aParaInt);
Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Ellipse(), 1);
break;
case IntPatch_Parabola :
Vtgtint = ElCLib::DN(Paraint,(*((Handle(IntPatch_GLine)*)&slin(Range)))->Parabola(),1);
theLParams.Append(aParaInt);
Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Parabola(), 1);
break;
case IntPatch_Hyperbola :
Vtgtint = ElCLib::DN(Paraint,(*((Handle(IntPatch_GLine)*)&slin(Range)))->Hyperbola(),1);
theLParams.Append(aParaInt);
Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Hyperbola(), 1);
break;
case IntPatch_Analytic:
{
const Handle(IntPatch_ALine)& alin = (*((Handle(IntPatch_ALine)*)&slin(Range)));
Standard_Boolean abid = alin->D1(Paraint,pt,Vtgtint);
if (!abid) {
Standard_Real domaininf,domainsup,paramproche;
Standard_Boolean boolbid;
domaininf = alin->FirstParameter(boolbid);
domainsup = alin->LastParameter(boolbid);
if(Paraint>=domaininf && Paraint<=domainsup) {
Standard_Real DeltaParam = 0.001 * (domainsup-domaininf);
if(Paraint-domaininf >= domainsup-Paraint) {
//-- On decale le point vers le parametre le plus eloigne.
DeltaParam = -DeltaParam;
}
Standard_Integer kountbid = 0;
Standard_Boolean bornok = Standard_True;
paramproche = Paraint;
do {
paramproche+=DeltaParam;
kountbid++;
gp_Pnt ptbid;
if(paramproche>=domaininf && paramproche<=domainsup) {
abid = alin->D1(paramproche,ptbid,Vtgtint);
}
else {
bornok = Standard_False;
}
}
while(abid==Standard_False && kountbid<5 && bornok);
//-- Attention aux points de tangence (croisement de 4 lignes )
bornok = Standard_True;
kountbid = 0;
gp_Vec OVtgtint(0.0,0.0,0.0);
paramproche = Paraint;
do {
paramproche-=DeltaParam;
kountbid++;
gp_Pnt ptbid;
if(paramproche>=domaininf && paramproche<=domainsup) {
abid = alin->D1(paramproche,ptbid,OVtgtint);
}
else {
bornok = Standard_False;
}
}
while(abid==Standard_False && kountbid<5 && bornok);
if(bornok) {
paramproche = Vtgtint.Dot(OVtgtint);
if(paramproche<=0.0) abid = Standard_False;
}
}
if(!abid) {
//-- cout << "Pb sur Calcul de derivee 111 " << endl;
Vtgtint.SetCoord(0.,0.,0.);
}
if (!Handle(IntPatch_ALine)::DownCast(slin(theLineIdx))->D1(theLParams.Last(), pt, Vtgtint))
{
//Previously (before the fix #29807) this code tried to process case
//when Handle(IntPatch_ALine)::D1(...) method returns FALSE and
//computed Vtgtint input argument value. Currently, any singularities
//must be processed by high-level algorithms (IntPatch_SpecialPoints class).
//Therefore this code has been deleted as deprecated.
Vtgtint.SetCoord(0.0, 0.0, 0.0);
}
}
break;
@@ -1218,19 +1228,20 @@ Standard_Boolean FindLine (gp_Pnt& Psurf,
return Standard_True;
}
Standard_Boolean SingleLine (const gp_Pnt& Psurf,
const Handle(IntPatch_Line)& lin,
const Standard_Real Tol,
Standard_Real& Paraint,
gp_Vec& Vtgtint) {
// Traitement du point de depart ayant pour representation Psurf
// dans l espace. On le replace sur la ligne d intersection; On a en sortie
// son parametre et sa tangente sur la ligne d intersection.
// La fonction renvoie False si le point projete est a une distance
// superieure a Tol du point a projeter.
//=======================================================================
//function : SingleLine
//purpose : Traitement du point de depart ayant pour representation Psurf
// dans l espace. On le replace sur la ligne d intersection; On a en sortie
// son parametre et sa tangente sur la ligne d intersection.
// La fonction renvoie False si le point projete est a une distance
// superieure a Tol du point a projeter.
//=======================================================================
Standard_Boolean SingleLine(const gp_Pnt& Psurf,
const Handle(IntPatch_Line)& lin,
const Standard_Real Tol,
Standard_Real& Paraint,
gp_Vec& Vtgtint)
{
IntPatch_IType typarc = lin->ArcType();
Standard_Real parproj = 0.;
@@ -1238,7 +1249,6 @@ Standard_Boolean SingleLine (const gp_Pnt& Psurf,
gp_Pnt ptproj;
Standard_Boolean retvalue;
switch (typarc) {
case IntPatch_Lin :
parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Line(),Psurf);
@@ -1262,46 +1272,30 @@ Standard_Boolean SingleLine (const gp_Pnt& Psurf,
break;
case IntPatch_Analytic :
{
Handle(IntPatch_ALine) alin (Handle(IntPatch_ALine)::DownCast (lin));
Standard_Boolean ok = alin->FindParameter(Psurf,parproj);
if (ok) {
gp_Pnt ptbid;
Standard_Boolean bid = alin->D1(parproj,ptbid,tgint);
if (!bid) {
Standard_Real domaininf,domainsup,paramproche;
Standard_Boolean boolbid;
domaininf = alin->FirstParameter(boolbid);
domainsup = alin->LastParameter(boolbid);
if(parproj>=domaininf && parproj<=domainsup) {
Standard_Real DeltaParam = 0.001 * (domainsup-domaininf);
if(parproj-domaininf >= domainsup-parproj) {
//-- On decale le point vers le parametre le plus eloigne.
DeltaParam = -DeltaParam;
}
Standard_Integer kountbid = 0;
paramproche = parproj;
do {
paramproche+=DeltaParam;
kountbid++;
bid = alin->D1(paramproche,ptbid,tgint);
}
while(bid==Standard_False && kountbid<5);
ptproj = Psurf;
}
if(!bid) {
//-- cout << "Pb sur Calcul de derivee ALine " << endl;
tgint.SetCoord(0.,0.,0.);
return(Standard_False);
}
}
else {
ptproj = Psurf;
}
Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin));
TColStd_ListOfReal aLParams;
alin->FindParameter(Psurf, aLParams);
if (!aLParams.IsEmpty())
{
ptproj = Psurf;
parproj = aLParams.Last();
gp_Pnt aPtemp;
if (!alin->D1(parproj, aPtemp, tgint))
{
//Previously (before the fix #29807) this code tried to process case
//when Handle(IntPatch_ALine)::D1(...) method returns FALSE and
//computed Vtgtint input argument value. Currently, any singularities
//must be processed by high-level algorithms (IntPatch_SpecialPoints class).
//Therefore this code has been deleted as deprecated.
tgint.SetCoord(0.0, 0.0, 0.0);
}
}
else {
//-- cout << "---- Pb sur ligne analytique dans SingleLine" << endl;
//-- cout << " Find Parameter"<<endl;
return Standard_False;
else
{
//-- cout << "---- Pb sur ligne analytique dans SingleLine" << endl;
//-- cout << " Find Parameter"<<endl;
return Standard_False;
}
}
break;
@@ -1485,6 +1479,7 @@ void ProcessSegments (const IntPatch_SequenceOfSegmentOfTheSOnBounds& listedg,
if (EdgeDegenere==Standard_False && dofirst) {
if (ptvtx.Value().Distance(PStartf.Value()) <=TolArc) {
ptvtx.SetMultiple(Standard_True);
ptvtx.SetTolerance(TolArc);
if (typ == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,ptvtx);
}
@@ -1549,6 +1544,7 @@ void ProcessSegments (const IntPatch_SequenceOfSegmentOfTheSOnBounds& listedg,
if (EdgeDegenere==Standard_False && dolast) {
if (ptvtx.Value().Distance(PStartl.Value()) <=TolArc) {
ptvtx.SetMultiple(Standard_True);
ptvtx.SetTolerance(TolArc);
if (typ == IntPatch_Analytic) {
Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,ptvtx);
}
@@ -1988,6 +1984,7 @@ void ProcessRLine (IntPatch_SequenceOfLine& slin,
}
if (keeppoint) {
Ptvtx.SetMultiple(Standard_True);
Ptvtx.SetTolerance(_TolArc);
newptvtx.SetMultiple(Standard_True);
if (typ2 == IntPatch_Analytic) {

View File

@@ -307,11 +307,15 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
}
nbpt = solrst.NbPoints();
nbseg= solrst.NbSegments();
for (i=1; i<= nbpt; i++) {
pnt1.Append(solrst.Point(i));
for (i = 1; i <= nbpt; i++)
{
const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
pnt1.Append(aPt);
}
for (i=1; i<= nbseg; i++) {
edg1.Append(solrst.Segment(i));
for (i = 1; i <= nbseg; i++)
{
const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
edg1.Append(aSegm);
}
nosolonS1 = (nbpt == 0) && (nbseg == 0);
@@ -335,15 +339,19 @@ void IntPatch_ImpImpIntersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
if (solrst.AllArcSolution() && typs1 == typs2) {
all2 = Standard_True;
}
nbpt = solrst.NbPoints();
nbseg= solrst.NbSegments();
for (i=1; i<= nbpt; i++) {
pnt2.Append(solrst.Point(i));
const IntPatch_ThePathPointOfTheSOnBounds& aPt = solrst.Point(i);
pnt2.Append(aPt);
}
for (i=1; i<= nbseg; i++) {
edg2.Append(solrst.Segment(i));
const IntPatch_TheSegmentOfTheSOnBounds& aSegm = solrst.Segment(i);
edg2.Append(aSegm);
}
nosolonS2 = (nbpt == 0) && (nbseg == 0);
if (nosolonS2 && all2) { // cas de face sans restrictions

View File

@@ -29,12 +29,10 @@ static void ShortCosForm( const Standard_Real theCosFactor,
Standard_Real& theCoeff,
Standard_Real& theAngle);
//
static
Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
const gp_Cone& aCo,
IntAna_Curve& aC,
const Standard_Real aTol,
IntAna_ListOfCurve& aLC);
static Standard_Boolean ExploreCurve(const gp_Cone& theCo,
IntAna_Curve& aC,
const Standard_Real aTol,
IntAna_ListOfCurve& aLC);
static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
const Standard_Real theUlTarget,
@@ -511,13 +509,6 @@ private:
const Standard_Boolean myIsReverse;
};
static
Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
const gp_Cone& aCo,
IntAna_Curve& aC,
const Standard_Real aTol,
IntAna_ListOfCurve& aLC);
static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
const IntSurf_Quadric& theQuad2,
const Handle(IntSurf_LineOn2S)& theLine,
@@ -840,6 +831,7 @@ void ProcessBounds(const Handle(IntPatch_ALine)& alig, //-- ligne coura
if (!procf) {
d=ptf.Distance(ptsol.Value());
if (d <= Tol) {
ptsol.SetTolerance(Tol);
if (!ptsol.IsMultiple()) {
//-- le point ptsol (de aligold) est declare multiple sur aligold
Multpoint = Standard_True;
@@ -858,6 +850,7 @@ void ProcessBounds(const Handle(IntPatch_ALine)& alig, //-- ligne coura
}
if (!procl) {
if (ptl.Distance(ptsol.Value()) <= Tol) {
ptsol.SetTolerance(Tol);
if (!ptsol.IsMultiple()) {
Multpoint = Standard_True;
ptsol.SetMultiple(Standard_True);
@@ -888,6 +881,8 @@ void ProcessBounds(const Handle(IntPatch_ALine)& alig, //-- ligne coura
}
}
}
ptsol.SetTolerance(Tol);
if (!procf && !procl) {
Quad1.Parameters(ptf,U1,V1);
Quad2.Parameters(ptf,U2,V2);
@@ -4136,7 +4131,7 @@ Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
//curvsol = anaint.Curve(i);
aC=anaint.Curve(i);
aLC.Clear();
ExploreCurve(Cy, Co, aC, 10.*Tol, aLC);
ExploreCurve(Co, aC, 10.*Tol, aLC);
//
aIt.Initialize(aLC);
for (; aIt.More(); aIt.Next()) {
@@ -4209,61 +4204,69 @@ Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
}
//=======================================================================
//function : ExploreCurve
//purpose :
//purpose : Splits aC on several curves in the cone apex points.
//=======================================================================
Standard_Boolean ExploreCurve(const gp_Cylinder& ,//aCy,
const gp_Cone& aCo,
IntAna_Curve& aC,
const Standard_Real aTol,
IntAna_ListOfCurve& aLC)
Standard_Boolean ExploreCurve(const gp_Cone& theCo,
IntAna_Curve& theCrv,
const Standard_Real theTol,
IntAna_ListOfCurve& theLC)
{
Standard_Boolean bFind=Standard_False;
Standard_Real aTheta, aT1, aT2, aDst;
gp_Pnt aPapx, aPx;
const Standard_Real aSqTol = theTol*theTol;
const gp_Pnt aPapx(theCo.Apex());
Standard_Real aT1, aT2;
theCrv.Domain(aT1, aT2);
theLC.Clear();
//
//aC.Dump();
//
aLC.Clear();
aLC.Append(aC);
//
aPapx=aCo.Apex();
//
aC.Domain(aT1, aT2);
//
aPx=aC.Value(aT1);
aDst=aPx.Distance(aPapx);
if (aDst<aTol) {
return bFind;
TColStd_ListOfReal aLParams;
theCrv.FindParameter(aPapx, aLParams);
if (aLParams.IsEmpty())
{
theLC.Append(theCrv);
return Standard_False;
}
aPx=aC.Value(aT2);
aDst=aPx.Distance(aPapx);
if (aDst<aTol) {
return bFind;
for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next())
{
Standard_Real aPrm = anItr.Value();
if ((aPrm - aT1) < Precision::PConfusion())
continue;
Standard_Boolean isLast = Standard_False;
if ((aT2 - aPrm) < Precision::PConfusion())
{
aPrm = aT2;
isLast = Standard_True;
}
const gp_Pnt aP = theCrv.Value(aPrm);
const Standard_Real aSqD = aP.SquareDistance(aPapx);
if (aSqD < aSqTol)
{
IntAna_Curve aC1 = theCrv;
aC1.SetDomain(aT1, aPrm);
aT1 = aPrm;
theLC.Append(aC1);
}
if (isLast)
break;
}
//
bFind=aC.FindParameter(aPapx, aTheta);
if (!bFind){
return bFind;
if (theLC.IsEmpty())
{
theLC.Append(theCrv);
return Standard_False;
}
//
aPx=aC.Value(aTheta);
aDst=aPx.Distance(aPapx);
if (aDst>aTol) {
return !bFind;
if ((aT2 - aT1) > Precision::PConfusion())
{
IntAna_Curve aC1 = theCrv;
aC1.SetDomain(aT1, aT2);
theLC.Append(aC1);
}
//
// need to be splitted at aTheta
IntAna_Curve aC1, aC2;
//
aC1=aC;
aC1.SetDomain(aT1, aTheta);
aC2=aC;
aC2.SetDomain(aTheta, aT2);
//
aLC.Clear();
aLC.Append(aC1);
aLC.Append(aC2);
//
return bFind;
return Standard_True;
}

View File

@@ -19,6 +19,7 @@
#include <Adaptor3d_HSurface.hxx>
#include <Adaptor3d_TopolTool.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
#include <IntPatch_ArcFunction.hxx>
#include <IntPatch_PointLine.hxx>
#include <IntPatch_RLine.hxx>
@@ -87,6 +88,7 @@ static IntPatch_SpecPntType IsSeamOrPole(const Handle(Adaptor3d_HSurface)& theQS
const Handle(IntSurf_LineOn2S)& theLine,
const Standard_Boolean IsReversed,
const Standard_Integer theRefIndex,
const Standard_Real theTol3D,
const Standard_Real theDeltaMax)
{
if((theRefIndex < 1) || (theRefIndex >= theLine->NbPoints()))
@@ -96,6 +98,8 @@ static IntPatch_SpecPntType IsSeamOrPole(const Handle(Adaptor3d_HSurface)& theQS
Standard_Real aUQRef, aVQRef, aUPRef, aVPRef;
Standard_Real aUQNext, aVQNext, aUPNext, aVPNext;
const gp_Pnt &aP3d = theLine->Value(theRefIndex + 1).Value();
if(IsReversed)
{
theLine->Value(theRefIndex).Parameters (aUPRef, aVPRef, aUQRef, aVQRef);
@@ -109,6 +113,28 @@ static IntPatch_SpecPntType IsSeamOrPole(const Handle(Adaptor3d_HSurface)& theQS
const GeomAbs_SurfaceType aType = theQSurf->GetType();
if ((aType == GeomAbs_Cone) &&
(theQSurf->Cone().Apex().SquareDistance(aP3d) < theTol3D*theTol3D))
{
return IntPatch_SPntPoleSeamU;
}
else if (aType == GeomAbs_Sphere)
{
const Standard_Real aSqTol = theTol3D*theTol3D;
gp_Pnt aP(ElSLib::Value(0.0, M_PI_2, theQSurf->Sphere()));
if (aP.SquareDistance(aP3d) < aSqTol)
{
return IntPatch_SPntPoleSeamU;
}
aP = ElSLib::Value(0.0, -M_PI_2, theQSurf->Sphere());
if (aP.SquareDistance(aP3d) < aSqTol)
{
return IntPatch_SPntPoleSeamU;
}
}
const Standard_Real aDeltaU = Abs(aUQRef - aUQNext);
if((aType != GeomAbs_Torus) && (aDeltaU < theDeltaMax))
@@ -2628,6 +2654,15 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
PrePoint, IsReversed))
{
sline->Add(PrePoint);
//Avoid adding duplicate points.
for (;aFindex <= aLindex; aFindex++)
{
if (!PrePoint.IsSame(aSSLine->Value(aFindex), theTolTang))
{
break;
}
}
}
else
{
@@ -2658,7 +2693,8 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
DetectOfBoundaryAchievement(theQSurf, IsReversed, aSSLine,
k, aTOL2D, sline, isOnBoundary);
aPrePointExist = IsSeamOrPole(theQSurf, aSSLine, IsReversed, k - 1, aDeltaUmax);
aPrePointExist = IsSeamOrPole(theQSurf, aSSLine, IsReversed,
k - 1, theTolTang, aDeltaUmax);
if (isOnBoundary && (aPrePointExist != IntPatch_SPntPoleSeamU))
{
@@ -2742,7 +2778,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
aSupBound(3) = theQSurf->LastUParameter();
IntPatch_SpecialPoints::
AddPointOnUorVIso(theQSurf, thePSurf, aRefPt, Standard_False,
AddPointOnUorVIso(theQSurf, thePSurf, aRefPt, Standard_False, 0.0,
aTol, aStartPoint, anInfBound, aSupBound,
aNewPoint, IsReversed);
}
@@ -2752,9 +2788,10 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
IntPatch_Point aVert;
aVert.SetValue(aRefPt);
aVert.SetTolerance(theTolTang);
if(IntPatch_SpecialPoints::
AddSingularPole(theQSurf, thePSurf, aRefPt, theTolTang,
AddSingularPole(theQSurf, thePSurf, aRefPt,
aVert, aNewPoint, IsReversed))
{
aPrePointExist = IntPatch_SPntPole;
@@ -2823,7 +2860,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
aSupBound(3) = theQSurf->LastVParameter();
IntPatch_SpecialPoints::
AddPointOnUorVIso(theQSurf, thePSurf, aRefPt, Standard_True, aTol,
AddPointOnUorVIso(theQSurf, thePSurf, aRefPt, Standard_True, 0.0, aTol,
aStartPoint, anInfBound, aSupBound, aNewPoint,
IsReversed);
}
@@ -2878,7 +2915,9 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_PointLine)& theLin
if(sline->NbPoints() == 1)
{
flNextLine = Standard_True;
aFindex = aBindex;
if (aFindex < aBindex)
aFindex = aBindex;
//Go to the next part of aSSLine
//because we cannot create the line

View File

@@ -1432,8 +1432,32 @@ void IntPatch_Intersection::GeomGeomPerfom(const Handle(Adaptor3d_HSurface)& the
theS1->IsVPeriodic()? theS1->VPeriod() : 0.0,
theS2->IsUPeriodic()? theS2->UPeriod() : 0.0,
theS2->IsVPeriodic()? theS2->VPeriod() : 0.0};
NCollection_List<gp_Pnt> aListOfCriticalPoints;
if (theS1->GetType() == GeomAbs_Cone)
{
aListOfCriticalPoints.Append(theS1->Cone().Apex());
}
else if (theS1->GetType() == GeomAbs_Sphere)
{
aListOfCriticalPoints.Append(theS1->Value(0.0, M_PI_2));
aListOfCriticalPoints.Append(theS1->Value(0.0, -M_PI_2));
}
if (theS2->GetType() == GeomAbs_Cone)
{
aListOfCriticalPoints.Append(theS2->Cone().Apex());
}
else if (theS2->GetType() == GeomAbs_Sphere)
{
aListOfCriticalPoints.Append(theS2->Value(0.0, M_PI_2));
aListOfCriticalPoints.Append(theS2->Value(0.0, -M_PI_2));
}
IntPatch_WLineTool::ExtendTwoWLines(slin, theS1, theS2, TolTang,
anArrOfPeriod, aBx1, aBx2);
anArrOfPeriod, aBx1, aBx2,
aListOfCriticalPoints);
}
}

View File

@@ -153,18 +153,18 @@ void IntPatch_Point::Dump() const {
Standard_Real u1,v1,u2,v2;
pt.Parameters(u1,v1,u2,v2);
printf("P(%15.10f,%15.10f,%15.10f) UV1(%15.10f,%15.10f) UV2(%15.10f,%15.10f) (Para:%15.10f)\n",
printf("P(%+10.20f,%+10.20f,%+10.20f) UV1(%+10.20f,%+10.20f) UV2(%+10.20f,%+10.20f) (Para:%+10.20f)\n",
(double)(pt.Value().X()),
(double)(pt.Value().Y()),
(double)(pt.Value().Z()),
(double)u1,(double)v1,(double)u2,(double)v2,(double)para);
if(onS1)
printf("*OnS1* par=%15.10f arc1=%10p", (double)prm1, (void*)arcS1.operator->());
printf("*OnS1* par=%+10.20f arc1=%10p", (double)prm1, (void*)arcS1.operator->());
if(vtxonS1)
printf(" *Vtx1* vtx1=%10p", (void*)vS1.operator->());
if(onS1 || vtxonS1) printf("\n");
if(onS2)
printf("*OnS2* par=%15.10f arc2=%10p", (double)prm2, (void*)arcS2.operator->());
printf("*OnS2* par=%+10.20f arc2=%10p", (double)prm2, (void*)arcS2.operator->());
if(vtxonS2)
printf(" *Vtx2* vtx2=%10p", (void*)vS2.operator->());
@@ -184,4 +184,6 @@ void IntPatch_Point::Dump() const {
}
cout<<endl;
}
cout << "\nToler = " << Tolerance();
cout << endl;
}

View File

@@ -222,7 +222,10 @@ private:
Standard_Real para;
Standard_Real tol;
Standard_Boolean tgt;
//TRUE if the point is in several intersection lines
Standard_Boolean mult;
Standard_Boolean onS1;
Standard_Boolean vtxonS1;
Handle(Adaptor3d_HVertex) vS1;

View File

@@ -119,8 +119,13 @@ Standard_Real IntPatch_PointLine::
const gp_Vec aCTan(aN1.Crossed(aN2));
const Standard_Real aSqMagnFDer = aCTan.SquareMagnitude();
if(aSqMagnFDer < aSqSmallValue)
if (aSqMagnFDer < 1.0e-8)
{
// Use 1.0e-4 (instead of aSmallValue) to provide
// stable computation between different platforms.
// See test bugs modalg_7 bug29807_sc01
return -1.0;
}
Standard_Real aDuS1 = 0.0, aDvS1 = 0.0, aDuS2 = 0.0, aDvS2 = 1.0;
@@ -160,7 +165,8 @@ Standard_Real IntPatch_PointLine::
const Standard_Real aDetSyst = aB*aB - aA*aC;
if(Abs(aDetSyst) < aSmallValue)
{//Indetermined system solution
{
//Undetermined system solution
return -1.0;
}

View File

@@ -16,6 +16,7 @@
#include <IntPatch_SpecialPoints.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <ElCLib.hxx>
#include <Extrema_ExtPS.hxx>
#include <Extrema_GenLocateExtPS.hxx>
#include <Geom_ConicalSurface.hxx>
@@ -35,10 +36,12 @@ class FuncPreciseSeam: public math_FunctionSetWithDerivatives
public:
FuncPreciseSeam(const Handle(Adaptor3d_HSurface)& theQSurf, // quadric
const Handle(Adaptor3d_HSurface)& thePSurf, // another surface
const Standard_Boolean isTheUSeam):
const Standard_Boolean isTheUSeam,
const Standard_Real theIsoParameter):
myQSurf(theQSurf),
myPSurf(thePSurf),
mySeamCoordInd(isTheUSeam? 1 : 0) // Defines, U- or V-seam is used
mySeamCoordInd(isTheUSeam? 1 : 0), // Defines, U- or V-seam is used
myIsoParameter(theIsoParameter)
{
};
@@ -58,7 +61,7 @@ public:
try
{
const Standard_Integer anIndX = theX.Lower(), anIndF = theF.Lower();
Standard_Real aUV[] = {0.0, 0.0};
Standard_Real aUV[] = {myIsoParameter, myIsoParameter};
aUV[mySeamCoordInd] = theX(anIndX+2);
const gp_Pnt aP1(myPSurf->Value(theX(anIndX), theX(anIndX+1)));
const gp_Pnt aP2(myQSurf->Value(aUV[0], aUV[1]));
@@ -81,7 +84,7 @@ public:
const Standard_Integer anIndX = theX.Lower(),
anIndRD = theD.LowerRow(),
anIndCD = theD.LowerCol();
Standard_Real aUV[] = {0.0, 0.0};
Standard_Real aUV[] = {myIsoParameter, myIsoParameter};
aUV[mySeamCoordInd] = theX(anIndX+2);
gp_Pnt aPt;
@@ -131,10 +134,30 @@ private:
const Handle(Adaptor3d_HSurface)& myQSurf;
const Handle(Adaptor3d_HSurface)& myPSurf;
// 1 for U-coordinate, 0 - for V one.
//! 1 for U-coordinate, 0 - for V one.
const Standard_Integer mySeamCoordInd;
//! Constant parameter of iso-line
const Standard_Real myIsoParameter;
};
//=======================================================================
//function : GetTangent
//purpose : Computes tangent having the given parameter.
// See calling method(s) for detailed information
//=======================================================================
static inline void GetTangent(const Standard_Real theConeSemiAngle,
const Standard_Real theParameter,
gp_XYZ& theResult)
{
const Standard_Real aW2 = theParameter*theParameter;
const Standard_Real aCosUn = (1.0 - aW2) / (1.0 + aW2);
const Standard_Real aSinUn = 2.0*theParameter / (1.0 + aW2);
const Standard_Real aTanA = Tan(theConeSemiAngle);
theResult.SetCoord(aTanA*aCosUn, aTanA*aSinUn, 1.0);
}
//=======================================================================
//function : IsPointOnSurface
//purpose : Checks if thePt is in theSurf (with given tolerance).
@@ -281,6 +304,7 @@ Standard_Boolean IntPatch_SpecialPoints::
const Handle(Adaptor3d_HSurface)& thePSurf,
const IntSurf_PntOn2S& theRefPt,
const Standard_Boolean theIsU,
const Standard_Real theIsoParameter,
const math_Vector& theToler,
const math_Vector& theInitPoint,
const math_Vector& theInfBound,
@@ -292,7 +316,7 @@ Standard_Boolean IntPatch_SpecialPoints::
IntSurf::SetPeriod(theIsReversed ? thePSurf : theQSurf,
theIsReversed ? theQSurf : thePSurf, anArrOfPeriod);
FuncPreciseSeam aF(theQSurf, thePSurf, theIsU);
FuncPreciseSeam aF(theQSurf, thePSurf, theIsU, theIsoParameter);
math_FunctionSetRoot aSRF(aF, theToler);
aSRF.Perform(aF, theInitPoint, theInfBound, theSupBound);
@@ -323,6 +347,432 @@ Standard_Boolean IntPatch_SpecialPoints::
return Standard_True;
}
//=======================================================================
//function : ProcessSphere
//purpose :
/*
The intersection point (including the pole)
must be satisfied to the following system:
\left\{\begin{matrix}
R*\cos (U_{q})*\cos (V_{q})=S_{x}(U_{s},V_{s})
R*\sin (U_{q})*\cos (V_{q})=S_{y}(U_{s},V_{s})
R*\sin (V_{q})=S_{z}(U_{s},V_{s})
\end{matrix}\right,
where
R is the radius of the sphere;
@S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf;
@U_{s}@ and @V_{s}@ are parameters on the parametric surface;
@U_{q}@ and @V_{q}@ are equal to theUquad and theVquad correspondingly.
Consequently (from first two equations),
\left\{\begin{matrix}
\cos (U_{q}) = \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}
\sin (U_{q}) = \frac{S_{y}(U_{s},V_{s})}{R*\cos (V_{q})}
\end{matrix}\right.
For pole,
V_{q}=\pm \pi /2 \Rightarrow \cos (V_{q}) = 0 (denominator is equal to 0).
Therefore, computation U_{q} directly is impossibly.
Let @V_{q}@ tends to @\pm \pi /2@.
Then (indeterminate form is evaluated in accordance of L'Hospital rule),
\cos (U_{q}) = \lim_{V_{q} \to (\pi /2-0)}
\frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}=
-\lim_{V_{q} \to (\pi /2-0)}
\frac{\frac{\partial S_{x}}
{\partial U_{s}}*\frac{\mathrm{d} U_{s}}
{\mathrm{d} V_{q}}+\frac{\partial S_{x}}
{\partial V_{s}}*\frac{\mathrm{d} V_{s}}
{\mathrm{d} V_{q}}}{R*\sin (V_{q})} =
-\frac{1}{R}*\frac{\mathrm{d} U_{s}}
{\mathrm{d} V_{q}}*(\frac{\partial S_{x}}
{\partial U_{s}}+\frac{\partial S_{x}}
{\partial V_{s}}*\frac{\mathrm{d} V_{s}}
{\mathrm{d} U_{s}}) =
-\frac{1}{R}*\frac{\mathrm{d} V_{s}}
{\mathrm{d} V_{q}}*(\frac{\partial S_{x}}
{\partial U_{s}}*\frac{\mathrm{d} U_{s}}
{\mathrm{d} V_{s}}+\frac{\partial S_{x}}
{\partial V_{s}}).
Analogicaly for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@).
Let mean, that
\cos (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \cos (U_{q}) \left | _{V_{q} \to (\pi /2-0)}
\sin (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \sin (U_{q}) \left | _{V_{q} \to (\pi /2-0)}
From the 3rd equation of the system, we obtain
\frac{\mathrm{d} (R*\sin (V_{q}))}{\mathrm{d} V_{q}} =
\frac{\mathrm{d} S_{z}(U_{s},V_{s})}{\mathrm{d} V_{q}}
or
R*\cos (V_{q}) = \frac{\partial S_{z}}{\partial U_{s}}*
\frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}}
{\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}}.
If @V_{q}=\pm \pi /2@, then
\frac{\partial S_{z}}{\partial U_{s}}*
\frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}}
{\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}} = 0.
Consequently, if @\frac{\partial S_{z}}{\partial U_{s}} \neq 0 @ then
\frac{\mathrm{d} U_{s}}{\mathrm{d} V_{s}} =
-\frac{\frac{\partial S_{z}}{\partial V_{s}}}
{\frac{\partial S_{z}}{\partial U_{s}}}.
If @ \frac{\partial S_{z}}{\partial V_{s}} \neq 0 @ then
\frac{\mathrm{d} V_{s}}{\mathrm{d} U_{s}} =
-\frac{\frac{\partial S_{z}}{\partial U_{s}}}
{\frac{\partial S_{z}}{\partial V_{s}}}
Cases, when @ \frac{\partial S_{z}}{\partial U_{s}} =
\frac{\partial S_{z}}{\partial V_{s}} = 0 @ are not consider here.
The reason is written below.
*/
//=======================================================================
Standard_Boolean IntPatch_SpecialPoints::ProcessSphere(const IntSurf_PntOn2S& thePtIso,
const gp_Vec& theDUofPSurf,
const gp_Vec& theDVofPSurf,
const Standard_Boolean theIsReversed,
const Standard_Real theVquad,
Standard_Real& theUquad,
Standard_Boolean& theIsIsoChoosen)
{
theIsIsoChoosen = Standard_False;
//Vector with {@ \cos (U_{q}) @, @ \sin (U_{q}) @} coordinates.
//Ask to pay attention to the fact that this vector is always normalized.
gp_Vec2d aV1;
if ((Abs(theDUofPSurf.Z()) < Precision::PConfusion()) &&
(Abs(theDVofPSurf.Z()) < Precision::PConfusion()))
{
//Example of this case is an intersection of a plane with a sphere
//when the plane tangents the sphere in some pole (i.e. only one
//intersection point, not line). In this case, U-coordinate of the
//sphere is undefined (can be realy anything).
//Another reason is that we have tangent zone around the pole
//(see bug #26576).
//Computation of correct value of theUquad is impossible.
//Therefore, (in order to return something) we will consider
//the intersection line goes along some isoline in neighborhood
//of the pole.
#ifdef INTPATCH_ADDSPECIALPOINTS_DEBUG
cout << "Cannot find UV-coordinate for quadric in the pole."
" See considered comment above. IntPatch_SpecialPoints.cxx,"
" ProcessSphere(...)" << endl;
#endif
Standard_Real aUIso = 0.0, aVIso = 0.0;
if (theIsReversed)
thePtIso.ParametersOnS2(aUIso, aVIso);
else
thePtIso.ParametersOnS1(aUIso, aVIso);
theUquad = aUIso;
theIsIsoChoosen = Standard_True;
}
else
{
if (Abs(theDUofPSurf.Z()) > Abs(theDVofPSurf.Z()))
{
const Standard_Real aDusDvs = theDVofPSurf.Z() / theDUofPSurf.Z();
aV1.SetCoord(theDUofPSurf.X()*aDusDvs - theDVofPSurf.X(),
theDUofPSurf.Y()*aDusDvs - theDVofPSurf.Y());
}
else
{
const Standard_Real aDvsDus = theDUofPSurf.Z() / theDVofPSurf.Z();
aV1.SetCoord(theDVofPSurf.X()*aDvsDus - theDUofPSurf.X(),
theDVofPSurf.Y()*aDvsDus - theDUofPSurf.Y());
}
aV1.Normalize();
if (Abs(aV1.X()) > Abs(aV1.Y()))
theUquad = Sign(asin(aV1.Y()), theVquad);
else
theUquad = Sign(acos(aV1.X()), theVquad);
}
return Standard_True;
}
//=======================================================================
//function : ProcessCone
//purpose :
/*
The intersection point (including the pole)
must be satisfied to the following system:
\left\{\begin {matrix}
(V_{q}\sin(a) + R)*\cos(U_{q})) = S_{x}(U_{s}, V_{s})\\
(V_{q}\sin(a) + R)*\sin(U_{q})) = S_{y}(U_{s}, V_{s})\\
V_{q}\cos(a) = S_{z}(U_{s}, V_{s})
\end {matrix}\right,
where
R is the radius of the cone;
a is its semi-angle;
@S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf;
@U_{s}@ and @V_{s}@ are parameters on the parametric surface;
@U_{q}@ and @V_{q}@ are equal to theUquad and theVquad correspondingly.
Consequently (from first two equations),
\left\{\begin{matrix}
\cos(U_{q})=\frac{S_{x}(U_{s},V_{s})}{(V_{q}\sin(a)+R)}\\
\sin(U_{q})=\frac{S_{y}(U_{s}, V_{s})}{(V_{q}\sin(a)+R)}
\end{matrix}\right.
For pole, the denominator of these two equations is equal to 0.
Therefore, computation U_{q} directly is impossibly.
Let @V_{q}@ tends to @\frac{-R}{\sin(a)})@.
Then (indeterminate form is evaluated in accordance of L'Hospital rule),
\cos (U_{q}) =
\lim_{V_{q} \to (\frac{-R}{\sin(a)})}\frac{S_{x}(U_{s},V_{s})}{(V_{q}\sin(a)+R)}=
\frac{1}{\sin(a)}* \lim_{V_{q} \to (\frac{-R}{\sin(a)})}\frac{dU_{s}}{dV_{q}}*
(\frac{\partial S_{x}}{\partial U_{s}}+\frac{\partial S_{x}}{\partial V_{s}}*
\frac{dV_{s}}{dU_{s}})=
\frac{1}{\sin(a)}* \lim_{V_{q} \to (\frac{-R}{\sin(a)})}\frac{dV_{s}}{dV_{q}}*
(\frac{\partial S_{x}}{\partial U_{s}}*
\frac{dU_{s}}{dV_{s}}+\frac{\partial S_{x}}{\partial V_{s}})
Analogically for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@).
After differentiating 3rd equation of the system, we will obtain
\cos(a)=\frac{dS_{z}}{dV_{q}}=\frac{dU_{s}}{dV_{q}}*
(\frac{\partial S_{z}}{\partial U_{s}}+\frac{\partial S_{z}}{\partial V_{s}}*
\frac{dV_{s}}{dU_{s}})
or
\frac{dU_{s}}{dV_{q}}=\frac{\cos(a)}{\frac{\partial S_{z}}{\partial U_{s}}+
\frac{\partial S_{z}}{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}
After substituting we will obtain
\cos (U_{q}) =
\cot(a)*\frac{\frac{\partial S_{x}}{\partial U_{s}}+\frac{\partial S_{x}}
{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}{\frac{\partial S_{z}}
{\partial U_{s}}+\frac{\partial S_{z}}{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}
\sin (U_{q}) =
\cot(a)*\frac{\frac{\partial S_{y}}{\partial U_{s}}+\frac{\partial S_{y}}
{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}{\frac{\partial S_{z}}
{\partial U_{s}}+\frac{\partial S_{z}}{\partial V_{s}}*\frac{dV_{s}}{dU_{s}}}
So, we have obtained vector with coordinates {@ \cos (U_{q}) @, @ \sin (U_{q}) @}.
Ask to pay attention to the fact that this vector is always normalized.
And after normalization this vector will have coordinates
{\cos (U_{q}), \sin (U_{q})} = {dS_{x}, dS_{y}}.Normalized().
It means that we have to compute a tangent to the intersection curve in
the cone apex point. After that, just take its X- and Y-coordinates.
However, we have to compute derivative @\frac{dV_{s}}{dU_{s}}@ in order
to compute this vector. In order to find this derivative, we use the
information about direction of tangent to the intersection curve.
This tangent will be directed along the cone generatrix obtained by intersection
of the cone with a plane tangent to 2nd (intersected) surface.
*/
//=======================================================================
Standard_Boolean IntPatch_SpecialPoints::ProcessCone(const IntSurf_PntOn2S& thePtIso,
const gp_Vec& theDUofPSurf,
const gp_Vec& theDVofPSurf,
const gp_Cone& theCone,
const Standard_Boolean theIsReversed,
Standard_Real& theUquad,
Standard_Boolean& theIsIsoChoosen)
{
theIsIsoChoosen = Standard_False;
// A plane tangent to 2nd (intersected) surface.
// Its normal.
const gp_XYZ aTgPlaneZ(theDUofPSurf.Crossed(theDVofPSurf).XYZ());
const Standard_Real aSqModTg = aTgPlaneZ.SquareModulus();
if (aSqModTg < Precision::SquareConfusion())
{
theIsIsoChoosen = Standard_True;
}
gp_XYZ aTgILine[2];
const Standard_Integer aNbTangent = !theIsIsoChoosen?
GetTangentToIntLineForCone(theCone.SemiAngle(),
aTgPlaneZ.Divided(Sqrt(aSqModTg)),
aTgILine) : 0;
if (aNbTangent == 0)
{
theIsIsoChoosen = Standard_True;
}
else
{
const Standard_Real aPeriod = M_PI + M_PI;
Standard_Real aUIso = 0.0, aVIso = 0.0;
if (theIsReversed)
thePtIso.ParametersOnS2(aUIso, aVIso);
else
thePtIso.ParametersOnS1(aUIso, aVIso);
aUIso = ElCLib::InPeriod(aUIso, 0.0, aPeriod);
// Sought U-parameter in the apex point
// For 2 possible parameters value,
// one will be chosen which is nearer
// to aUIso. Following variables will help to chose.
Standard_Real aMinDelta = RealLast();
for (Standard_Integer anIdx = 0; anIdx < aNbTangent; anIdx++)
{
// Vector {@\cos(a), \sin(a)@}
gp_Vec2d aVecCS(aTgILine[anIdx].X(), aTgILine[anIdx].Y());
const Standard_Real aSqMod = aVecCS.SquareMagnitude();
if (aSqMod < Precision::SquareConfusion())
{
theIsIsoChoosen = Standard_True;
break;
}
// Normalize
aVecCS.Divide(Sqrt(aSqMod));
// Angle in range [0, PI/2]
Standard_Real anUq = (Abs(aVecCS.X()) < Abs(aVecCS.Y())) ? ACos(Abs(aVecCS.X())) : ASin(Abs(aVecCS.Y()));
// Convert angles to the range [0, 2*PI]
if (aVecCS.Y() < 0.0)
{
if (aVecCS.X() > 0.0)
{
anUq = -anUq;
}
else
{
anUq += M_PI;
}
}
else if (aVecCS.X() < 0.0)
{
anUq = M_PI - anUq;
}
//Select the parameter the nearest to aUIso
anUq = ElCLib::InPeriod(anUq, 0.0, aPeriod);
Standard_Real aDelta = Abs(anUq - aUIso);
if (aDelta > M_PI)
aDelta = aPeriod - aDelta;
if (aDelta < aMinDelta)
{
aMinDelta = aDelta;
theUquad = anUq;
}
}
}
if (theIsIsoChoosen)
{
#ifdef INTPATCH_ADDSPECIALPOINTS_DEBUG
cout << "Cannot find UV-coordinate for quadric in the pole."
" IntPatch_AddSpecialPoints.cxx, ProcessCone(...)" << endl;
#endif
theIsIsoChoosen = Standard_True;
Standard_Real aUIso = 0.0, aVIso = 0.0;
if (theIsReversed)
thePtIso.ParametersOnS2(aUIso, aVIso);
else
thePtIso.ParametersOnS1(aUIso, aVIso);
theUquad = aUIso;
return Standard_True;
}
else
{
return Standard_True;
}
//return Standard_False;
}
//=======================================================================
//function : GetTangentToIntLineForCone
//purpose : The following conditions must be satisfied:
//1. The cone is represented in its canonical form.
//2. The plane goes through the cone apex and has the normal vector thePlnNormal.
//3. Vector thePlnNormal has already been normalized
/*
Let us enter the new coordinate system where the origin will be in the cone apex
and axes are the same as in World-Coordinate-System (WCS).
There the horizontal plane (which is parallel XY-plane) with the origin
(0, 0, 1) will intersect the cone by the circle with center (0, 0, 1),
direction {0, 0, 1} and radius tg(a) where a is the cone semi-angle.
Its equation will be
\left\{\begin{matrix}
x(U_{n}) = \tan(a)*\cos(U_{n}) = \tan(a)*\frac{1-\tan^{2}(U_{n}/2)}{1+\tan^{2}(U_{n}/2)}\\
y(U_{n}) = \tan(a)*\sin (U_{n}) = \tan(a)*\frac{2*\tan(U_{n}/2)}{1+\tan^{2}(U_{n}/2)}\\
z(U_{n}) = 1
\end{matrix}\right.
The given plane has (in this coordinate system) location (0, 0, 0) and
the same normal thePlnNormal=={nx,ny,nz}. Its equation is:
nx*x+ny*y+nz*z==0
After substitution circle's equation to the plane's equation
we will obtain a quadratic equation
aA*w^2 + 2*aB*w + aC = 0.
*/
//=======================================================================
Standard_Integer IntPatch_SpecialPoints::GetTangentToIntLineForCone(const Standard_Real theConeSemiAngle,
const gp_XYZ& thePlnNormal,
gp_XYZ theResult[2])
{
const Standard_Real aNullTol = Epsilon(1.0);
const Standard_Real aTanA = Tan(theConeSemiAngle);
const Standard_Real aA = thePlnNormal.Z() / aTanA - thePlnNormal.X();
const Standard_Real aB = thePlnNormal.Y();
const Standard_Real aC = thePlnNormal.Z() / aTanA + thePlnNormal.X();
if (Abs(aA) < aNullTol)
{
if (Abs(aB) > aNullTol)
{
//The plane goes along the cone generatrix.
GetTangent(theConeSemiAngle, -aC / (aB + aB), theResult[0]);
return 1;
}
//The cone and the plane have only one common point.
//It is the cone apex.
return 0;
}
//Discriminant of this equation is equal to
Standard_Real aDiscr = thePlnNormal.Z() / Sin(theConeSemiAngle);
aDiscr = 1.0 - aDiscr*aDiscr;
if (Abs(aDiscr) < aNullTol)
{
//The plane goes along the cone generatrix.
// Attention! Mathematically, this cond. is equivalent to
// above processed one (Abs(aA) < aNullTol && (Abs(aB) > aNullTol)).
// However, we separate this branch in order to eliminate numerical
// instability.
GetTangent(theConeSemiAngle, -aB / aA, theResult[0]);
return 1;
}
else if (aDiscr > 0.0)
{
const Standard_Real aRD = Sqrt(aDiscr);
GetTangent(theConeSemiAngle, (-aB+aRD)/aA, theResult[0]);
GetTangent(theConeSemiAngle, (-aB-aRD)/aA, theResult[1]);
return 2;
}
// We will never come here.
return 0;
}
//=======================================================================
//function : AddSingularPole
//purpose : theQSurf is the surface possibly containing special point,
@@ -333,22 +783,11 @@ Standard_Boolean IntPatch_SpecialPoints::
AddSingularPole(const Handle(Adaptor3d_HSurface)& theQSurf,
const Handle(Adaptor3d_HSurface)& thePSurf,
const IntSurf_PntOn2S& thePtIso,
const Standard_Real theTol,
IntPatch_Point& theVertex,
IntSurf_PntOn2S& theAddedPoint,
IntSurf_PntOn2S& theAddedPoint,
const Standard_Boolean theIsReversed,
const Standard_Boolean theIsReqRefCheck)
{
const Standard_Real aUpPeriod = thePSurf->IsUPeriodic() ? thePSurf->UPeriod() : 0.0;
const Standard_Real aUqPeriod = theQSurf->IsUPeriodic() ? theQSurf->UPeriod() : 0.0;
const Standard_Real aVpPeriod = thePSurf->IsVPeriodic() ? thePSurf->VPeriod() : 0.0;
const Standard_Real aVqPeriod = theQSurf->IsVPeriodic() ? theQSurf->VPeriod() : 0.0;
const Standard_Real anArrOfPeriod[4] = {theIsReversed? aUpPeriod : aUqPeriod,
theIsReversed? aVpPeriod : aVqPeriod,
theIsReversed? aUqPeriod : aUpPeriod,
theIsReversed? aVqPeriod : aVpPeriod};
//On parametric
Standard_Real aU0 = 0.0, aV0 = 0.0;
//aPQuad is Pole
@@ -379,13 +818,13 @@ Standard_Boolean IntPatch_SpecialPoints::
}
theQSurf->D0(aUquad, aVquad, aPQuad);
if (theIsReqRefCheck && (aPQuad.SquareDistance(theVertex.Value()) >= theTol*theTol))
const Standard_Real aTol = theVertex.Tolerance();
if (theIsReqRefCheck && (aPQuad.SquareDistance(theVertex.Value()) >= aTol*aTol))
{
return Standard_False;
}
if(!IsPointOnSurface(thePSurf, aPQuad, theTol, aP0, aU0, aV0))
if (!IsPointOnSurface(thePSurf, aPQuad, aTol, aP0, aU0, aV0))
{
return Standard_False;
}
@@ -398,25 +837,20 @@ Standard_Boolean IntPatch_SpecialPoints::
else
theAddedPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), aUquad, aVquad, aU0, aV0);
Standard_Boolean isSame = Standard_False;
if (theAddedPoint.IsSame(theVertex.PntOn2S(), Precision::Confusion()))
{
isSame = Standard_True;
}
const Standard_Boolean isSame = theAddedPoint.IsSame(theVertex.PntOn2S(),
Precision::Confusion());
//Found pole does not exist in the Walking-line
//It must be added there (with correct 2D-parameters)
//2D-parameters of theparametric surface have already been found (aU0, aV0).
//2D-parameters of thePSurf surface have already been found (aU0, aV0).
//Let find 2D-parameters on the quadric.
//The algorithm depends on the type of the quadric. Here we consider a Sphere only.
//Analogical result can be made for another types (e.g. cone, but formulas will
//be different) in case of need.
//The algorithm depends on the type of the quadric.
//Here we consider a Sphere and cone only.
//First of all, we need in adjusting thePSurf in the coordinate system of the Sphere
//(in order to make the equation of the sphere maximal simple). However, as it will be
//First of all, we need in adjusting thePSurf in the coordinate system of the Sphere/Cone
//(in order to make its equation maximal simple). However, as it will be
//shown later, thePSurf is used in algorithm in order to get its derivatives.
//Therefore, for improving performance, transformation of these vectors is enough
//(there is no point in transformation of full surface).
@@ -439,146 +873,19 @@ Standard_Boolean IntPatch_SpecialPoints::
if(theQSurf->GetType() == GeomAbs_Sphere)
{
//The intersection point (including the pole)
//must be satisfied to the following system:
// \left\{\begin{matrix}
// R*\cos (U_{q})*\cos (V_{q})=S_{x}(U_{s},V_{s})
// R*\sin (U_{q})*\cos (V_{q})=S_{y}(U_{s},V_{s})
// R*\sin (V_{q})=S_{z}(U_{s},V_{s})
// \end{matrix}\right,
//where
// R is the radius of the sphere;
// @S_{x}@, @S_{y}@ and @S_{z}@ are X, Y and Z-coordinates of thePSurf;
// @U_{s}@ and @V_{s}@ are equal to aU0 and aV0 corespondingly;
// @U_{q}@ and @V_{q}@ are equal to aUquad and aVquad corespondingly.
//Consequently (from first two equations),
// \left\{\begin{matrix}
// \cos (U_{q}) = \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}
// \sin (U_{q}) = \frac{S_{y}(U_{s},V_{s})}{R*\cos (V_{q})}
// \end{matrix}\right.
//For pole,
// V_{q}=\pm \pi /2 \Rightarrow \cos (V_{q}) = 0 (denominator is equal to 0).
//Therefore, computation U_{q} directly is impossibly.
//
//Let @V_{q}@ tends to @\pm \pi /2@.
//Then (indeterminate form is evaluated in accordance of L'Hospital rule),
// \cos (U_{q}) = \lim_{V_{q} \to (\pi /2-0)}
// \frac{S_{x}(U_{s},V_{s})}{R*\cos (V_{q})}=
// -\lim_{V_{q} \to (\pi /2-0)}
// \frac{\frac{\partial S_{x}}
// {\partial U_{s}}*\frac{\mathrm{d} U_{s}}
// {\mathrm{d} V_{q}}+\frac{\partial S_{x}}
// {\partial V_{s}}*\frac{\mathrm{d} V_{s}}
// {\mathrm{d} V_{q}}}{R*\sin (V_{q})} =
// -\frac{1}{R}*\frac{\mathrm{d} U_{s}}
// {\mathrm{d} V_{q}}*(\frac{\partial S_{x}}
// {\partial U_{s}}+\frac{\partial S_{x}}
// {\partial V_{s}}*\frac{\mathrm{d} V_{s}}
// {\mathrm{d} U_{s}}) =
// -\frac{1}{R}*\frac{\mathrm{d} V_{s}}
// {\mathrm{d} V_{q}}*(\frac{\partial S_{x}}
// {\partial U_{s}}*\frac{\mathrm{d} U_{s}}
// {\mathrm{d} V_{s}}+\frac{\partial S_{x}}
// {\partial V_{s}}).
//Analogicaly for @\sin (U_{q})@ (@S_{x}@ is substituted to @S_{y}@).
//Let mean, that
// \cos (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \cos (U_{q}) \left | _{V_{q} \to (\pi /2-0)}
// \sin (U_{q}) \left | _{V_{q} \to (-\pi /2+0)} = \sin (U_{q}) \left | _{V_{q} \to (\pi /2-0)}
//From the 3rd equation of the system, we obtain
// \frac{\mathrm{d} (R*\sin (V_{q}))}{\mathrm{d} V_{q}} =
// \frac{\mathrm{d} S_{z}(U_{s},V_{s})}{\mathrm{d} V_{q}}
//or
// R*\cos (V_{q}) = \frac{\partial S_{z}}{\partial U_{s}}*
// \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}}
// {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}}.
//If @V_{q}=\pm \pi /2@, then
// \frac{\partial S_{z}}{\partial U_{s}}*
// \frac{\mathrm{d} U_{s}} {\mathrm{d} V_{q}}+\frac{\partial S_{z}}
// {\partial V_{s}}*\frac{\mathrm{d} V_{s}}{\mathrm{d} V_{q}} = 0.
//Consequently, if @\frac{\partial S_{z}}{\partial U_{s}} \neq 0 @ then
// \frac{\mathrm{d} U_{s}}{\mathrm{d} V_{s}} =
// -\frac{\frac{\partial S_{z}}{\partial V_{s}}}
// {\frac{\partial S_{z}}{\partial U_{s}}}.
//If @ \frac{\partial S_{z}}{\partial V_{s}} \neq 0 @ then
// \frac{\mathrm{d} V_{s}}{\mathrm{d} U_{s}} =
// -\frac{\frac{\partial S_{z}}{\partial U_{s}}}
// {\frac{\partial S_{z}}{\partial V_{s}}}
//Cases, when @ \frac{\partial S_{z}}{\partial U_{s}} =
//\frac{\partial S_{z}}{\partial V_{s}} = 0 @ are not consider here.
//The reason is written below.
//Vector with {@ \cos (U_{q}) @, @ \sin (U_{q}) @} coordinates.
//Ask to pay attention to the fact that this vector is always normalyzed.
gp_Vec2d aV1;
if( (Abs(aVecDu.Z()) < Precision::PConfusion()) &&
(Abs(aVecDv.Z()) < Precision::PConfusion()))
if (!ProcessSphere(thePtIso, aVecDu, aVecDv, theIsReversed,
aVquad, aUquad, isIsoChoosen))
{
//Example of this case is an intersection of a plane with a sphere
//when the plane tangents the sphere in some pole (i.e. only one
//intersection point, not line). In this case, U-coordinate of the
//sphere is undefined (can be realy anything).
//Another reason is that we have tangent zone around the pole
//(see bug #26576).
//Computation of correct value of aUquad is impossible.
//Therefore, (in oreder to return something) we will consider
//the intersection line goes along some isoline in neighbourhood
//of the pole.
#ifdef INTPATCH_ADDSPECIALPOINTS_DEBUG
cout << "Cannot find UV-coordinate for quadric in the pole."
" See considered comment above. IntPatch_AddSpecialPoints.cxx,"
" AddSingularPole(...)" << endl;
#endif
Standard_Real aUIso = 0.0, aVIso = 0.0;
if(theIsReversed)
thePtIso.ParametersOnS2(aUIso, aVIso);
else
thePtIso.ParametersOnS1(aUIso, aVIso);
aUquad = aUIso;
isIsoChoosen = Standard_True;
}
else
{
if(Abs(aVecDu.Z()) > Abs(aVecDv.Z()))
{
const Standard_Real aDusDvs = aVecDv.Z()/aVecDu.Z();
aV1.SetCoord( aVecDu.X()*aDusDvs - aVecDv.X(),
aVecDu.Y()*aDusDvs - aVecDv.Y());
}
else
{
const Standard_Real aDvsDus = aVecDu.Z()/aVecDv.Z();
aV1.SetCoord( aVecDv.X()*aDvsDus - aVecDu.X(),
aVecDv.Y()*aDvsDus - aVecDu.Y());
}
aV1.Normalize();
if(Abs(aV1.X()) > Abs(aV1.Y()))
aUquad = Sign(asin(aV1.Y()), aVquad);
else
aUquad = Sign(acos(aV1.X()), aVquad);
return Standard_False;
}
}
else //if(theQSurf->GetType() == GeomAbs_Cone)
{
// This case is not processed. However,
// it can be done using the same algorithm
// as for sphere (formulas will be different).
return Standard_False;
if (!ProcessCone(thePtIso, aVecDu, aVecDv, theQSurf->Cone(),
theIsReversed, aUquad, isIsoChoosen))
{
return Standard_False;
}
}
if(theIsReversed)
@@ -594,6 +901,16 @@ Standard_Boolean IntPatch_SpecialPoints::
if (!isIsoChoosen)
{
Standard_Real anArrOfPeriod[4];
if (theIsReversed)
{
IntSurf::SetPeriod(thePSurf, theQSurf, anArrOfPeriod);
}
else
{
IntSurf::SetPeriod(theQSurf, thePSurf, anArrOfPeriod);
}
AdjustPointAndVertex(theVertex.PntOn2S(), anArrOfPeriod, theAddedPoint);
}
else
@@ -606,7 +923,32 @@ Standard_Boolean IntPatch_SpecialPoints::
//=======================================================================
//function : ContinueAfterSpecialPoint
//purpose :
//purpose : If the last point of the line is the pole of the quadric then
// the Walking-line has been broken in this point.
// However, new line must start from this point. Here we must
// find 2D-coordinates of "this new" point.
/*
The inters. line in the neighborhood of the Apex/Pole(s) can be
approximated by the intersection result of the Cone/Sphere with
the plane going through the Apex/Pole and being tangent to the
2nd intersected surface. This intersection result is well known.
In case of sphere, the inters. result is a circle.
If we go along this circle and across the Pole then U-parameter of
the sphere (@U_{q}@) will change to +/-PI.
In case of cone, the inters. result is two intersected lines (which
can be merged to one in a special case when the plane goes along
some generatrix of the cone). The direction of these lines
are computed by GetTangentToIntLineForCone(...) method).
When the real (not lines) inters. curve goes through the cone apex then
two variants are possible:
a) The tangent line to the inters. curve will be left. In this case
U-parameter of the cone (@U_{q}@) will be change to +/-PI.
b) Another line (as inters. result of cone + plane) will tangent
to the inters. curve. In this case @U_{q}@ must be recomputed.
*/
//=======================================================================
Standard_Boolean IntPatch_SpecialPoints::
ContinueAfterSpecialPoint(const Handle(Adaptor3d_HSurface)& theQSurf,
@@ -620,36 +962,63 @@ Standard_Boolean IntPatch_SpecialPoints::
if(theSPType == IntPatch_SPntNone)
return Standard_False;
//If the last point of the line is the pole of the quadric.
//In this case, Walking-line has been broken in this point.
//However, new line must start from this point. Here we must
//find its 2D-coordinates.
//For sphere and cone, some intersection point is satisfied to the system
// \cos(U_{q}) = S_{x}(U_{s},V_{s})/F(V_{q})
// \sin(U_{q}) = S_{y}(U_{s},V_{s})/F(V_{q})
//where
// @S_{x}@, @S_{y}@ are X and Y-coordinates of thePSurf;
// @U_{s}@ and @V_{s}@ are UV-parameters on thePSurf;
// @U_{q}@ and @V_{q}@ are UV-parameters on theQSurf;
// @F(V_{q}) @ is some function, which value independs on @U_{q}@
// (form of this function depends on the type of the quadric).
//When we go through the pole/apex, the function @F(V_{q}) @ changes sign.
//Therefore, some cases are possible, when only @\cos(U_{q}) @ or
//only @ \sin(U_{q}) @ change sign.
//Consequently, when the line goes throug the pole, @U_{q}@ can be
//changed on @\pi /2 @ (but not less).
if(theNewPoint.IsSame(theRefPt, Precision::Confusion(), theTol2D))
{
return Standard_False;
}
//Here, in case of pole/apex adding, we forbid "jumping" between two neighbor
//Walking-point with step greater than pi/4
if ((theSPType == IntPatch_SPntPole) && (theQSurf->GetType() == GeomAbs_Cone))
{
//Check if the condition b) is satisfied.
//Repeat the same steps as in
//IntPatch_SpecialPoints::AddSingularPole(...) method.
//On parametric
Standard_Real aU0 = 0.0, aV0 = 0.0;
//On quadric
Standard_Real aUquad = 0.0, aVquad = 0.0;
if (theIsReversed)
theNewPoint.Parameters(aU0, aV0, aUquad, aVquad);
else
theNewPoint.Parameters(aUquad, aVquad, aU0, aV0);
gp_Pnt aPtemp;
gp_Vec aVecDu, aVecDv;
thePSurf->D1(aU0, aV0, aPtemp, aVecDu, aVecDv);
//Transforms parametric surface in coordinate-system of the quadric
gp_Trsf aTr;
aTr.SetTransformation(theQSurf->Cone().Position());
//Derivatives of transformed thePSurf
aVecDu.Transform(aTr);
aVecDv.Transform(aTr);
Standard_Boolean isIsoChoosen = Standard_False;
ProcessCone(theRefPt, aVecDu, aVecDv, theQSurf->Cone(),
theIsReversed, aUquad, isIsoChoosen);
theNewPoint.SetValue(!theIsReversed, aUquad, aVquad);
}
//As it has already been said, in case of going through the Pole/Apex,
//U-parameter of the quadric surface will change to +/-PI. This rule has some
//exceptions:
//1. When 2nd surface has C0-continuity in the point common with the Apex/Pole.
// In this case, the tangent line to the intersection curve after the Apex/Pole
// must be totally recomputed according to the new derivatives of the 2nd surface.
// Currently, it is not implemented but will be able to be done after the
// corresponding demand.
//2. The inters. curve has C1 continuity but huge curvature in the point common with
// the Apex/Pole. Existing inters. algorithm does not allow putting many points
// near to the Apex/Pole in order to cover this "sharp" piece of the inters. curve.
// Therefore, we use adjusting U-parameter of the quadric surface with
// period PI/2 instead of 2PI. It does not have any mathematical idea
// but allows creating WLine with more or less uniform distributed points.
// In other words, we forbid "jumping" between two neighbor Walking-points
// with step greater than PI/4.
const Standard_Real aPeriod = (theSPType == IntPatch_SPntPole)? M_PI_2 : 2.0*M_PI;
const Standard_Real aUpPeriod = thePSurf->IsUPeriodic() ? thePSurf->UPeriod() : 0.0;

View File

@@ -24,6 +24,9 @@
#include <Standard_Handle.hxx>
class Adaptor3d_HSurface;
class gp_Cone;
class gp_Vec;
class gp_XYZ;
class IntPatch_Point;
class IntSurf_PntOn2S;
class math_Vector;
@@ -51,12 +54,18 @@ public:
//! theRefPt is used to correct adjusting parameters.
//! If theIsReversed is TRUE then theQSurf corresponds to the
//! second (otherwise, the first) surface while forming
//! intersection point IntSurf_PntOn2S.
//! intersection point IntSurf_PntOn2S.
//! All math_Vector-objects must be filled as follows:
//! [1] - U-parameter of thePSurf;
//! [2] - V-parameter of thePSurf;
//! [3] - U- (if V-isoline is considered) or V-parameter
//! (if U-isoline is considered) of theQSurf.
Standard_EXPORT static Standard_Boolean
AddPointOnUorVIso(const Handle(Adaptor3d_HSurface)& theQSurf,
const Handle(Adaptor3d_HSurface)& thePSurf,
const IntSurf_PntOn2S& theRefPt,
const Standard_Boolean theIsU,
const Standard_Real theIsoParameter,
const math_Vector& theToler,
const math_Vector& theInitPoint,
const math_Vector& theInfBound,
@@ -80,7 +89,6 @@ public:
AddSingularPole(const Handle(Adaptor3d_HSurface)& theQSurf,
const Handle(Adaptor3d_HSurface)& thePSurf,
const IntSurf_PntOn2S& thePtIso,
const Standard_Real theTol3d,
IntPatch_Point& theVertex,
IntSurf_PntOn2S& theAddedPoint,
const Standard_Boolean theIsReversed =
@@ -120,6 +128,39 @@ public:
const Standard_Real theArrPeriods[4],
IntSurf_PntOn2S &theNewPoint,
IntPatch_Point* const theVertex = 0);
protected:
//! Computes "special point" in the sphere
//! The parameter will be found in the range [0, 2*PI].
//! Therefore it must be adjusted to valid range by
//! the high-level algorithm
static Standard_EXPORT Standard_Boolean ProcessSphere(const IntSurf_PntOn2S& thePtIso,
const gp_Vec& theDUofPSurf,
const gp_Vec& theDVofPSurf,
const Standard_Boolean theIsReversed,
const Standard_Real theVquad,
Standard_Real& theUquad,
Standard_Boolean& theIsIsoChoosen);
//! Computes "special point" in the cone.
//! The parameter will be found in the range [0, 2*PI].
//! Therefore it must be adjusted to valid range by
//! the high-level algorithm.
static Standard_EXPORT Standard_Boolean ProcessCone(const IntSurf_PntOn2S& thePtIso,
const gp_Vec& theDUofPSurf,
const gp_Vec& theDVofPSurf,
const gp_Cone& theCone,
const Standard_Boolean theIsReversed,
Standard_Real& theUquad,
Standard_Boolean& theIsIsoChoosen);
//! Computes vector tangent to the intersection line in cone apex.
//! There exist not more than 2 tangent. They will be stores in theResult vector.
//! Returns the number of found tangents.
//! thePlnNormal is the normalized vector of the normal to the plane intersected the cone.
static Standard_EXPORT Standard_Integer GetTangentToIntLineForCone(const Standard_Real theConeSemiAngle,
const gp_XYZ& thePlnNormal,
gp_XYZ theResult[2]);
};
#endif // _IntPatch_AddSpecialPoints_HeaderFile

View File

@@ -41,7 +41,8 @@ enum IntPatchWT_WLsConnectionType
{
IntPatchWT_NotConnected,
IntPatchWT_Singular,
IntPatchWT_EachOther
IntPatchWT_Common,
IntPatchWT_ReqExtend
};
//=======================================================================
@@ -849,17 +850,23 @@ static IntPatchWT_WLsConnectionType
const Standard_Real* const theArrPeriods)
{
const Standard_Real aSqToler = theToler3D*theToler3D;
IntPatchWT_WLsConnectionType aRetVal = IntPatchWT_NotConnected;
if(theVec3.SquareMagnitude() <= aSqToler)
{
return IntPatchWT_NotConnected;
if ((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle))
{
return aRetVal;
}
else
{
aRetVal = IntPatchWT_Common;
}
}
if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) ||
(theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) ||
(theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle))
else if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) ||
(theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) ||
(theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle))
{
return IntPatchWT_NotConnected;
return aRetVal;
}
const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
@@ -973,7 +980,12 @@ static IntPatchWT_WLsConnectionType
return IntPatchWT_Singular;
}
return IntPatchWT_EachOther;
if (aRetVal == IntPatchWT_Common)
{
return IntPatchWT_Common;
}
return IntPatchWT_ReqExtend;
}
//=======================================================================
@@ -984,12 +996,47 @@ static IntPatchWT_WLsConnectionType
Standard_Boolean CheckArgumentsToJoin(const Handle(Adaptor3d_HSurface)& theS1,
const Handle(Adaptor3d_HSurface)& theS2,
const IntSurf_PntOn2S& thePnt,
const gp_Pnt& theP1,
const gp_Pnt& theP2,
const gp_Pnt& theP3,
const Standard_Real theMinRad)
{
const Standard_Real aRad =
IntPatch_PointLine::CurvatureRadiusOfIntersLine(theS1, theS2, thePnt);
const Standard_Real aRad =
IntPatch_PointLine::CurvatureRadiusOfIntersLine(theS1, theS2, thePnt);
return (aRad > theMinRad);
if (aRad > theMinRad)
{
return Standard_True;
}
else if (aRad > 0.0)
{
return Standard_False;
}
// Curvature radius cannot be computed.
// Check smoothness of polygon.
// theP2
// *
// |
// |
// * o *
// theP1 O theP3
//Joining is enabled if two conditions are satisfied together:
// 1. Angle (theP1, theP2, theP3) is quite big;
// 2. Modulus of perpendicular (O->theP2) to the segment (theP1->theP3)
// is less than 0.01*<modulus of this segment>.
const gp_Vec aV12f(theP1, theP2), aV12l(theP2, theP3);
if (aV12f.Angle(aV12l) > IntPatch_WLineTool::myMaxConcatAngle)
return Standard_False;
const gp_Vec aV13(theP1, theP3);
const Standard_Real aSq13 = aV13.SquareMagnitude();
return (aV12f.CrossSquareMagnitude(aV13) < 1.0e-4*aSq13*aSq13);
}
//=======================================================================
@@ -1482,18 +1529,14 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
const Standard_Real aSqMinFDist = Min(aSqDistF, aSqDistL);
if (aSqMinFDist < Precision::SquareConfusion())
{
if (CheckArgumentsToJoin(theS1, theS2, aPntFWL1, aMinRad))
const Standard_Boolean isFM = (aSqDistF < aSqDistL);
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
aWLine2->Point(aNbPntsWL2 - 1);
if (!IsSeamOrBound(aPt1, aPt2, aPntFWL1,
anArrPeriods, anArrFBonds, anArrLBonds))
{
const Standard_Boolean isFM = (aSqDistF < aSqDistL);
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
aWLine2->Point(aNbPntsWL2 - 1);
if (!IsSeamOrBound(aPt1, aPt2, aPntFWL1,
anArrPeriods, anArrFBonds, anArrLBonds))
{
isFirstConnected = Standard_True;
}
isFirstConnected = Standard_True;
}
}
@@ -1503,18 +1546,14 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
const Standard_Real aSqMinLDist = Min(aSqDistF, aSqDistL);
if (aSqMinLDist < Precision::SquareConfusion())
{
if (CheckArgumentsToJoin(theS1, theS2, aPntLWL1, aMinRad))
const Standard_Boolean isFM = (aSqDistF < aSqDistL);
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
aWLine2->Point(aNbPntsWL2 - 1);
if (!IsSeamOrBound(aPt1, aPt2, aPntLWL1,
anArrPeriods, anArrFBonds, anArrLBonds))
{
const Standard_Boolean isFM = (aSqDistF < aSqDistL);
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
aWLine2->Point(aNbPntsWL2 - 1);
if (!IsSeamOrBound(aPt1, aPt2, aPntLWL1,
anArrPeriods, anArrFBonds, anArrLBonds))
{
isLastConnected = Standard_True;
}
isLastConnected = Standard_True;
}
}
@@ -1549,15 +1588,29 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
const Standard_Integer anIndexWL2 = isFirstConnected ? aListFC.First() : aListLC.First();
Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(anIndexWL2)));
const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
aWLine1->ClearVertexes();
const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
if (isFirstConnected)
{
if (aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
const Standard_Real aSqDistF = aPntFWL1.Value().SquareDistance(aPntFWL2.Value());
const Standard_Real aSqDistL = aPntFWL1.Value().SquareDistance(aPntLWL2.Value());
const Standard_Boolean isFM = (aSqDistF < aSqDistL);
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
aWLine2->Point(aNbPntsWL2 - 1);
if (!CheckArgumentsToJoin(theS1, theS2, aPntFWL1, aPt1.Value(),
aPntFWL1.Value(), aPt2.Value(), aMinRad))
{
continue;
}
aWLine1->ClearVertexes();
if (isFM)
{
//First-First-connection
for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
@@ -1578,10 +1631,26 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
}
else //if (isLastConnected)
{
if (aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
const Standard_Real aSqDistF = aPntLWL1.Value().SquareDistance(aPntFWL2.Value());
const Standard_Real aSqDistL = aPntLWL1.Value().SquareDistance(aPntLWL2.Value());
const Standard_Boolean isFM = (aSqDistF < aSqDistL);
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
aWLine2->Point(aNbPntsWL2 - 1);
if (!CheckArgumentsToJoin(theS1, theS2, aPntLWL1, aPt1.Value(),
aPntFWL1.Value(), aPt2.Value(), aMinRad))
{
continue;
}
aWLine1->ClearVertexes();
if (isFM)
{
//Last-First connection
for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->Add(aPt);
@@ -1609,13 +1678,15 @@ void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
//purpose : Performs extending theWLine1 and theWLine2 through their
// respecting end point.
//=======================================================================
void IntPatch_WLineTool::ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
const Handle(Adaptor3d_HSurface)& theS1,
const Handle(Adaptor3d_HSurface)& theS2,
const Standard_Real theToler3D,
const Standard_Real* const theArrPeriods,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2)
void IntPatch_WLineTool::
ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
const Handle(Adaptor3d_HSurface)& theS1,
const Handle(Adaptor3d_HSurface)& theS2,
const Standard_Real theToler3D,
const Standard_Real* const theArrPeriods,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2,
const NCollection_List<gp_Pnt>& theListOfCriticalPoints)
{
if(theSlin.Length() < 2)
return;
@@ -1677,6 +1748,46 @@ void IntPatch_WLineTool::ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
{
aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
}
if (!theListOfCriticalPoints.IsEmpty())
{
for (NCollection_List<gp_Pnt>::Iterator anItr(theListOfCriticalPoints);
anItr.More(); anItr.Next())
{
const gp_Pnt &aPt = anItr.Value();
if (!(aCheckResult & (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast)))
{
if (aPt.SquareDistance(aPntFWL1.Value()) < Precision::Confusion())
{
aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast;
}
}
if (!(aCheckResult & (IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast)))
{
if (aPt.SquareDistance(aPntLWL1.Value()) < Precision::Confusion())
{
aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
}
}
if (!(aCheckResult & (IntPatchWT_DisFirstFirst | IntPatchWT_DisLastFirst)))
{
if (aPt.SquareDistance(aPntFWL2.Value()) < Precision::Confusion())
{
aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisLastFirst;
}
}
if (!(aCheckResult & (IntPatchWT_DisFirstLast | IntPatchWT_DisLastLast)))
{
if (aPt.SquareDistance(aPntLWL2.Value()) < Precision::Confusion())
{
aCheckResult |= IntPatchWT_DisFirstLast | IntPatchWT_DisLastLast;
}
}
}
}
}
if(aCheckResult == (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast |

View File

@@ -18,6 +18,7 @@
#include <IntPatch_SequenceOfLine.hxx>
#include <IntPatch_WLine.hxx>
#include <NCollection_List.hxx>
class Adaptor3d_TopolTool;
@@ -49,29 +50,30 @@ public:
const Handle(Adaptor3d_TopolTool) &theDom1,
const Handle(Adaptor3d_TopolTool) &theDom2);
//! Joins all WLines from theSlin to one if it is possible and records
//! the result into theSlin again. Lines will be kept to be splitted if:
//! a) they are separated (has no common points);
//! b) resulted line (after joining) go through seam-edges or surface boundaries.
//!
//! In addition, if points in theSPnt lies at least in one of the line in theSlin,
//! this point will be deleted.
//! Joins all WLines from theSlin to one if it is possible and records
//! the result into theSlin again. Lines will be kept to be split if:
//! a) they are separated (has no common points);
//! b) resulted line (after joining) go through seam-edges or surface boundaries.
//!
//! In addition, if points in theSPnt lies at least in one of the line in theSlin,
//! this point will be deleted.
Standard_EXPORT static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
IntPatch_SequenceOfPoint& theSPnt,
Handle(Adaptor3d_HSurface) theS1,
Handle(Adaptor3d_HSurface) theS2,
const Standard_Real theTol3D);
//! 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. Both theS1 and theS2
//! must be quadrics. Other cases are not supported.
//! theArrPeriods must be filled as follows (every value must not be negative;
//! if the surface is not periodic the period must be equal to 0.0 strictly):
//! {<U-period of 1st surface>, <V-period of 1st surface>,
//! <U-period of 2nd surface>, <V-period of 2nd surface>}.
//! 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. Both theS1 and theS2
//! must be quadrics. Other cases are not supported.
//! theArrPeriods must be filled as follows (every value must not be negative;
//! if the surface is not periodic the period must be equal to 0.0 strictly):
//! {<U-period of 1st surface>, <V-period of 1st surface>,
//! <U-period of 2nd surface>, <V-period of 2nd surface>}.
//! theListOfCriticalPoints must contain 3D-points where joining is disabled.
Standard_EXPORT static void
ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
const Handle(Adaptor3d_HSurface)& theS1,
@@ -79,7 +81,8 @@ public:
const Standard_Real theToler3D,
const Standard_Real* const theArrPeriods,
const Bnd_Box2d& theBoxS1,
const Bnd_Box2d& theBoxS2);
const Bnd_Box2d& theBoxS2,
const NCollection_List<gp_Pnt>& theListOfCriticalPoints);
//! Max angle to concatenate two WLines to avoid result with C0-continuity
static const Standard_Real myMaxConcatAngle;