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

0026431: Can't cut a sphere from a cylinder

This branch contains fixes for 26675 and 26431 bugs.

1. Normalization has been eliminated.
2. Interfaces of AppDef_Compute::Parametrization(...) and BRepAlgo_BooleanOperations::SetApproxParameters() methods have been changed.
3. Overloaded methods for ApproxInt_Approx::SetParameters(...), TopOpeBRepTool_GeomTool::GetTolerances(...) and TopOpeBRepTool_GeomTool::SetTolerances(...) have been removed (because some fields of these classes are not used more).
4. Comments for some methods have been changed in BRepApprox_TheMultiLineOfApprox.hxx and GeomInt_TheMultiLineOfWLApprox.hxx files.
5. Some fields have been deleted from ApproxInt_MultiLine class. Kept members have become constant.
6. Interface of ksection DRAW-command has been changed.
7. Now, 2dintersect DRAW-command prints information about found segments.
8. Some code fragments have been rewritten to make them easier.
9. Algorithm of splitting WLine, which goes through pole of sphere has been improved.
10. Improve approximation algorithm in order to it will compute correct 2D- and 3D-tangent at the end of bezier constraints (including case when curve goes through or finishes on singular points).
11. Interface of IntPatch_WLine::Dump(...) method has been corrected.
12. Some methods for working with Walking-line are made more universal (available for both GeomInt and IntTools packages).
13. Problem in BRepLib::SameParameter(...) method has been fixed (see corresponding comment).
14. Small correction in Draft package.
15. Any outputs in IntPatch_Intersection::Dump(...) method have become disabled because they are useless. If anybody need in this outputs he/she will correct this method himself/herself.

Adjusting some test cases according to their new behavior.
Creation of new test cases.

----------------------------------------------------------------------------------------------------------------------------

Some explanation of new behavior of some test cases:

 1. Regressions:

a) blend simple X4
The problem is described in the issue #0026740. According to this description,  the result on the current MASTER seems to be wrong indeed.

b) boolean bcommon_complex C7 and boolean bcut_complex Q1
These test case use same shapes with different Boolean operation (COMMON and CUT). They are already BAD (on the MASTER). Now, some sub-shapes have become not-shared, simply. In my opinion, we shall apply new behavior of these tests.

c) boolean bsection M3
The problem described in the issue #0026777 exists even on the current MASTER.

d) boolean bsection M9
The problem is described in the message http://tracker.dev.opencascade.org/view.php?id=26815#c47546. Here, we have really regression in the picture.

e) boolean bsection N2

The problem is described in issue #0026814.

f) boolean volumemaker G1

The problem is described in issue #26020.

g) bugs modalg_1 bug1255 (and bug1255_1)

The problem is described in issue #26815.

h) bugs modalg_2 bug5805_18, bugs modalg_2 bug5805_42, bugs modalg_2 bug5805_46

The problem is described in issue #25925.

i) bugs modalg_3 bug602

The problem is describes in issue #602.

j) bugs modalg_5 bug24915

The problem is described in the message http://tracker.dev.opencascade.org/view.php?id=25929#c48565. It is not fixed by this issue.

k) bugs modalg_5 bug25838

The main reason is described in issue #0026816.

----------------------------------------------------------------------------
2. Improvements:

a) boolean volumemaker F9
b) bugs modalg_1 bug10160_3
c) bugs modalg_2 bug22557
d) bugs modalg_5 bug25319_1 (_2)
e) draft angle G2
f) offset shape A1
g) offset with_intersect_80 N7
This commit is contained in:
nbv
2015-11-10 10:31:19 +03:00
committed by bugmaster
parent f44aa19760
commit 4e14c88f77
81 changed files with 5716 additions and 3883 deletions

View File

@@ -94,3 +94,5 @@ IntPatch_TheSurfFunction_0.cxx
IntPatch_WLine.cxx
IntPatch_WLine.hxx
IntPatch_WLine.lxx
IntPatch_WLineTool.cxx
IntPatch_WLineTool.hxx

View File

@@ -39,7 +39,9 @@
#include <IntSurf_SequenceOfPathPoint.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_NumericError.hxx>
#include <Standard_OutOfRange.hxx>
#include <Standard_TypeMismatch.hxx>
#include <StdFail_NotDone.hxx>
#include <TColStd_Array1OfInteger.hxx>
@@ -66,13 +68,16 @@
#include <Bnd_Box2d.hxx>
#include <IntPatch_PointLine.hxx>
static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& Line,
const Standard_Boolean IsReversed,
const IntSurf_Quadric& Quad,
const Handle(Adaptor3d_TopolTool)& PDomain,
const Handle(Adaptor3d_HSurface)& QSurf,
const Standard_Real ArcTol,
IntPatch_SequenceOfLine& Lines);
#include <Extrema_GenLocateExtPS.hxx>
static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
const Standard_Boolean IsReversed,
const IntSurf_Quadric& theQuad,
const Handle(Adaptor3d_TopolTool)& thePDomain,
const Handle(Adaptor3d_HSurface)& theQSurf,
const Handle(Adaptor3d_HSurface)& theOtherSurf,
const Standard_Real theArcTol,
IntPatch_SequenceOfLine& theLines);
static
void ComputeTangency (const IntPatch_TheSOnBounds& solrst,
IntSurf_SequenceOfPathPoint& seqpdep,
@@ -783,6 +788,10 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
// <-A
wline = new IntPatch_WLine(thelin,Standard_False,trans1,trans2);
#ifdef OCCT_DEBUG
//wline->Dump(0);
#endif
if ( iwline->HasFirstPoint()
&& iwline->IsTangentAtBegining() == Standard_False)
{
@@ -1464,12 +1473,13 @@ void IntPatch_ImpPrmIntersection::Perform (const Handle(Adaptor3d_HSurface)& Sur
const Handle(Adaptor3d_TopolTool)& PDomain = (reversed) ? D1 : D2;
const Handle(Adaptor3d_HSurface)& aQSurf = (reversed) ? Surf2 : Surf1;
const Handle(Adaptor3d_HSurface)& anOtherSurf = (reversed) ? Surf1 : Surf2;
IntPatch_SequenceOfLine dslin;
Standard_Boolean isDecompose = Standard_False;
for(Standard_Integer i = 1; i <= slin.Length(); i++ )
{
if(DecomposeResult(slin(i),reversed,Quad,PDomain,aQSurf,TolArc,dslin))
if(DecomposeResult(slin(i),reversed,Quad,PDomain,aQSurf, anOtherSurf, TolArc,dslin))
{
isDecompose = Standard_True;
}
@@ -1624,76 +1634,6 @@ static Standard_Boolean AreSamePoints(const IntSurf_PntOn2S& P1,
return result;
}
static void ForcedPurgePoints(const Handle(IntSurf_LineOn2S)& Result,
const Standard_Boolean IsReversed,
const IntSurf_Quadric& Quad)
{
if(Result->NbPoints() <= 30) return;
Standard_Integer Index = 0, IndexLimF = 8, IndexLimL = 8;
Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
if(IsReversed) {
Result->Value(1).ParametersOnS2(U1,V1);
Result->Value(Result->NbPoints()).ParametersOnS2(U2,V2);
}
else {
Result->Value(1).ParametersOnS1(U1,V1);
Result->Value(Result->NbPoints()).ParametersOnS1(U2,V2);
}
if(Quad.TypeQuadric() == GeomAbs_Cone) {
Standard_Real Uapx = 0., Vapx = 0.;
Quad.Parameters(Quad.Cone().Apex(),Uapx,Vapx);
if(fabs(V1-Vapx) <= 1.e-3)
IndexLimF = 12;
if(fabs(V2-Vapx) <= 1.e-3)
IndexLimL = 12;
}
if(Quad.TypeQuadric() == GeomAbs_Sphere) {
Standard_Real Vapx1 = M_PI/2., Vapx2 = -M_PI/2.;
if(fabs(V1-Vapx1) <= 1.e-3 || fabs(V1-Vapx2) <= 1.e-3)
IndexLimF = 12;
if(fabs(V2-Vapx1) <= 1.e-3 || fabs(V2-Vapx2) <= 1.e-3)
IndexLimL = 12;
}
while(Result->NbPoints() > 2 && Index < IndexLimF) {
Result->RemovePoint(2);
Index++;
}
Index = 0;
while(Result->NbPoints() > 2 && Index < IndexLimL) {
Result->RemovePoint(Result->NbPoints()-1);
Index++;
}
}
// DEBUG FUNCTION !!!
#if 0
static void DumpLine(Handle(IntSurf_LineOn2S)& Line,
Standard_Boolean IsReversed,
Standard_Integer Number)
{
cout << "DUMP LINE" << endl;
Standard_Integer i;
Standard_Real U,V;
for(i = 1; i <= Line->NbPoints(); i++) {
if(i <= Number || i >= (Line->NbPoints()-Number)) {
if(IsReversed)
Line->Value(i).ParametersOnS2(U,V); // S2 - quadric
else
Line->Value(i).ParametersOnS1(U,V); // S1 - quadric
cout << "point p" << i << " " << U << " " << V << endl;
}
}
cout << endl;
}
#endif
// DEBUG FUNCTION !!!
static void SearchVertices(const Handle(IntSurf_LineOn2S)& Line,
const Handle(IntSurf_LineOn2S)& Vertices,
TColStd_Array1OfInteger& PTypes)
@@ -2378,19 +2318,23 @@ static Standard_Boolean SplitOnSegments(Handle(IntPatch_WLine)& WLine,
return result;
}
//=======================================================================
//function : DecomposeResult
//purpose : Split <theLine> in the places where it passes through seam edge
// or singularity (apex of cone or pole of sphere).
// This passage is detected by jump of U-parameter
// from point to point.
//=======================================================================
static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
const Standard_Boolean IsReversed,
const IntSurf_Quadric& theQuad,
const Handle(Adaptor3d_TopolTool)& thePDomain,
const Handle(Adaptor3d_HSurface)& theQSurf,
const Handle(Adaptor3d_HSurface)& theQSurf, //quadric
const Handle(Adaptor3d_HSurface)& thePSurf, //parametric
const Standard_Real theArcTol,
IntPatch_SequenceOfLine& theLines)
{
// Split <theLine> in the places where it passes through seam edge or singularity
// (apex of cone or pole of sphere). This passage is detected by jump of U-parameter
// from point to point.
const Standard_Real aDeltaUmax = 0.5*M_PI;
const Standard_Real aDeltaUmax = M_PI_2;
const Standard_Real aTOL3D = 1.e-10,
aTOL2D = Precision::PConfusion(),
aTOL2DS = Precision::PConfusion();
@@ -2437,7 +2381,13 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
// build WLine parts (if any)
Standard_Boolean flNextLine = Standard_True;
Standard_Boolean hasBeenDecomposed = Standard_False;
Standard_Boolean PrePointExist = Standard_False;
enum PrePoint_Type
{
PrePoint_NONE,
PrePoint_SEAM,
PrePoint_POLE
}PrePointExist = PrePoint_NONE;
IntSurf_PntOn2S PrePoint;
while(flNextLine)
{
@@ -2449,15 +2399,86 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
Handle(IntSurf_LineOn2S) sline = new IntSurf_LineOn2S();
//if((Lindex-Findex+1) <= 2 )
if(aLindex <= aFindex)
return hasBeenDecomposed;
if((aLindex <= aFindex) && (PrePointExist != PrePoint_POLE))
{
//break of "while(flNextLine)" cycle
break;
}
if (PrePointExist)
if (PrePointExist == PrePoint_SEAM)
{
sline->Add(PrePoint);
PrePointExist = Standard_False;
}
else if(PrePointExist == PrePoint_POLE)
{
//The last point of the line is the pole of the quadric.
//Therefore, 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, 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).
const Standard_Real aPeriod = M_PI_2, aHalfPeriod = M_PI_4;
const IntSurf_PntOn2S& aRefPt = aSSLine->Value(aFindex);
IntSurf_PntOn2S aFirstPoint = PrePoint;
if(!aFirstPoint.IsSame(aRefPt, Precision::Confusion()))
{
Standard_Real aURef = 0.0, aVRef = 0.0;
Standard_Real aUquad = 0.0, aVquad = 0.0;
//Take parameters on quadric
if(IsReversed)
{
aFirstPoint.ParametersOnS2(aUquad, aVquad);
aRefPt.ParametersOnS2(aURef, aVRef);
}
else
{
aFirstPoint.ParametersOnS1(aUquad, aVquad);
aRefPt.ParametersOnS1(aURef, aVRef);
}
{
Standard_Real aDeltaPar = aURef-aUquad;
const Standard_Real anIncr = aPeriod*Sign(1.0, aDeltaPar);
while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod))
{
aUquad += anIncr;
aDeltaPar = aURef-aUquad;
}
}
aFirstPoint.SetValue(!IsReversed, aUquad, aVquad);
sline->Add(aFirstPoint);
}
else
{
//break of "while(flNextLine)" cycle
break;
}
}
PrePointExist = PrePoint_NONE;
// analyze other points
for(Standard_Integer k = aFindex; k <= aLindex; k++)
{
@@ -2517,7 +2538,7 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
Abs(AnU1 - 2*M_PI) <= Precision::PConfusion())
{
//Modify <PrePoint>
PrePointExist = Standard_True;
PrePointExist = PrePoint_SEAM;
Standard_Real theU1, theV1;
if (!IsReversed)
{
@@ -2534,6 +2555,240 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
theU1, theV1);
}
}
else
{//Check if WLine goes through pole
const Standard_Real aTol = Precision::Confusion();
const Standard_Real aPeriod = M_PI+M_PI, aHalfPeriod = M_PI;
const IntSurf_PntOn2S& aRefPt = aSSLine->Value(aBindex-1);
//Not quadric point
Standard_Real aU0 = 0.0, aV0 = 0.0;
//Quadric point
Standard_Real aUQuadRef = 0.0, aVQuadRef = 0.0;
if(IsReversed)
{
aRefPt.Parameters(aU0, aV0, aUQuadRef, aVQuadRef);
}
else
{
aRefPt.Parameters(aUQuadRef, aVQuadRef, aU0, aV0);
}
//Transforms parametric surface in coordinate-system of the quadric
gp_Trsf aTr;
aTr.SetTransformation(theQuad.Sphere().Position());
//aPQuad is Pole
gp_Pnt aPQuad;
Standard_Real aUquad = 0.0;
Standard_Real aVquad = 0.0;
if(theQuad.TypeQuadric() == GeomAbs_Sphere)
{
aVquad = Sign(M_PI_2, aVQuadRef);
}
else if(theQuad.TypeQuadric() == GeomAbs_Cone)
{
const Standard_Real aRadius = theQuad.Cone().RefRadius();
const Standard_Real aSemiAngle = theQuad.Cone().SemiAngle();
aVquad = -aRadius/sin(aSemiAngle);
}
else
{
Standard_TypeMismatch::Raise( "IntPatch_ImpPrmIntersection.cxx,"
" DecomposeResult(...): "
"Unsupported quadric with Pole");
}
theQSurf->D0(aUquad, aVquad, aPQuad);
Extrema_GenLocateExtPS anExtr(aPQuad, thePSurf->Surface(), aU0, aV0,
Precision::PConfusion(),
Precision::PConfusion());
if(!anExtr.IsDone())
break;
if(anExtr.SquareDistance() < aTol*aTol)
{ //Pole is an intersection point
//(lies in the quadric and the parametric surface)
anExtr.Point().Parameter(aU0, aV0);
gp_Pnt aP0(anExtr.Point().Value());
IntSurf_PntOn2S aNewPoint;
aNewPoint.SetValue(0.5*(aP0.XYZ() + aPQuad.XYZ()), IsReversed, aU0, aV0);
if(!aNewPoint.IsSame(aRefPt, 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).
//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.
//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
//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).
gp_Pnt aPtemp;
gp_Vec aVecDu, aVecDv;
thePSurf->D1(aU0, aV0, aPtemp, aVecDu, aVecDv);
//Derivatives of transformed thePSurf
aVecDu.Transform(aTr);
aVecDv.Transform(aTr);
if(theQuad.TypeQuadric() == 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()) > Abs(aVecDv.Z()))
{
//Example of this exception is intersection 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). On the other hand,
//in this case there are not any Walking-line to be decomposited.
Standard_NumericError_Raise_if(Abs(aVecDu.Z()) < Precision::PConfusion(),
"IntPatch_ImpPrmIntersection.cxx, DecomposeResult(...): "
"Cannot find UV-coordinate for quadric in the pole");
const Standard_Real aDusDvs = aVecDv.Z()/aVecDu.Z();
aV1.SetCoord( aVecDu.X()*aDusDvs - aVecDv.X(),
aVecDu.Y()*aDusDvs - aVecDv.Y());
}
else
{
//Example of this exception is intersection 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). On the other hand,
//in this case there are not any Walking-line to be decomposited.
Standard_NumericError_Raise_if(Abs(aVecDv.Z()) < Precision::PConfusion(),
"IntPatch_ImpPrmIntersection.cxx, DecomposeResult(...): "
"Cannot find UV-coordinate for quadric in the pole");
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);
}
{
//Adjust found U-paramter to previous point of the Walking-line
Standard_Real aDeltaPar = aUQuadRef-aUquad;
const Standard_Real anIncr = aPeriod*Sign(1.0, aDeltaPar);
while((aDeltaPar > aHalfPeriod) || (aDeltaPar < -aHalfPeriod))
{
aUquad += anIncr;
aDeltaPar = aUQuadRef-aUquad;
}
}
aNewPoint.SetValue(!IsReversed, aUquad, aVquad);
sline->Add(aNewPoint);
PrePointExist = PrePoint_POLE;
PrePoint = aNewPoint;
}
}
}
////
break;
}
@@ -2572,11 +2827,6 @@ static Standard_Boolean DecomposeResult(const Handle(IntPatch_Line)& theLine,
}
}
if(!hasInternals)
{
ForcedPurgePoints(sline,IsReversed,theQuad);
}
Handle(IntPatch_WLine) wline =
new IntPatch_WLine(sline,Standard_False,
theLine->TransitionOnS1(),theLine->TransitionOnS2());

View File

@@ -12,6 +12,7 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <IntPatch_Intersection.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <Adaptor3d_TopolTool.hxx>
@@ -20,406 +21,23 @@
#include <IntPatch_GLine.hxx>
#include <IntPatch_ImpImpIntersection.hxx>
#include <IntPatch_ImpPrmIntersection.hxx>
#include <IntPatch_Intersection.hxx>
#include <IntPatch_Line.hxx>
#include <IntPatch_Point.hxx>
#include <IntPatch_PrmPrmIntersection.hxx>
#include <IntPatch_RLine.hxx>
#include <IntPatch_WLine.hxx>
#include <IntPatch_WLineTool.hxx>
#include <IntSurf_Quadric.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_OutOfRange.hxx>
#include <StdFail_NotDone.hxx>
#include <IntPatch_LineConstructor.hxx>
#include <stdio.h>
#define DEBUG 0
static const Standard_Integer aNbPointsInALine = 200;
//=======================================================================
//function : MinMax
//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
// theParMAX = MAX(theParMIN, theParMAX).
//=======================================================================
static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
{
if(theParMIN > theParMAX)
{
const Standard_Real aTmp = theParMAX;
theParMAX = theParMIN;
theParMIN = aTmp;
}
}
//=======================================================================
//function : IsSeam
//purpose : Returns:
// 0 - if interval [theU1, theU2] does not intersect the "seam-edge"
// or if "seam-edge" do not exist;
// 1 - if interval (theU1, theU2) intersect the "seam-edge".
// 2 - if theU1 or/and theU2 lie ON the "seam-edge"
//
//ATTENTION!!!
// If (theU1 == theU2) then this function will return only both 0 or 2.
//=======================================================================
static Standard_Integer IsSeam( const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Real thePeriod)
{
if(IsEqual(thePeriod, 0.0))
return 0;
//If interval [theU1, theU2] intersect seam-edge then there exists an integer
//number N such as
// (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T),
//where T is the period.
//I.e. the inerval [theU1/T, theU2/T] must contain at least one
//integer number. In this case, Floor(theU1/T) and Floor(theU2/T)
//return different values or theU1/T is strictly integer number.
//Examples:
// 1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3.
// 2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2.
const Standard_Real aVal1 = theU1/thePeriod,
aVal2 = theU2/thePeriod;
const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
if(aPar1 != aPar2)
{//Interval (theU1, theU2] intersects seam-edge
if(IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
{//aVal2 is an integer number => theU2 lies ON the "seam-edge"
return 2;
}
return 1;
}
//Here, aPar1 == aPar2.
if(IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
{//aVal1 is an integer number => theU1 lies ON the "seam-edge"
return 2;
}
//If aVal2 is a true integer number then always (aPar1 != aPar2).
return 0;
}
//=======================================================================
//function : IsSeamOrBound
//purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
// (if it exist) or surface boundaries and both thePtf and thePtl do
// not match "seam-edge" or boundaries.
// Point thePtmid lies in this segment. If thePtmid match
// "seam-edge" or boundaries strictly (without any tolerance) then
// the function will return TRUE.
// See comments in function body for detail information.
//=======================================================================
static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
const IntSurf_PntOn2S& thePtl,
const IntSurf_PntOn2S& thePtmid,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
const Standard_Real theUfSurf1,
const Standard_Real theUlSurf1,
const Standard_Real theVfSurf1,
const Standard_Real theVlSurf1,
const Standard_Real theUfSurf2,
const Standard_Real theUlSurf2,
const Standard_Real theVfSurf2,
const Standard_Real theVlSurf2)
{
Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
thePtf.Parameters(aU11, aV11, aU12, aV12);
thePtl.Parameters(aU21, aV21, aU22, aV22);
MinMax(aU11, aU21);
MinMax(aV11, aV21);
MinMax(aU12, aU22);
MinMax(aV12, aV22);
if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0)
{//Interval [aU11, aU21] intersects theUfSurf1
return Standard_True;
}
if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0)
{//Interval [aU11, aU21] intersects theUlSurf1
return Standard_True;
}
if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0)
{//Interval [aV11, aV21] intersects theVfSurf1
return Standard_True;
}
if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0)
{//Interval [aV11, aV21] intersects theVlSurf1
return Standard_True;
}
if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0)
{//Interval [aU12, aU22] intersects theUfSurf2
return Standard_True;
}
if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0)
{//Interval [aU12, aU22] intersects theUlSurf2
return Standard_True;
}
if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0)
{//Interval [aV12, aV22] intersects theVfSurf2
return Standard_True;
}
if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0)
{//Interval [aV12, aV22] intersects theVlSurf2
return Standard_True;
}
if(IsSeam(aU11, aU21, theU1Period))
return Standard_True;
if(IsSeam(aV11, aV21, theV1Period))
return Standard_True;
if(IsSeam(aU12, aU22, theU2Period))
return Standard_True;
if(IsSeam(aV12, aV22, theV2Period))
return Standard_True;
/*
The segment [thePtf, thePtl] does not intersect the boundaries and
the seam-edge of the surfaces.
Nevertheless, following situation is possible:
seam or
bound
|
thePtf * |
|
* thePtmid
thePtl * |
|
This case must be processed, too.
*/
Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
thePtmid.Parameters(aU1, aV1, aU2, aV2);
if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1))
return Standard_True;
if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2))
return Standard_True;
if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1))
return Standard_True;
if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
return Standard_True;
if(IsSeam(aU1, aU1, theU1Period))
return Standard_True;
if(IsSeam(aU2, aU2, theU2Period))
return Standard_True;
if(IsSeam(aV1, aV1, theV1Period))
return Standard_True;
if(IsSeam(aV2, aV2, theV2Period))
return Standard_True;
return Standard_False;
}
//=======================================================================
//function : JoinWLines
//purpose : 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.
//=======================================================================
static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
IntPatch_SequenceOfPoint& theSPnt,
const Standard_Real theTol3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
const Standard_Real theUfSurf1,
const Standard_Real theUlSurf1,
const Standard_Real theVfSurf1,
const Standard_Real theVlSurf1,
const Standard_Real theUfSurf2,
const Standard_Real theUlSurf2,
const Standard_Real theVfSurf2,
const Standard_Real theVlSurf2)
{
if(theSlin.Length() == 0)
return;
for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
{
Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1)));
if(aWLine1.IsNull())
{//We must have failed to join not-point-lines
return;
}
const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
const IntSurf_PntOn2S& aPntFW1 = aWLine1->Point(1);
const IntSurf_PntOn2S& aPntLW1 = aWLine1->Point(aNbPntsWL1);
for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
{
const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
if( aPntCur.IsSame(aPntFW1, Precision::Confusion()) ||
aPntCur.IsSame(aPntLW1, Precision::Confusion()))
{
theSPnt.Remove(aNPt);
aNPt--;
}
}
Standard_Boolean hasBeenRemoved = Standard_False;
for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
{
Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2)));
const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->InsertBefore(1, aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->InsertBefore(1, aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->Add(aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->Add(aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
}
if(hasBeenRemoved)
aNumOfLine1--;
}
}
//======================================================================
// function: SequenceOfLine
//======================================================================
@@ -1103,7 +721,8 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& theS1,
const Standard_Real TolArc,
const Standard_Real TolTang,
const Standard_Boolean isGeomInt,
const Standard_Boolean theIsReqToKeepRLine)
const Standard_Boolean theIsReqToKeepRLine,
const Standard_Boolean theIsReqToPostWLProc)
{
myTolArc = TolArc;
myTolTang = TolTang;
@@ -1336,6 +955,25 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& theS1,
ParamParamPerfom(theS1, theD1, theS2, theD2, TolArc,
TolTang, ListOfPnts, RestrictLine, typs1, typs2);
}
if(!theIsReqToPostWLProc)
return;
for(Standard_Integer i = slin.Lower(); i <= slin.Upper(); i++)
{
Handle(IntPatch_WLine) aWL = Handle(IntPatch_WLine)::DownCast(slin.Value(i));
if(aWL.IsNull())
continue;
Handle(IntPatch_WLine) aRW = IntPatch_WLineTool::ComputePurgedWLine(aWL, theS1, theS2, theD1, theD2);
if(aRW.IsNull())
continue;
slin.InsertAfter(i, aRW);
slin.Remove(i);
}
}
//=======================================================================
@@ -1350,7 +988,9 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& theS1,
const Standard_Real TolTang,
IntSurf_ListOfPntOn2S& ListOfPnts,
const Standard_Boolean RestrictLine,
const Standard_Boolean isGeomInt)
const Standard_Boolean isGeomInt,
const Standard_Boolean theIsReqToKeepRLine,
const Standard_Boolean theIsReqToPostWLProc)
{
myTolArc = TolArc;
myTolTang = TolTang;
@@ -1547,14 +1187,33 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& theS1,
if(theD1->DomainIsInfinite() || theD2->DomainIsInfinite())
{
GeomGeomPerfom(theS1, theD1, theS2, theD2, TolArc,
TolTang, ListOfPnts, RestrictLine, typs1, typs2);
TolTang, ListOfPnts, RestrictLine, typs1, typs2, theIsReqToKeepRLine);
}
else
{
GeomGeomPerfomTrimSurf(theS1, theD1, theS2, theD2,
TolArc, TolTang, ListOfPnts, RestrictLine, typs1, typs2);
TolArc, TolTang, ListOfPnts, RestrictLine, typs1, typs2, theIsReqToKeepRLine);
}
}
if(!theIsReqToPostWLProc)
return;
for(Standard_Integer i = slin.Lower(); i <= slin.Upper(); i++)
{
Handle(IntPatch_WLine) aWL = Handle(IntPatch_WLine)::DownCast(slin.Value(i));
if(aWL.IsNull())
continue;
Handle(IntPatch_WLine) aRW = IntPatch_WLineTool::ComputePurgedWLine(aWL, theS1, theS2, theD1, theD2);
if(aRW.IsNull())
continue;
slin.InsertAfter(i, aRW);
slin.Remove(i);
}
}
//=======================================================================
@@ -1912,15 +1571,19 @@ void IntPatch_Intersection::
spnt.Append(aPoint);
}
JoinWLines( slin, spnt, theTolTang,
theS1->IsUPeriodic()? theS1->UPeriod() : 0.0,
theS2->IsUPeriodic()? theS2->UPeriod() : 0.0,
theS1->IsVPeriodic()? theS1->VPeriod() : 0.0,
theS2->IsVPeriodic()? theS2->VPeriod() : 0.0,
theS1->FirstUParameter(), theS1->LastUParameter(),
theS1->FirstVParameter(), theS1->LastVParameter(),
theS2->FirstUParameter(), theS2->LastUParameter(),
theS2->FirstVParameter(), theS2->LastVParameter());
IntPatch_WLineTool::JoinWLines( slin, spnt, theTolTang,
theS1->IsUPeriodic()? theS1->UPeriod() : 0.0,
theS2->IsUPeriodic()? theS2->UPeriod() : 0.0,
theS1->IsVPeriodic()? theS1->VPeriod() : 0.0,
theS2->IsVPeriodic()? theS2->VPeriod() : 0.0,
theS1->FirstUParameter(),
theS1->LastUParameter(),
theS1->FirstVParameter(),
theS1->LastVParameter(),
theS2->FirstUParameter(),
theS2->LastUParameter(),
theS2->FirstVParameter(),
theS2->LastVParameter());
}
}
}
@@ -2000,31 +1663,35 @@ void IntPatch_Intersection::Perform(const Handle(Adaptor3d_HSurface)& S1,
for (; i<=nblm; i++) slin.Append(interpp.Line(i));
}
}
for(Standard_Integer i = slin.Lower(); i <= slin.Upper(); i++)
{
Handle(IntPatch_WLine) aWL = Handle(IntPatch_WLine)::DownCast(slin.Value(i));
if(aWL.IsNull())
continue;
Handle(IntPatch_WLine) aRW = IntPatch_WLineTool::ComputePurgedWLine(aWL, S1, S2, D1, D2);
if(aRW.IsNull())
continue;
slin.InsertAfter(i, aRW);
slin.Remove(i);
}
}
//======================================================================
#include <IntPatch_IType.hxx>
#include <IntPatch_LineConstructor.hxx>
#include <Adaptor2d_HCurve2d.hxx>
#include <Geom_Curve.hxx>
#define MAXR 200
#ifdef DUMPOFIntPatch_Intersection
//void IntPatch_Intersection__MAJ_R(Handle(Adaptor2d_HCurve2d) *R1,
// Handle(Adaptor2d_HCurve2d) *R2,
// int *NR1,
// int *NR2,
// Standard_Integer nbR1,
// Standard_Integer nbR2,
// const IntPatch_Point& VTX)
void IntPatch_Intersection__MAJ_R(Handle(Adaptor2d_HCurve2d) *,
void IntPatch_Intersection__MAJ_R(Handle(Adaptor2d_HCurve2d) *R1,
Handle(Adaptor2d_HCurve2d) *,
int *NR1,
int *,
int *,
Standard_Integer nbR1,
Standard_Integer ,
Standard_Integer ,
const IntPatch_Point& )
const IntPatch_Point& VTX)
{
/*
if(VTX.IsOnDomS1()) {
//-- long unsigned ptr= *((long unsigned *)(((Handle(Standard_Transient) *)(&(VTX.ArcOnS1())))));
@@ -2038,18 +1705,17 @@ void IntPatch_Intersection__MAJ_R(Handle(Adaptor2d_HCurve2d) *,
printf("\n R Pas trouvee (IntPatch)\n");
}
*/
}
#endif
//void IntPatch_Intersection::Dump(const Standard_Integer Mode,
void IntPatch_Intersection::Dump(const Standard_Integer ,
const Handle(Adaptor3d_HSurface)& S1,
const Handle(Adaptor3d_TopolTool)& D1,
const Handle(Adaptor3d_HSurface)& S2,
const Handle(Adaptor3d_TopolTool)& D2) const
void IntPatch_Intersection::Dump(const Standard_Integer /*Mode*/,
const Handle(Adaptor3d_HSurface)& /*S1*/,
const Handle(Adaptor3d_TopolTool)& /*D1*/,
const Handle(Adaptor3d_HSurface)& /*S2*/,
const Handle(Adaptor3d_TopolTool)& /*D2*/) const
{
#ifdef DUMPOFIntPatch_Intersection
const int MAXR = 200;
//-- ----------------------------------------------------------------------
//-- construction de la liste des restrictions & vertex
//--
@@ -2061,14 +1727,14 @@ void IntPatch_Intersection::Dump(const Standard_Integer ,
NR1[nbR1]=0;
nbR1++;
}
for(D2->Init();D2->More() && nbR2<MAXR; D2->Next()) {
for(D2->Init();D2->More() && nbR2<MAXR; D2->Next()) {
R2[nbR2]=D2->Value();
NR2[nbR2]=0;
nbR2++;
}
printf("\nDUMP_INT: ----empt:%2ud tgte:%2ud oppo:%2ud ---------------------------------",empt,tgte,empt);
Standard_Integer i,j,nbr1,nbr2,nbgl,nbgc,nbge,nbgp,nbgh,nbl,nbr,nbg,nbw,nba;
Standard_Integer i,nbr1,nbr2,nbgl,nbgc,nbge,nbgp,nbgh,nbl,nbr,nbg,nbw,nba;
nbl=nbr=nbg=nbw=nba=nbgl=nbge=nbr1=nbr2=nbgc=nbgp=nbgh=0;
nbl=NbLines();
for(i=1;i<=nbl;i++) {
@@ -2151,7 +1817,7 @@ void IntPatch_Intersection::Dump(const Standard_Integer ,
printf("\nDUMP_LC :vtx :%2d r:%2d :%2d :%2d",
nbvw,nbvr,nbva,nbvg);
printf("\n");
printf("\n");
#endif
}

View File

@@ -79,14 +79,32 @@ public:
//! When intersection result returns IntPatch_RLine and another
//! IntPatch_Line (not restriction) we (in case of theIsReqToKeepRLine==TRUE)
//! will always keep both lines even if they are coincided.
Standard_EXPORT void Perform (const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Handle(Adaptor3d_HSurface)& S2, const Handle(Adaptor3d_TopolTool)& D2, const Standard_Real TolArc, const Standard_Real TolTang, const Standard_Boolean isGeomInt = Standard_True, const Standard_Boolean theIsReqToKeepRLine = Standard_False);
//! Flag theIsReqToPostWLProc has been enterred only for
//! compatibility with TopOpeBRep package. It shall be deleted
//! after deleting TopOpeBRep.
//! If theIsReqToPostWLProc == FALSE, then we will work with Walking-line
//! obtained after intersection algorithm directly (wothout any post-processing).
Standard_EXPORT void Perform (const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Handle(Adaptor3d_HSurface)& S2, const Handle(Adaptor3d_TopolTool)& D2, const Standard_Real TolArc, const Standard_Real TolTang, const Standard_Boolean isGeomInt = Standard_True, const Standard_Boolean theIsReqToKeepRLine = Standard_False, const Standard_Boolean theIsReqToPostWLProc = Standard_True);
//! If isGeomInt == Standard_False, then method
//! Param-Param intersection will be used.
Standard_EXPORT void Perform (const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Handle(Adaptor3d_HSurface)& S2, const Handle(Adaptor3d_TopolTool)& D2, const Standard_Real TolArc, const Standard_Real TolTang, IntSurf_ListOfPntOn2S& LOfPnts, const Standard_Boolean RestrictLine = Standard_True, const Standard_Boolean isGeomInt = Standard_True);
//! Flag theIsReqToKeepRLine has been enterred only for
//! compatibility with TopOpeBRep package. It shall be deleted
//! after deleting TopOpeBRep.
//! When intersection result returns IntPatch_RLine and another
//! IntPatch_Line (not restriction) we (in case of theIsReqToKeepRLine==TRUE)
//! will always keep both lines even if they are coincided.
//! Flag theIsReqToPostWLProc has been enterred only for
//! compatibility with TopOpeBRep package. It shall be deleted
//! after deleting TopOpeBRep.
//! If theIsReqToPostWLProc == FALSE, then we will work with Walking-line
//! obtained after intersection algorithm directly (wothout any post-processing).
Standard_EXPORT void Perform (const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Handle(Adaptor3d_HSurface)& S2, const Handle(Adaptor3d_TopolTool)& D2, const Standard_Real TolArc, const Standard_Real TolTang, IntSurf_ListOfPntOn2S& LOfPnts, const Standard_Boolean RestrictLine = Standard_True, const Standard_Boolean isGeomInt = Standard_True, const Standard_Boolean theIsReqToKeepRLine = Standard_False, const Standard_Boolean theIsReqToPostWLProc = Standard_True);
//! Perform with start point
Standard_EXPORT void Perform (const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Handle(Adaptor3d_HSurface)& S2, const Handle(Adaptor3d_TopolTool)& D2, const Standard_Real U1, const Standard_Real V1, const Standard_Real U2, const Standard_Real V2, const Standard_Real TolArc, const Standard_Real TolTang);
//! Uses for finding self-intersected surfaces.
Standard_EXPORT void Perform (const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_TopolTool)& D1, const Standard_Real TolArc, const Standard_Real TolTang);
//! Returns True if the calculus was succesfull.

View File

@@ -0,0 +1,953 @@
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <IntPatch_WLineTool.hxx>
#include <Adaptor3d_HSurface.hxx>
#include <Adaptor3d_TopolTool.hxx>
//=======================================================================
//function : MinMax
//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
// theParMAX = MAX(theParMIN, theParMAX).
//
// Static subfunction in IsSeamOrBound.
//=======================================================================
static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
{
if(theParMIN > theParMAX)
{
const Standard_Real aTmp = theParMAX;
theParMAX = theParMIN;
theParMIN = aTmp;
}
}
//=========================================================================
// function : FillPointsHash
// purpose : Fill points hash by input data.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
NCollection_Array1<Standard_Integer> &thePointsHash)
{
// 1 - Delete point.
// 0 - Store point.
// -1 - Vertex point (not delete).
Standard_Integer i, v;
for(i = 1; i <= theWLine->NbPnts(); i++)
thePointsHash.SetValue(i, 0);
for(v = 1; v <= theWLine->NbVertex(); v++)
{
IntPatch_Point aVertex = theWLine->Vertex(v);
Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
thePointsHash.SetValue(avertexindex, -1);
}
}
//=========================================================================
// function : MakeNewWLine
// purpose : Makes new walking line according to the points hash
// Static subfunction in ComputePurgedWLine and DeleteOuter.
//=========================================================================
static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
const NCollection_Array1<Standard_Integer> &thePointsHash)
{
Standard_Integer i;
Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
Standard_Integer anOldLineIdx = 1, aVertexIdx = 1;
for(i = 1; i <= thePointsHash.Upper(); i++)
{
if (thePointsHash(i) == 0)
{
// Store this point.
aPurgedLineOn2S->Add(theWLine->Point(i));
anOldLineIdx++;
}
else if (thePointsHash(i) == -1)
{
// Add vertex.
IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
aVertex.SetParameter(anOldLineIdx++);
aLocalWLine->AddVertex(aVertex);
aPurgedLineOn2S->Add(theWLine->Point(i));
}
}
return aLocalWLine;
}
//=========================================================================
// function : MovePoint
// purpose : Move point into surface param space. No interpolation used
// because walking algorithm should care for closeness to the param space.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static void MovePoint(const Handle(Adaptor3d_HSurface) &theS1,
Standard_Real &U1, Standard_Real &V1)
{
if (U1 < theS1->FirstUParameter())
U1 = theS1->FirstUParameter();
if (U1 > theS1->LastUParameter())
U1 = theS1->LastUParameter();
if (V1 < theS1->FirstVParameter())
V1 = theS1->FirstVParameter();
if (V1 > theS1->LastVParameter())
V1 = theS1->LastVParameter();
}
//=========================================================================
// function : DeleteOuterPoints
// purpose : Check and delete out of bounds points on walking line.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static Handle(IntPatch_WLine)
DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
const Handle(Adaptor3d_HSurface) &theS1,
const Handle(Adaptor3d_HSurface) &theS2,
const Handle(Adaptor3d_TopolTool) &theDom1,
const Handle(Adaptor3d_TopolTool) &theDom2)
{
Standard_Integer i;
NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
FillPointsHash(theWLine, aDelOuterPointsHash);
if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
theS2->IsUPeriodic() || theS2->IsVPeriodic() )
return theWLine;
gp_Pnt2d aPntOnF1, aPntOnF2;
Standard_Real aX1, aY1, aX2, aY2;
// Iterate over points in walking line and delete which are out of bounds.
// Forward.
Standard_Boolean isAllDeleted = Standard_True;
Standard_Boolean aChangedFirst = Standard_False;
Standard_Integer aFirstGeomIdx = 1;
for(i = 1; i <= theWLine->NbPnts(); i++)
{
theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
aPntOnF1.SetCoord(aX1, aY1);
aPntOnF2.SetCoord(aX2, aY2);
TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
if (aState1 == TopAbs_OUT ||
aState2 == TopAbs_OUT )
{
aDelOuterPointsHash(i) = 1;
aChangedFirst = Standard_True;
}
else
{
isAllDeleted = Standard_False;
aFirstGeomIdx = Max (i - 1, 1);
if (aDelOuterPointsHash(i) == -1)
aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
aDelOuterPointsHash(i) = -1;
break;
}
}
if (isAllDeleted)
{
// ALL points are out of bounds:
// case boolean bcut_complex F5 and similar.
return theWLine;
}
// Backward.
Standard_Boolean aChangedLast = Standard_False;
Standard_Integer aLastGeomIdx = theWLine->NbPnts();
for(i = theWLine->NbPnts(); i >= 1; i--)
{
theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
aPntOnF1.SetCoord(aX1, aY1);
aPntOnF2.SetCoord(aX2, aY2);
TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
if (aState1 == TopAbs_OUT ||
aState2 == TopAbs_OUT )
{
aDelOuterPointsHash(i) = 1;
aChangedLast = Standard_True; // Move vertex to first good point
}
else
{
aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
if (aDelOuterPointsHash(i) == -1)
aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
aDelOuterPointsHash(i) = -1;
break;
}
}
if (!aChangedFirst && !aChangedLast)
{
// Nothing is done, return input.
return theWLine;
}
// Build new line and modify geometry of necessary vertexes.
Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash);
if (aChangedFirst)
{
// Vertex geometry.
IntPatch_Point aVertex = aLocalWLine->Vertex(1);
aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
Standard_Real aU1, aU2, aV1, aV2;
theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
MovePoint(theS1, aU1, aV1);
MovePoint(theS2, aU2, aV2);
aVertex.SetParameters(aU1, aV1, aU2, aV2);
aLocalWLine->Replace(1, aVertex);
// Change point in walking line.
aLocalWLine->SetPoint(1, aVertex);
}
if (aChangedLast)
{
// Vertex geometry.
IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
Standard_Real aU1, aU2, aV1, aV2;
theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
MovePoint(theS1, aU1, aV1);
MovePoint(theS2, aU2, aV2);
aVertex.SetParameters(aU1, aV1, aU2, aV2);
aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
// Change point in walking line.
aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
}
return aLocalWLine;
}
//=========================================================================
// function : IsInsideIn2d
// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
// In 2d space. Static subfunction in DeleteByTube.
//=========================================================================
static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
const gp_Vec2d& aBaseVec,
const gp_Pnt2d& aNextPnt,
const Standard_Real aSquareMaxDist)
{
gp_Vec2d aVec2d(aBasePnt, aNextPnt);
//d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
Standard_Real aCross = aVec2d.Crossed(aBaseVec);
Standard_Real aSquareDist = aCross * aCross
/ aBaseVec.SquareMagnitude();
return (aSquareDist <= aSquareMaxDist);
}
//=========================================================================
// function : IsInsideIn3d
// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
// In 3d space. Static subfunction in DeleteByTube.
//=========================================================================
static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
const gp_Vec& aBaseVec,
const gp_Pnt& aNextPnt,
const Standard_Real aSquareMaxDist)
{
gp_Vec aVec(aBasePnt, aNextPnt);
//d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
/ aBaseVec.SquareMagnitude();
return (aSquareDist <= aSquareMaxDist);
}
static const Standard_Integer aMinNbBadDistr = 15;
static const Standard_Integer aNbSingleBezier = 30;
//=========================================================================
// function : DeleteByTube
// purpose : Check and delete points using tube criteria.
// Static subfunction in ComputePurgedWLine.
//=========================================================================
static Handle(IntPatch_WLine)
DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
const Handle(Adaptor3d_HSurface) &theS1,
const Handle(Adaptor3d_HSurface) &theS2)
{
// III: Check points for tube criteria:
// Workaround to handle case of small amount points after purge.
// Test "boolean boptuc_complex B5" and similar.
Standard_Integer aNbPnt = 0 , i;
if (theWLine->NbPnts() <= 2)
return theWLine;
NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
FillPointsHash(theWLine, aNewPointsHash);
// Inital computations.
Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
// Choose base tolerance and scale it to pipe algorithm.
const Standard_Real aBaseTolerance = Precision::Approximation();
Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
theS1->VResolution(aBaseTolerance));
Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
theS2->VResolution(aBaseTolerance));
Standard_Real aTol1 = aResS1Tol * aResS1Tol;
Standard_Real aTol2 = aResS2Tol * aResS2Tol;
Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
const Standard_Real aLimitCoeff = 0.99 * 0.99;
for(i = 3; i <= theWLine->NbPnts(); i++)
{
Standard_Boolean isDeleteState = Standard_False;
theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
if (aNewPointsHash(i - 1) != - 1 &&
IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
{
// Handle possible uneven parametrization on one of 2d subspaces.
// Delete point only when expected lengths are close to each other (aLimitCoeff).
// Example:
// c2d1 - line
// c3d - line
// c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
, gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
, gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
Standard_Real aStepCoeff = Min(aStepOnS1, aStepOnS2) / Max(aStepOnS1, aStepOnS2);
if (aStepCoeff > aLimitCoeff)
{
// Set hash flag to "Delete" state.
isDeleteState = Standard_True;
aNewPointsHash.SetValue(i - 1, 1);
// Change middle point.
UonS1[1] = UonS1[2];
UonS2[1] = UonS2[2];
VonS1[1] = VonS1[2];
VonS2[1] = VonS2[2];
}
}
if (!isDeleteState)
{
// Compute new pipe parameters.
UonS1[0] = UonS1[1];
VonS1[0] = VonS1[1];
UonS2[0] = UonS2[1];
VonS2[0] = VonS2[1];
UonS1[1] = UonS1[2];
VonS1[1] = VonS1[2];
UonS2[1] = UonS2[2];
VonS2[1] = VonS2[2];
aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
aBase3dPnt = theWLine->Point(i - 1).Value();
aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
aNbPnt++;
}
}
// Workaround to handle case of small amount of points after purge.
// Test "boolean boptuc_complex B5" and similar.
// This is possible since there are at least two points.
if (aNewPointsHash(1) == -1 &&
aNewPointsHash(2) == -1 &&
aNbPnt <= 3)
{
// Delete first.
aNewPointsHash(1) = 1;
}
if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
aNewPointsHash(theWLine->NbPnts() ) == -1 &&
aNbPnt <= 3)
{
// Delete last.
aNewPointsHash(theWLine->NbPnts()) = 1;
}
// Purgre when too small amount of points left.
if (aNbPnt <= 2)
{
for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
{
if (aNewPointsHash(i) != -1)
{
aNewPointsHash(i) = 1;
}
}
}
// Handle possible bad distribution of points,
// which are will converted into one single bezier curve (less than 30 points).
// Make distribution more even:
// max step will be nearly to 0.1 of param distance.
if (aNbPnt + 2 > aMinNbBadDistr &&
aNbPnt + 2 < aNbSingleBezier )
{
for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
{
Standard_Integer aHashIdx =
Standard_Integer(anIdx * theWLine->NbPnts() / 9);
//Store this point.
aNewPointsHash(aHashIdx) = 0;
}
}
return MakeNewWLine(theWLine, aNewPointsHash);
}
//=======================================================================
//function : IsSeam
//purpose : Returns:
// 0 - if interval [theU1, theU2] does not intersect the "seam-edge"
// or if "seam-edge" do not exist;
// 1 - if interval (theU1, theU2) intersect the "seam-edge".
// 2 - if theU1 or/and theU2 lie ON the "seam-edge"
//
//ATTENTION!!!
// If (theU1 == theU2) then this function will return only both 0 or 2.
//
// Static subfunction in IsSeamOrBound.
//=======================================================================
static Standard_Integer IsSeam( const Standard_Real theU1,
const Standard_Real theU2,
const Standard_Real thePeriod)
{
if(IsEqual(thePeriod, 0.0))
return 0;
//If interval [theU1, theU2] intersect seam-edge then there exists an integer
//number N such as
// (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T),
//where T is the period.
//I.e. the inerval [theU1/T, theU2/T] must contain at least one
//integer number. In this case, Floor(theU1/T) and Floor(theU2/T)
//return different values or theU1/T is strictly integer number.
//Examples:
// 1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3.
// 2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2.
const Standard_Real aVal1 = theU1/thePeriod,
aVal2 = theU2/thePeriod;
const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
if(aPar1 != aPar2)
{//Interval (theU1, theU2] intersects seam-edge
if(IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
{//aVal2 is an integer number => theU2 lies ON the "seam-edge"
return 2;
}
return 1;
}
//Here, aPar1 == aPar2.
if(IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
{//aVal1 is an integer number => theU1 lies ON the "seam-edge"
return 2;
}
//If aVal2 is a true integer number then always (aPar1 != aPar2).
return 0;
}
//=======================================================================
//function : IsSeamOrBound
//purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
// (if it exist) or surface boundaries and both thePtf and thePtl do
// not match "seam-edge" or boundaries.
// Point thePtmid lies in this segment. If thePtmid match
// "seam-edge" or boundaries strictly (without any tolerance) then
// the function will return TRUE.
// See comments in function body for detail information.
//
// Static subfunction in JoinWLines.
//=======================================================================
static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
const IntSurf_PntOn2S& thePtl,
const IntSurf_PntOn2S& thePtmid,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
const Standard_Real theUfSurf1,
const Standard_Real theUlSurf1,
const Standard_Real theVfSurf1,
const Standard_Real theVlSurf1,
const Standard_Real theUfSurf2,
const Standard_Real theUlSurf2,
const Standard_Real theVfSurf2,
const Standard_Real theVlSurf2)
{
Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
thePtf.Parameters(aU11, aV11, aU12, aV12);
thePtl.Parameters(aU21, aV21, aU22, aV22);
MinMax(aU11, aU21);
MinMax(aV11, aV21);
MinMax(aU12, aU22);
MinMax(aV12, aV22);
if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0)
{//Interval [aU11, aU21] intersects theUfSurf1
return Standard_True;
}
if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0)
{//Interval [aU11, aU21] intersects theUlSurf1
return Standard_True;
}
if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0)
{//Interval [aV11, aV21] intersects theVfSurf1
return Standard_True;
}
if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0)
{//Interval [aV11, aV21] intersects theVlSurf1
return Standard_True;
}
if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0)
{//Interval [aU12, aU22] intersects theUfSurf2
return Standard_True;
}
if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0)
{//Interval [aU12, aU22] intersects theUlSurf2
return Standard_True;
}
if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0)
{//Interval [aV12, aV22] intersects theVfSurf2
return Standard_True;
}
if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0)
{//Interval [aV12, aV22] intersects theVlSurf2
return Standard_True;
}
if(IsSeam(aU11, aU21, theU1Period))
return Standard_True;
if(IsSeam(aV11, aV21, theV1Period))
return Standard_True;
if(IsSeam(aU12, aU22, theU2Period))
return Standard_True;
if(IsSeam(aV12, aV22, theV2Period))
return Standard_True;
/*
The segment [thePtf, thePtl] does not intersect the boundaries and
the seam-edge of the surfaces.
Nevertheless, following situation is possible:
seam or
bound
|
thePtf * |
|
* thePtmid
thePtl * |
|
This case must be processed, too.
*/
Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
thePtmid.Parameters(aU1, aV1, aU2, aV2);
if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1))
return Standard_True;
if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2))
return Standard_True;
if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1))
return Standard_True;
if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
return Standard_True;
if(IsSeam(aU1, aU1, theU1Period))
return Standard_True;
if(IsSeam(aU2, aU2, theU2Period))
return Standard_True;
if(IsSeam(aV1, aV1, theV1Period))
return Standard_True;
if(IsSeam(aV2, aV2, theV2Period))
return Standard_True;
return Standard_False;
}
//=========================================================================
// function : ComputePurgedWLine
// purpose :
//=========================================================================
Handle(IntPatch_WLine) IntPatch_WLineTool::
ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
const Handle(Adaptor3d_HSurface) &theS1,
const Handle(Adaptor3d_HSurface) &theS2,
const Handle(Adaptor3d_TopolTool) &theDom1,
const Handle(Adaptor3d_TopolTool) &theDom2)
{
Standard_Integer i, k, v, nb, nbvtx;
Handle(IntPatch_WLine) aResult;
nbvtx = theWLine->NbVertex();
nb = theWLine->NbPnts();
if (nb==2)
{
const IntSurf_PntOn2S& p1 = theWLine->Point(1);
const IntSurf_PntOn2S& p2 = theWLine->Point(2);
if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
return aResult;
}
Handle(IntPatch_WLine) aLocalWLine;
Handle(IntPatch_WLine) aTmpWLine = theWLine;
Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
for(i = 1; i <= nb; i++)
aLineOn2S->Add(theWLine->Point(i));
for(v = 1; v <= nbvtx; v++)
aLocalWLine->AddVertex(theWLine->Vertex(v));
// I: Delete equal points
for(i = 1; i <= aLineOn2S->NbPoints(); i++)
{
Standard_Integer aStartIndex = i + 1;
Standard_Integer anEndIndex = i + 5;
nb = aLineOn2S->NbPoints();
anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
if((aStartIndex > nb) || (anEndIndex <= 1))
continue;
k = aStartIndex;
while(k <= anEndIndex)
{
if(i != k)
{
IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
Standard_Real UV[8];
p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
Standard_Real aMax = Abs(UV[0]);
for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
{
if (aMax < Abs(UV[anIdx]))
aMax = Abs(UV[anIdx]);
}
if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
{
aTmpWLine = aLocalWLine;
aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
for(v = 1; v <= aTmpWLine->NbVertex(); v++)
{
IntPatch_Point aVertex = aTmpWLine->Vertex(v);
Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
if(avertexindex >= k)
{
aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
}
aLocalWLine->AddVertex(aVertex);
}
aLineOn2S->RemovePoint(k);
anEndIndex--;
continue;
}
}
k++;
}
}
if (aLineOn2S->NbPoints() <= 2)
{
if (aLineOn2S->NbPoints() == 2)
return aLocalWLine;
else
return aResult;
}
// Avoid purge in case of C0 continuity:
// Intersection approximator may produce invalid curve after purge, example:
// bugs modalg_5 bug24731.
// Do not run purger when base number of points is too small.
if (theS1->UContinuity() == GeomAbs_C0 ||
theS1->VContinuity() == GeomAbs_C0 ||
theS2->UContinuity() == GeomAbs_C0 ||
theS2->VContinuity() == GeomAbs_C0 ||
nb < aNbSingleBezier)
{
return aLocalWLine;
}
// II: Delete out of borders points.
Handle(IntPatch_WLine) aLocalWLineOuter =
DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
// III: Delete points by tube criteria.
Handle(IntPatch_WLine) aLocalWLineTube =
DeleteByTube(aLocalWLineOuter, theS1, theS2);
if(aLocalWLineTube->NbPnts() > 1)
{
aResult = aLocalWLineTube;
}
return aResult;
}
//=======================================================================
//function : JoinWLines
//purpose :
//=======================================================================
void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
IntPatch_SequenceOfPoint& theSPnt,
const Standard_Real theTol3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
const Standard_Real theUfSurf1,
const Standard_Real theUlSurf1,
const Standard_Real theVfSurf1,
const Standard_Real theVlSurf1,
const Standard_Real theUfSurf2,
const Standard_Real theUlSurf2,
const Standard_Real theVfSurf2,
const Standard_Real theVlSurf2)
{
if(theSlin.Length() == 0)
return;
for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
{
Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1)));
if(aWLine1.IsNull())
{//We must have failed to join not-point-lines
continue;
}
const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
const IntSurf_PntOn2S& aPntFW1 = aWLine1->Point(1);
const IntSurf_PntOn2S& aPntLW1 = aWLine1->Point(aNbPntsWL1);
for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
{
const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
if( aPntCur.IsSame(aPntFW1, Precision::Confusion()) ||
aPntCur.IsSame(aPntLW1, Precision::Confusion()))
{
theSPnt.Remove(aNPt);
aNPt--;
}
}
Standard_Boolean hasBeenRemoved = Standard_False;
for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
{
Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2)));
if(aWLine2.IsNull())
continue;
const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->InsertBefore(1, aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->InsertBefore(1, aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->Add(aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
{
const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
theV1Period, theV2Period, theUfSurf1, theUlSurf1,
theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
theVfSurf2, theVlSurf2))
{
aWLine1->ClearVertexes();
for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
{
const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
aWLine1->Curve()->Add(aPt);
}
aWLine1->ComputeVertexParameters(theTol3D);
theSlin.Remove(aNumOfLine2);
aNumOfLine2--;
hasBeenRemoved = Standard_True;
continue;
}
}
}
if(hasBeenRemoved)
aNumOfLine1--;
}
}

View File

@@ -0,0 +1,81 @@
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _IntPatch_WLineTool_HeaderFile
#define _IntPatch_WLineTool_HeaderFile
#include <Standard_Boolean.hxx>
#include <Standard_Macro.hxx>
#include <IntPatch_WLine.hxx>
#include <IntPatch_SequenceOfLine.hxx>
class TopoDS_Face;
class GeomAdaptor_HSurface;
class GeomInt_LineConstructor;
class IntTools_Context;
class Adaptor3d_TopolTool;
class Adaptor3d_HSurface;
//! IntPatch_WLineTool provides set of static methods related to walking lines.
class IntPatch_WLineTool
{
public:
DEFINE_STANDARD_ALLOC
//! I
//! Removes equal points (leave one of equal points) from theWLine
//! and recompute vertex parameters.
//!
//! II
//! Removes point out of borders in case of non periodic surfaces.
//!
//! III
//! Removes exceed points using tube criteria:
//! delete 7D point if it lies near to expected lines in 2d and 3d.
//! Each task (2d, 2d, 3d) have its own tolerance and checked separately.
//!
//! Returns new WLine or null WLine if the number
//! of the points is less than 2.
Standard_EXPORT static
Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
const Handle(Adaptor3d_HSurface) &theS1,
const Handle(Adaptor3d_HSurface) &theS2,
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.
Standard_EXPORT static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
IntPatch_SequenceOfPoint& theSPnt,
const Standard_Real theTol3D,
const Standard_Real theU1Period,
const Standard_Real theU2Period,
const Standard_Real theV1Period,
const Standard_Real theV2Period,
const Standard_Real theUfSurf1,
const Standard_Real theUlSurf1,
const Standard_Real theVfSurf1,
const Standard_Real theVlSurf1,
const Standard_Real theUfSurf2,
const Standard_Real theUlSurf2,
const Standard_Real theVfSurf2,
const Standard_Real theVlSurf2);
};
#endif