1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-06 18:26:22 +03:00
occt/src/GeomInt/GeomInt_IntSS_1.cxx
nbv e2e0498b17 0027431: [Regression to 6.9.1] Huge tolerance obtained during intersection of cylinder and sphere
The root of the problem is incorrect processing of cases when intersection line goes through the apex(es) of sphere. The fix improves this situation. The algorithm is taken from DecomposeResult(...) function (see IntPatch_ImpPrmIntersection.cxx file). Before the fix, faltering steps were done to solve this problem. As result, it worked in some particular cases. Now, its possibilities have been extended significantly.

Following changes have been made in the fix:

1. Class IntPatch_ALineToWLine has been rewritten cardinally. It touches as interfaces of existing methods as adding/removing some methods/fields. Correction touches both cases: going through seam of Cone/Sphere and through pole(s) of sphere. Old interface did not allow making some actions with analytical line (ALine), e.g. splitting it on several Walking-lines (WLine).

2. Restriction-line support has been removed from Implicit-Implicit intersection result (see IntPatch_Intersection::GeomGeomPerfom(...) method). It connects with the fact that the intersection algorithm itself returns precise intersection line in analytical cases (in compare with parametric intersector). Therefore, we do not need in additional (restriction) line.

3. New class IntPatch_SpecialPoints has been added. This class contains methods to add some special points (such as apex of cone, pole of sphere, point on surface boundary etc.) in intersection line (IntPatch_PointLine). It is based on the static functions, which already exist in IntPatch_ImpPrmIntersection.cxx file (these functions have been moved to the new class).

4. Method IntPatch_WLineTool::ExtendTwoWlinesToEachOther(...) has been renamed to IntPatch_WLineTool::ExtendTwoWLines(...). It is connected with changing main idea of the method. Now it allows extending WLine to the surface boundary or to the singular point (if it is possible): cone apex, sphere pole etc. Interface of this method has been corrected, too. At that, old functionality (extending to each other) has been kept. For implementation of this algorithm, new enumeration "IntPatchWT_WLsConnectionType" has been created.

5. Method IntPatch_PointLine::CurvatureRadiusOfIntersLine(...) has been added. See IntPatch_PointLine.hxx for detail information. It allows correct step computing depended on the local curvature of the intersection line. This method uses geometrical properties of intersected surfaces to compute local curvature. Therefore, it can be applied in wide range of cases even if the intersection curve is not represented in explicit form (e.g. in case of param-param-intersection).

6. Method IntSurf::SetPeriod(...) has been created.

7. Additional check has been added in Draft_Modification::Perform() method for better choice of correct fragment of intersection line for processing DRAFT operation.

8. New overload method IntPatch_Point::SetValue() has been added.

9. Some refactoring of the code has been made.

Creation of test case for issue #27431.

---------------------------------------------------------------------------------------------
Some test cases have been adjusted according to their new behavior.

   tests\bugs\modalg_4\bug62
It is really IMPROVEMENT (but fortuitous).

   tests\bugs\modalg_5\bug25838
The behavior of this test has been reverted to the state before fixing the issue #27341. Main problem has not been fixed in #27341. It was fortuitous improvement.

    tests\bugs\moddata_2\bug565
Quality of intersection curve was not checked. And the curve is bad on both MASTER and FIX. Input data are really wrong: plane-like-cone. However, on the MASTER, four intersection curves (the quality is insignificant) are expected. On the fix, not empty intersection result is expected simply.

   tests\boolean\volumemaker\A8
Differences in images and CPU is expected. Difference in images is expected to be fixed in the issue #26020. Now, we should apply this behavior.
Much CPU time is spent by IntTools_FaceFace::ComputeTolReached3d(...) and GeomInt_IntSS::BuildPCurves(...) methods calling. These methods are not touched by the algorithm. It is the result of change of intersection curve(s) form. However, the new Curve(s) seems to be valid and can be applied. As result, new behavior can be applied, too.

   tests\boolean\volumemaker\F8
   tests\boolean\volumemaker\F9
   tests\boolean\volumemaker\G5
   tests\boolean\volumemaker\G6
CPU difference is expected. Much CPU time is spent by IntPatch_PointLine::CurvatureRadiusOfIntersLine(...) method calling. This method is really new (it does not exist on the MASTER) and is really useful. Therefore, we should apply new behavior.

   tests\boolean\volumemaker\G1
CPU difference is expected. Much CPU time is spent by IntTools_WLineTool::DecompositionOfWLine(...) and IntTools_FaceFace::ComputeTolReached3d(...) methods calling. These methods are not touched by the algorithm. It is the result of change of intersection curve(s) form. However, the new Curve(s) seems to be valid and can be applied. As result, new behavior can be applied, too.

   tests\bugs\modalg_6\bug26619
Differences in images is expected. The test keeps its BAD status on the FIX. But the result on the fix is nearer to expected than on the MASTER. Issue #27014 is still actual. As before, it is not clear, why the number of entities is different. The number of section curves has not been changed. Interfered entities are the same as on the MASTER.

   tests\bugs\modalg_5\bug25319_1(2)
The reason is described in the issue #27896.

Small correction in the test case
2016-11-03 14:15:41 +03:00

1339 lines
45 KiB
C++

// Created on: 1995-01-27
// Created by: Jacques GOUSSARD
// Copyright (c) 1995-1999 Matra Datavision
// 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 <algorithm>
#include <GeomInt_IntSS.hxx>
#include <Adaptor3d_TopolTool.hxx>
#include <Approx_CurveOnSurface.hxx>
#include <ElSLib.hxx>
#include <Extrema_ExtPS.hxx>
#include <Geom2dAdaptor.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GeomAdaptor.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomInt.hxx>
#include <GeomInt_LineTool.hxx>
#include <GeomInt_WLApprox.hxx>
#include <GeomLib_Check2dBSplineCurve.hxx>
#include <GeomLib_CheckBSplineCurve.hxx>
#include <GeomProjLib.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Hyperbola.hxx>
#include <Geom_Line.hxx>
#include <Geom_Parabola.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <IntPatch_GLine.hxx>
#include <IntPatch_RLine.hxx>
#include <IntPatch_WLine.hxx>
#include <IntRes2d_IntersectionSegment.hxx>
#include <IntSurf_Quadric.hxx>
#include <Precision.hxx>
//=======================================================================
//function : AdjustUPeriodic
//purpose :
//=======================================================================
static void AdjustUPeriodic (const Handle(Geom_Surface)& aS, const Handle(Geom2d_Curve)& aC2D)
{
if (aC2D.IsNull() || !aS->IsUPeriodic())
return;
//
const Standard_Real aEps=Precision::PConfusion();//1.e-9
const Standard_Real aEpsilon=Epsilon(10.);//1.77e-15
//
Standard_Real umin,umax,vmin,vmax;
aS->Bounds(umin,umax,vmin,vmax);
const Standard_Real aPeriod = aS->UPeriod();
const Standard_Real aT1=aC2D->FirstParameter();
const Standard_Real aT2=aC2D->LastParameter();
const Standard_Real aTx=aT1+0.467*(aT2-aT1);
const gp_Pnt2d aPx=aC2D->Value(aTx);
//
Standard_Real aUx=aPx.X();
if (fabs(aUx)<aEpsilon)
aUx=0.;
if (fabs(aUx-aPeriod)<aEpsilon)
aUx=aPeriod;
//
Standard_Real dU=0.;
while(aUx <(umin-aEps)) {
aUx+=aPeriod;
dU+=aPeriod;
}
while(aUx>(umax+aEps)) {
aUx-=aPeriod;
dU-=aPeriod;
}
//
if (dU!=0.) {
gp_Vec2d aV2D(dU, 0.);
aC2D->Translate(aV2D);
}
}
//=======================================================================
//function : GetQuadric
//purpose :
//=======================================================================
static void GetQuadric(const Handle(GeomAdaptor_HSurface)& HS1, IntSurf_Quadric& quad1)
{
switch (HS1->Surface().GetType())
{
case GeomAbs_Plane: quad1.SetValue(HS1->Surface().Plane()); break;
case GeomAbs_Cylinder: quad1.SetValue(HS1->Surface().Cylinder()); break;
case GeomAbs_Cone: quad1.SetValue(HS1->Surface().Cone()); break;
case GeomAbs_Sphere: quad1.SetValue(HS1->Surface().Sphere()); break;
case GeomAbs_Torus: quad1.SetValue(HS1->Surface().Torus()); break;
default: Standard_ConstructionError::Raise("GeomInt_IntSS::MakeCurve");
}
}
//=======================================================================
//function : Parameters
//purpose :
//=======================================================================
static void Parameters( const Handle(GeomAdaptor_HSurface)& HS1,
const Handle(GeomAdaptor_HSurface)& HS2,
const gp_Pnt& Ptref,
Standard_Real& U1,
Standard_Real& V1,
Standard_Real& U2,
Standard_Real& V2)
{
IntSurf_Quadric quad1,quad2;
//
GetQuadric(HS1, quad1);
GetQuadric(HS2, quad2);
//
quad1.Parameters(Ptref,U1,V1);
quad2.Parameters(Ptref,U2,V2);
}
//=======================================================================
//function : ParametersOfNearestPointOnSurface
//purpose :
//=======================================================================
static Standard_Boolean ParametersOfNearestPointOnSurface(const Extrema_ExtPS theExtr,
Standard_Real& theU,
Standard_Real& theV)
{
if(!theExtr.IsDone() || !theExtr.NbExt())
return Standard_False;
Standard_Integer anIndex = 1;
Standard_Real aMinSQDist = theExtr.SquareDistance(anIndex);
for(Standard_Integer i = 2; i <= theExtr.NbExt(); i++)
{
Standard_Real aSQD = theExtr.SquareDistance(i);
if (aSQD < aMinSQDist)
{
aMinSQDist = aSQD;
anIndex = i;
}
}
theExtr.Point(anIndex).Parameter(theU, theV);
return Standard_True;
}
//=======================================================================
//function : GetSegmentBoundary
//purpose :
//=======================================================================
static void GetSegmentBoundary( const IntRes2d_IntersectionSegment& theSegm,
const Handle(Geom2d_Curve)& theCurve,
GeomInt_VectorOfReal& theArrayOfParameters)
{
Standard_Real aU1 = theCurve->FirstParameter(), aU2 = theCurve->LastParameter();
if(theSegm.HasFirstPoint())
{
const IntRes2d_IntersectionPoint& anIPF = theSegm.FirstPoint();
aU1 = anIPF.ParamOnFirst();
}
if(theSegm.HasLastPoint())
{
const IntRes2d_IntersectionPoint& anIPL = theSegm.LastPoint();
aU2 = anIPL.ParamOnFirst();
}
theArrayOfParameters.Append(aU1);
theArrayOfParameters.Append(aU2);
}
//=======================================================================
//function : IntersectCurveAndBoundary
//purpose :
//=======================================================================
static void IntersectCurveAndBoundary(const Handle(Geom2d_Curve)& theC2d,
const Handle(Geom2d_Curve)* const theArrBounds,
const Standard_Integer theNumberOfCurves,
const Standard_Real theTol,
GeomInt_VectorOfReal& theArrayOfParameters)
{
if(theC2d.IsNull())
return;
Geom2dAdaptor_Curve anAC1(theC2d);
for(Standard_Integer aCurID = 0; aCurID < theNumberOfCurves; aCurID++)
{
if(theArrBounds[aCurID].IsNull())
continue;
Geom2dAdaptor_Curve anAC2(theArrBounds[aCurID]);
Geom2dInt_GInter anIntCC2d(anAC1, anAC2, theTol, theTol);
if(!anIntCC2d.IsDone() || anIntCC2d.IsEmpty())
continue;
for (Standard_Integer aPntID = 1; aPntID <= anIntCC2d.NbPoints(); aPntID++)
{
const Standard_Real aParam = anIntCC2d.Point(aPntID).ParamOnFirst();
theArrayOfParameters.Append(aParam);
}
for (Standard_Integer aSegmID = 1; aSegmID <= anIntCC2d.NbSegments(); aSegmID++)
{
GetSegmentBoundary(anIntCC2d.Segment(aSegmID), theC2d, theArrayOfParameters);
}
}
}
//=======================================================================
//function : isDegenerated
//purpose : Check if theAHC2d corresponds to a degenerated edge.
//=======================================================================
static Standard_Boolean isDegenerated(const Handle(GeomAdaptor_HSurface)& theGAHS,
const Handle(Adaptor2d_HCurve2d)& theAHC2d,
const Standard_Real theFirstPar,
const Standard_Real theLastPar)
{
const Standard_Real aSqTol = Precision::Confusion()*Precision::Confusion();
gp_Pnt2d aP2d;
gp_Pnt aP1, aP2;
theAHC2d->D0(theFirstPar, aP2d);
theGAHS->D0(aP2d.X(), aP2d.Y(), aP1);
theAHC2d->D0(theLastPar, aP2d);
theGAHS->D0(aP2d.X(), aP2d.Y(), aP2);
if(aP1.SquareDistance(aP2) > aSqTol)
return Standard_False;
theAHC2d->D0(0.5*(theFirstPar+theLastPar), aP2d);
theGAHS->D0(aP2d.X(), aP2d.Y(), aP2);
if(aP1.SquareDistance(aP2) > aSqTol)
return Standard_False;
return Standard_True;
}
//=======================================================================
//function : MakeCurve
//purpose :
//=======================================================================
void GeomInt_IntSS::MakeCurve(const Standard_Integer Index,
const Handle(Adaptor3d_TopolTool) & dom1,
const Handle(Adaptor3d_TopolTool) & dom2,
const Standard_Real Tol,
const Standard_Boolean Approx,
const Standard_Boolean ApproxS1,
const Standard_Boolean ApproxS2)
{
Standard_Boolean myApprox1, myApprox2, myApprox;
Standard_Real Tolpc, myTolApprox;
IntPatch_IType typl;
Handle(Geom2d_BSplineCurve) H1;
Handle(Geom_Surface) aS1, aS2;
//
Tolpc = Tol;
myApprox=Approx;
myApprox1=ApproxS1;
myApprox2=ApproxS2;
myTolApprox=0.0000001;
//
aS1=myHS1->ChangeSurface().Surface();
aS2=myHS2->ChangeSurface().Surface();
//
Handle(IntPatch_Line) L = myIntersector.Line(Index);
typl = L->ArcType();
//
if(typl==IntPatch_Walking) {
Handle(IntPatch_WLine) aWLine (Handle(IntPatch_WLine)::DownCast(L));
if(aWLine.IsNull()) {
return;
}
L = aWLine;
}
//
// Line Constructor
myLConstruct.Perform(L);
if (!myLConstruct.IsDone() || myLConstruct.NbParts() <= 0) {
return;
}
// Do the Curve
Standard_Boolean ok;
Standard_Integer i, j, aNbParts;
Standard_Real fprm, lprm;
Handle(Geom_Curve) newc;
switch (typl) {
//########################################
// Line, Parabola, Hyperbola
//########################################
case IntPatch_Lin:
case IntPatch_Parabola:
case IntPatch_Hyperbola: {
if (typl == IntPatch_Lin) {
newc=new Geom_Line (Handle(IntPatch_GLine)::DownCast(L)->Line());
}
else if (typl == IntPatch_Parabola) {
newc=new Geom_Parabola(Handle(IntPatch_GLine)::DownCast(L)->Parabola());
}
else if (typl == IntPatch_Hyperbola) {
newc=new Geom_Hyperbola (Handle(IntPatch_GLine)::DownCast(L)->Hyperbola());
}
//
aNbParts=myLConstruct.NbParts();
for (i=1; i<=aNbParts; i++) {
myLConstruct.Part(i, fprm, lprm);
if (!Precision::IsNegativeInfinite(fprm) &&
!Precision::IsPositiveInfinite(lprm)) {
Handle(Geom_TrimmedCurve) aCT3D=new Geom_TrimmedCurve(newc, fprm, lprm);
sline.Append(aCT3D);
//
if(myApprox1) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0.) {
myTolReached2d=Tolpc;
}
slineS1.Append(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
}
else {
slineS1.Append(H1);
}
//
if(myApprox2) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0.) {
myTolReached2d=Tolpc;
}
//
slineS2.Append(new Geom2d_TrimmedCurve(C2d,fprm,lprm));
}
else {
slineS2.Append(H1);
}
} // if (!Precision::IsNegativeInfinite(fprm) && !Precision::IsPositiveInfinite(lprm))
else {
GeomAbs_SurfaceType typS1 = myHS1->Surface().GetType();
GeomAbs_SurfaceType typS2 = myHS2->Surface().GetType();
if( typS1 == GeomAbs_SurfaceOfExtrusion ||
typS1 == GeomAbs_OffsetSurface ||
typS1 == GeomAbs_SurfaceOfRevolution ||
typS2 == GeomAbs_SurfaceOfExtrusion ||
typS2 == GeomAbs_OffsetSurface ||
typS2 == GeomAbs_SurfaceOfRevolution) {
sline.Append(newc);
slineS1.Append(H1);
slineS2.Append(H1);
continue;
}
Standard_Boolean bFNIt, bLPIt;
Standard_Real aTestPrm, dT=100.;
Standard_Real u1, v1, u2, v2, TolX;
//
bFNIt=Precision::IsNegativeInfinite(fprm);
bLPIt=Precision::IsPositiveInfinite(lprm);
aTestPrm=0.;
if (bFNIt && !bLPIt) {
aTestPrm=lprm-dT;
}
else if (!bFNIt && bLPIt) {
aTestPrm=fprm+dT;
}
//
gp_Pnt ptref(newc->Value(aTestPrm));
//
TolX = Precision::Confusion();
Parameters(myHS1, myHS2, ptref, u1, v1, u2, v2);
ok = (dom1->Classify(gp_Pnt2d(u1, v1), TolX) != TopAbs_OUT);
if(ok) {
ok = (dom2->Classify(gp_Pnt2d(u2,v2),TolX) != TopAbs_OUT);
}
if (ok) {
sline.Append(newc);
slineS1.Append(H1);
slineS2.Append(H1);
}
}
}// end of for (i=1; i<=myLConstruct.NbParts(); i++)
}// case IntPatch_Lin: case IntPatch_Parabola: case IntPatch_Hyperbola:
break;
//########################################
// Circle and Ellipse
//########################################
case IntPatch_Circle:
case IntPatch_Ellipse: {
if (typl == IntPatch_Circle) {
newc = new Geom_Circle
(Handle(IntPatch_GLine)::DownCast(L)->Circle());
}
else {
newc = new Geom_Ellipse
(Handle(IntPatch_GLine)::DownCast(L)->Ellipse());
}
//
Standard_Real aPeriod, aRealEpsilon;
//
aRealEpsilon=RealEpsilon();
aPeriod=M_PI+M_PI;
//
aNbParts=myLConstruct.NbParts();
//
for (i=1; i<=aNbParts; i++) {
myLConstruct.Part(i, fprm, lprm);
//
if (Abs(fprm) > aRealEpsilon || Abs(lprm-aPeriod) > aRealEpsilon) {
//==============================================
Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
//
sline.Append(aTC3D);
//
fprm=aTC3D->FirstParameter();
lprm=aTC3D->LastParameter ();
////
if(myApprox1) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0.) {
myTolReached2d=Tolpc;
}
slineS1.Append(C2d);
}
else { ////
slineS1.Append(H1);
}
//
if(myApprox2) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0) {
myTolReached2d=Tolpc;
}
slineS2.Append(C2d);
}
else {
slineS2.Append(H1);
}
//==============================================
} //if (Abs(fprm) > RealEpsilon() || Abs(lprm-2.*M_PI) > RealEpsilon())
//
else {// on regarde si on garde
//
if (aNbParts==1) {
if (Abs(fprm) < RealEpsilon() && Abs(lprm-2.*M_PI) < RealEpsilon()) {
Handle(Geom_TrimmedCurve) aTC3D=new Geom_TrimmedCurve(newc,fprm,lprm);
//
sline.Append(aTC3D);
fprm=aTC3D->FirstParameter();
lprm=aTC3D->LastParameter ();
if(myApprox1) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0) {
myTolReached2d=Tolpc;
}
slineS1.Append(C2d);
}
else { ////
slineS1.Append(H1);
}
if(myApprox2) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0) {
myTolReached2d=Tolpc;
}
slineS2.Append(C2d);
}
else {
slineS2.Append(H1);
}
break;
}
}
//
Standard_Real aTwoPIdiv17, u1, v1, u2, v2, TolX;
//
aTwoPIdiv17=2.*M_PI/17.;
//
for (j=0; j<=17; j++) {
gp_Pnt ptref (newc->Value (j*aTwoPIdiv17));
TolX = Precision::Confusion();
Parameters(myHS1, myHS2, ptref, u1, v1, u2, v2);
ok = (dom1->Classify(gp_Pnt2d(u1,v1),TolX) != TopAbs_OUT);
if(ok) {
ok = (dom2->Classify(gp_Pnt2d(u2,v2),TolX) != TopAbs_OUT);
}
if (ok) {
sline.Append(newc);
//==============================================
if(myApprox1) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0) {
myTolReached2d=Tolpc;
}
slineS1.Append(C2d);
}
else {
slineS1.Append(H1);
}
if(myApprox2) {
Handle (Geom2d_Curve) C2d;
BuildPCurves(fprm, lprm, Tolpc,myHS2->ChangeSurface().Surface(), newc, C2d);
if(Tolpc>myTolReached2d || myTolReached2d==0) {
myTolReached2d=Tolpc;
}
slineS2.Append(C2d);
}
else {
slineS2.Append(H1);
}
break;
}// end of if (ok) {
}// end of for (Standard_Integer j=0; j<=17; j++)
}// end of else { on regarde si on garde
}// for (i=1; i<=myLConstruct.NbParts(); i++)
}// IntPatch_Circle: IntPatch_Ellipse
break;
//########################################
// Analytic
//########################################
case IntPatch_Analytic:
//This case was processed earlier (in IntPatch_Intersection)
break;
//########################################
// Walking
//########################################
case IntPatch_Walking:{
Handle(IntPatch_WLine) WL =
Handle(IntPatch_WLine)::DownCast(L);
#ifdef GEOMINT_INTSS_DEBUG
WL->Dump(0);
#endif
//
Standard_Integer ifprm, ilprm;
//
if (!myApprox) {
aNbParts=myLConstruct.NbParts();
for (i=1; i<=aNbParts; i++) {
myLConstruct.Part(i, fprm, lprm);
ifprm=(Standard_Integer)fprm;
ilprm=(Standard_Integer)lprm;
//
Handle(Geom2d_BSplineCurve) aH1, aH2;
if(myApprox1) {
aH1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
}
if(myApprox2) {
aH2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
}
//
Handle(Geom_Curve) aBSp=MakeBSpline(WL, ifprm, ilprm);
//
sline.Append(aBSp);
slineS1.Append(aH1);
slineS2.Append(aH2);
}
}
//
else {
Standard_Boolean bIsDecomposited;
Standard_Integer nbiter, aNbSeqOfL;
GeomInt_WLApprox theapp3d;
IntPatch_SequenceOfLine aSeqOfL;
Standard_Real tol2d, aTolSS;
//
tol2d = myTolApprox;
aTolSS=2.e-7;
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, myHS1 != myHS2);
//
bIsDecomposited =
GeomInt_LineTool::DecompositionOfWLine(WL, myHS1, myHS2, aTolSS, myLConstruct, aSeqOfL);
//
aNbParts=myLConstruct.NbParts();
aNbSeqOfL=aSeqOfL.Length();
//
nbiter = (bIsDecomposited) ? aNbSeqOfL : aNbParts;
//
for(i = 1; i <= nbiter; i++) {
if(bIsDecomposited) {
WL = Handle(IntPatch_WLine)::DownCast(aSeqOfL.Value(i));
ifprm = 1;
ilprm = WL->NbPnts();
}
else {
myLConstruct.Part(i, fprm, lprm);
ifprm = (Standard_Integer)fprm;
ilprm = (Standard_Integer)lprm;
}
//-- lbr :
//-- Si une des surfaces est un plan , on approxime en 2d
//-- sur cette surface et on remonte les points 2d en 3d.
GeomAbs_SurfaceType typs1, typs2;
typs1 = myHS1->Surface().GetType();
typs2 = myHS2->Surface().GetType();
//
if(typs1 == GeomAbs_Plane) {
theapp3d.Perform(myHS1, myHS2, WL, Standard_False,
Standard_True, myApprox2,
ifprm, ilprm);
}
else if(typs2 == GeomAbs_Plane) {
theapp3d.Perform(myHS1,myHS2,WL,Standard_False,
myApprox1,Standard_True,
ifprm, ilprm);
}
else {
//
if (myHS1 != myHS2){
if ((typs1==GeomAbs_BezierSurface || typs1==GeomAbs_BSplineSurface) &&
(typs2==GeomAbs_BezierSurface || typs2==GeomAbs_BSplineSurface)) {
theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, 30, Standard_True);
//Standard_Boolean bUseSurfaces;
//bUseSurfaces=NotUseSurfacesForApprox(myFace1, myFace2, WL, ifprm, ilprm);
//if (bUseSurfaces) {
//theapp3d.SetParameters(myTolApprox, tol2d, 4, 8, 0, Standard_False);
//}
}
}
//
theapp3d.Perform(myHS1,myHS2,WL,Standard_True,
myApprox1,myApprox2,
ifprm, ilprm);
}
if (!theapp3d.IsDone()) {
//
Handle(Geom2d_BSplineCurve) aH1, aH2;
//
Handle(Geom_Curve) aBSp=MakeBSpline(WL, ifprm, ilprm);
if(myApprox1) {
aH1 = MakeBSpline2d(WL, ifprm, ilprm, Standard_True);
}
if(myApprox2) {
aH2 = MakeBSpline2d(WL, ifprm, ilprm, Standard_False);
}
//
sline.Append(aBSp);
slineS1.Append(aH1);
slineS2.Append(aH2);
}//if (!theapp3d.IsDone())
else {
if(myApprox1 || myApprox2 || (typs1==GeomAbs_Plane || typs2==GeomAbs_Plane)) {
if( theapp3d.TolReached2d()>myTolReached2d || myTolReached2d==0.) {
myTolReached2d = theapp3d.TolReached2d();
}
}
if(typs1==GeomAbs_Plane || typs2==GeomAbs_Plane) {
myTolReached3d = myTolReached2d;
}
else if( theapp3d.TolReached3d()>myTolReached3d || myTolReached3d==0.) {
myTolReached3d = theapp3d.TolReached3d();
}
Standard_Integer aNbMultiCurves, nbpoles;
//
aNbMultiCurves=theapp3d.NbMultiCurves();
for (j=1; j<=aNbMultiCurves; j++) {
if(typs1 == GeomAbs_Plane) {
const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
nbpoles = mbspc.NbPoles();
TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
TColgp_Array1OfPnt tpoles(1,nbpoles);
mbspc.Curve(1,tpoles2d);
const gp_Pln& Pln = myHS1->Surface().Plane();
//
Standard_Integer ik;
for(ik = 1; ik<= nbpoles; ik++) {
tpoles.SetValue(ik,
ElSLib::Value(tpoles2d.Value(ik).X(),
tpoles2d.Value(ik).Y(),
Pln));
}
//
Handle(Geom_BSplineCurve) BS =
new Geom_BSplineCurve(tpoles,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_CheckBSplineCurve Check(BS,myTolCheck,myTolAngCheck);
Check.FixTangent(Standard_True, Standard_True);
//
sline.Append(BS);
//
if(myApprox1) {
Handle(Geom2d_BSplineCurve) BS1 =
new Geom2d_BSplineCurve(tpoles2d,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_Check2dBSplineCurve Check1(BS1,myTolCheck,myTolAngCheck);
Check1.FixTangent(Standard_True,Standard_True);
//
AdjustUPeriodic (aS1, BS1);
//
slineS1.Append(BS1);
}
else {
slineS1.Append(H1);
}
if(myApprox2) {
mbspc.Curve(2, tpoles2d);
Handle(Geom2d_BSplineCurve) BS2 = new Geom2d_BSplineCurve(tpoles2d,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck);
newCheck.FixTangent(Standard_True,Standard_True);
//
AdjustUPeriodic (aS2, BS2);
//
slineS2.Append(BS2);
}
else {
slineS2.Append(H1);
}
}//if(typs1 == GeomAbs_Plane)
//
else if(typs2 == GeomAbs_Plane) {
const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
nbpoles = mbspc.NbPoles();
TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
TColgp_Array1OfPnt tpoles(1,nbpoles);
mbspc.Curve((myApprox1==Standard_True)? 2 : 1,tpoles2d);
const gp_Pln& Pln = myHS2->Surface().Plane();
//
Standard_Integer ik;
for(ik = 1; ik<= nbpoles; ik++) {
tpoles.SetValue(ik,
ElSLib::Value(tpoles2d.Value(ik).X(),
tpoles2d.Value(ik).Y(),
Pln));
}
//
Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_CheckBSplineCurve Check(BS,myTolCheck,myTolAngCheck);
Check.FixTangent(Standard_True,Standard_True);
//
sline.Append(BS);
//
if(myApprox2) {
Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_Check2dBSplineCurve Check1(BS1,myTolCheck,myTolAngCheck);
Check1.FixTangent(Standard_True,Standard_True);
//
//
AdjustUPeriodic (aS2, BS1);
//
slineS2.Append(BS1);
}
else {
slineS2.Append(H1);
}
if(myApprox1) {
mbspc.Curve(1,tpoles2d);
Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_Check2dBSplineCurve Check2(BS2,myTolCheck,myTolAngCheck);
Check2.FixTangent(Standard_True,Standard_True);
//
//
AdjustUPeriodic (aS1, BS2);
//
slineS1.Append(BS2);
}
else {
slineS1.Append(H1);
}
} // else if(typs2 == GeomAbs_Plane)
//
else { // typs1!=GeomAbs_Plane && typs2!=GeomAbs_Plane
const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
nbpoles = mbspc.NbPoles();
TColgp_Array1OfPnt tpoles(1,nbpoles);
mbspc.Curve(1,tpoles);
Handle(Geom_BSplineCurve) BS=new Geom_BSplineCurve(tpoles,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_CheckBSplineCurve Check(BS,myTolCheck,myTolAngCheck);
Check.FixTangent(Standard_True,Standard_True);
//
//Check IsClosed()
Standard_Real aDist = Max(BS->StartPoint().XYZ().SquareModulus(),
BS->EndPoint().XYZ().SquareModulus());
Standard_Real eps = Epsilon(aDist);
if(BS->StartPoint().SquareDistance(BS->EndPoint()) < 2.*eps)
{
// Avoid creating B-splines containing two coincident poles only
if (mbspc.Degree() == 1 && nbpoles == 2)
continue;
if (!BS->IsClosed() && !BS->IsPeriodic())
{
//force Closed()
gp_Pnt aPm((BS->Pole(1).XYZ() + BS->Pole(BS->NbPoles()).XYZ()) / 2.);
BS->SetPole(1, aPm);
BS->SetPole(BS->NbPoles(), aPm);
}
}
sline.Append(BS);
if(myApprox1) {
TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
mbspc.Curve(2,tpoles2d);
Handle(Geom2d_BSplineCurve) BS1=new Geom2d_BSplineCurve(tpoles2d,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_Check2dBSplineCurve newCheck(BS1,myTolCheck,myTolAngCheck);
newCheck.FixTangent(Standard_True,Standard_True);
//
AdjustUPeriodic (aS1, BS1);
//
slineS1.Append(BS1);
}
else {
slineS1.Append(H1);
}
if(myApprox2) {
TColgp_Array1OfPnt2d tpoles2d(1,nbpoles);
mbspc.Curve((myApprox1==Standard_True)? 3 : 2,tpoles2d);
Handle(Geom2d_BSplineCurve) BS2=new Geom2d_BSplineCurve(tpoles2d,
mbspc.Knots(),
mbspc.Multiplicities(),
mbspc.Degree());
GeomLib_Check2dBSplineCurve newCheck(BS2,myTolCheck,myTolAngCheck);
newCheck.FixTangent(Standard_True,Standard_True);
//
AdjustUPeriodic (aS2, BS2);
//
slineS2.Append(BS2);
}
else {
slineS2.Append(H1);
}
}// else { // typs1!=GeomAbs_Plane && typs2!=GeomAbs_Plane
}// for (j=1; j<=aNbMultiCurves; j++
}
}
}
}
break;
case IntPatch_Restriction:
{
Handle(IntPatch_RLine) RL =
Handle(IntPatch_RLine)::DownCast(L);
Handle(Geom_Curve) aC3d;
Handle(Geom2d_Curve) aC2d1, aC2d2;
Standard_Real aTolReached;
TreatRLine(RL, myHS1, myHS2, aC3d,
aC2d1, aC2d2, aTolReached);
if(aC3d.IsNull())
break;
Bnd_Box2d aBox1, aBox2;
const Standard_Real aU1f = myHS1->FirstUParameter(),
aV1f = myHS1->FirstVParameter(),
aU1l = myHS1->LastUParameter(),
aV1l = myHS1->LastVParameter();
const Standard_Real aU2f = myHS2->FirstUParameter(),
aV2f = myHS2->FirstVParameter(),
aU2l = myHS2->LastUParameter(),
aV2l = myHS2->LastVParameter();
aBox1.Add(gp_Pnt2d(aU1f, aV1f));
aBox1.Add(gp_Pnt2d(aU1l, aV1l));
aBox2.Add(gp_Pnt2d(aU2f, aV2f));
aBox2.Add(gp_Pnt2d(aU2l, aV2l));
GeomInt_VectorOfReal anArrayOfParameters;
//We consider here that the intersection line is same-parameter-line
anArrayOfParameters.Append(aC3d->FirstParameter());
anArrayOfParameters.Append(aC3d->LastParameter());
TrimILineOnSurfBoundaries(aC2d1, aC2d2, aBox1, aBox2, anArrayOfParameters);
const Standard_Integer aNbIntersSolutionsm1 = anArrayOfParameters.Length() - 1;
//Trim RLine found.
for(Standard_Integer anInd = 0; anInd < aNbIntersSolutionsm1; anInd++)
{
const Standard_Real aParF = anArrayOfParameters(anInd),
aParL = anArrayOfParameters(anInd+1);
if((aParL - aParF) <= Precision::PConfusion())
continue;
const Standard_Real aPar = 0.5*(aParF + aParL);
gp_Pnt2d aPt;
Handle(Geom2d_Curve) aCurv2d1, aCurv2d2;
if(!aC2d1.IsNull())
{
aC2d1->D0(aPar, aPt);
if(aBox1.IsOut(aPt))
continue;
if(myApprox1)
aCurv2d1 = new Geom2d_TrimmedCurve(aC2d1, aParF, aParL);
}
if(!aC2d2.IsNull())
{
aC2d2->D0(aPar, aPt);
if(aBox2.IsOut(aPt))
continue;
if(myApprox2)
aCurv2d2 = new Geom2d_TrimmedCurve(aC2d2, aParF, aParL);
}
Handle(Geom_Curve) aCurv3d = new Geom_TrimmedCurve(aC3d, aParF, aParL);
sline.Append(aCurv3d);
slineS1.Append(aCurv2d1);
slineS2.Append(aCurv2d2);
}
}
break;
}
}
//=======================================================================
//function : TreatRLine
//purpose : Approx of Restriction line
//=======================================================================
void GeomInt_IntSS::TreatRLine(const Handle(IntPatch_RLine)& theRL,
const Handle(GeomAdaptor_HSurface)& theHS1,
const Handle(GeomAdaptor_HSurface)& theHS2,
Handle(Geom_Curve)& theC3d,
Handle(Geom2d_Curve)& theC2d1,
Handle(Geom2d_Curve)& theC2d2,
Standard_Real& theTolReached)
{
Handle(GeomAdaptor_HSurface) aGAHS;
Handle(Adaptor2d_HCurve2d) anAHC2d;
Standard_Real tf, tl;
gp_Lin2d aL;
// It is assumed that 2d curve is 2d line (rectangular surface domain)
if(theRL->IsArcOnS1())
{
aGAHS = theHS1;
anAHC2d = theRL->ArcOnS1();
theRL->ParamOnS1(tf, tl);
theC2d1 = Geom2dAdaptor::MakeCurve(anAHC2d->Curve2d());
tf = Max(tf, theC2d1->FirstParameter());
tl = Min(tl, theC2d1->LastParameter());
theC2d1 = new Geom2d_TrimmedCurve(theC2d1, tf, tl);
}
else if (theRL->IsArcOnS2())
{
aGAHS = theHS2;
anAHC2d = theRL->ArcOnS2();
theRL->ParamOnS2(tf, tl);
theC2d2 = Geom2dAdaptor::MakeCurve(anAHC2d->Curve2d());
tf = Max(tf, theC2d2->FirstParameter());
tl = Min(tl, theC2d2->LastParameter());
theC2d2 = new Geom2d_TrimmedCurve(theC2d2, tf, tl);
}
else
{
return;
}
//Restriction line can correspond to a degenerated edge.
//In this case we return null-curve.
if(isDegenerated(aGAHS, anAHC2d, tf, tl))
return;
//
//To provide sameparameter it is necessary to get 3d curve as
//approximation of curve on surface.
Standard_Integer aMaxDeg = 8;
Standard_Integer aMaxSeg = 1000;
Approx_CurveOnSurface anApp(anAHC2d, aGAHS, tf, tl, Precision::Confusion(),
GeomAbs_C1, aMaxDeg, aMaxSeg,
Standard_True, Standard_False);
if(!anApp.HasResult())
return;
theC3d = anApp.Curve3d();
theTolReached = anApp.MaxError3d();
Standard_Real aTol = Precision::Confusion();
if(theRL->IsArcOnS1())
{
Handle(Geom_Surface) aS = GeomAdaptor::MakeSurface(theHS2->Surface());
BuildPCurves (tf, tl, aTol,
aS, theC3d, theC2d2);
}
if(theRL->IsArcOnS2())
{
Handle(Geom_Surface) aS = GeomAdaptor::MakeSurface(theHS1->Surface());
BuildPCurves (tf, tl, aTol,
aS, theC3d, theC2d1);
}
theTolReached = Max(theTolReached, aTol);
}
//=======================================================================
//function : BuildPCurves
//purpose :
//=======================================================================
void GeomInt_IntSS::BuildPCurves (Standard_Real f,
Standard_Real l,
Standard_Real& Tol,
const Handle (Geom_Surface)& S,
const Handle (Geom_Curve)& C,
Handle (Geom2d_Curve)& C2d)
{
if (!C2d.IsNull()) {
return;
}
//
Standard_Real umin,umax,vmin,vmax;
//
S->Bounds(umin, umax, vmin, vmax);
// in class ProjLib_Function the range of parameters is shrank by 1.e-09
if((l - f) > 2.e-09) {
C2d = GeomProjLib::Curve2d(C,f,l,S,umin,umax,vmin,vmax,Tol);
if (C2d.IsNull()) {
// proj. a circle that goes through the pole on a sphere to the sphere
Tol += Precision::Confusion();
C2d = GeomProjLib::Curve2d(C,f,l,S,Tol);
}
const Handle(Standard_Type)& aType = C2d->DynamicType();
if ( aType == STANDARD_TYPE(Geom2d_BSplineCurve))
{
//Check first, last knots to avoid problems with trimming
//First, last knots can differ from f, l because of numerical error
//of projection and approximation
//The same checking as in Geom2d_TrimmedCurve
if((C2d->FirstParameter() - f > Precision::PConfusion()) ||
(l - C2d->LastParameter() > Precision::PConfusion()))
{
Handle(Geom2d_BSplineCurve) aBspl = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
TColStd_Array1OfReal aKnots(1, aBspl->NbKnots());
aBspl->Knots(aKnots);
BSplCLib::Reparametrize(f, l, aKnots);
aBspl->SetKnots(aKnots);
}
}
}
else {
if((l - f) > Epsilon(Abs(f)))
{
//The domain of C2d is [Epsilon(Abs(f)), 2.e-09]
//On this small range C2d can be considered as segment
//of line.
Standard_Real aU=0., aV=0.;
GeomAdaptor_Surface anAS;
anAS.Load(S);
Extrema_ExtPS anExtr;
const gp_Pnt aP3d1 = C->Value(f);
const gp_Pnt aP3d2 = C->Value(l);
anExtr.SetAlgo(Extrema_ExtAlgo_Grad);
anExtr.Initialize(anAS, umin, umax, vmin, vmax,
Precision::Confusion(), Precision::Confusion());
anExtr.Perform(aP3d1);
if(ParametersOfNearestPointOnSurface(anExtr, aU, aV))
{
const gp_Pnt2d aP2d1(aU, aV);
anExtr.Perform(aP3d2);
if(ParametersOfNearestPointOnSurface(anExtr, aU, aV))
{
const gp_Pnt2d aP2d2(aU, aV);
if(aP2d1.Distance(aP2d2) > gp::Resolution())
{
TColgp_Array1OfPnt2d poles(1,2);
TColStd_Array1OfReal knots(1,2);
TColStd_Array1OfInteger mults(1,2);
poles(1) = aP2d1;
poles(2) = aP2d2;
knots(1) = f;
knots(2) = l;
mults(1) = mults(2) = 2;
C2d = new Geom2d_BSplineCurve(poles,knots,mults,1);
//Check same parameter in middle point .begin
const gp_Pnt PMid(C->Value(0.5*(f+l)));
const gp_Pnt2d pmidcurve2d(0.5*(aP2d1.XY() + aP2d2.XY()));
const gp_Pnt aPC(anAS.Value(pmidcurve2d.X(), pmidcurve2d.Y()));
const Standard_Real aDist = PMid.Distance(aPC);
Tol = Max(aDist, Tol);
//Check same parameter in middle point .end
}
}
}
}
}
//
if (S->IsUPeriodic() && !C2d.IsNull()) {
// Recadre dans le domaine UV de la face
Standard_Real aTm, U0, aEps, period, du, U0x;
Standard_Boolean bAdjust;
//
aEps = Precision::PConfusion();
period = S->UPeriod();
//
aTm = .5*(f + l);
gp_Pnt2d pm = C2d->Value(aTm);
U0 = pm.X();
//
bAdjust =
GeomInt::AdjustPeriodic(U0, umin, umax, period, U0x, du, aEps);
if (bAdjust) {
gp_Vec2d T1(du, 0.);
C2d->Translate(T1);
}
}
}
//=======================================================================
//function : TrimILineOnSurfBoundaries
//purpose : This function finds intersection points of given curves with
// surface boundaries and fills theArrayOfParameters by parameters
// along the given curves corresponding of these points.
//=======================================================================
void GeomInt_IntSS::TrimILineOnSurfBoundaries(const Handle(Geom2d_Curve)& theC2d1,
const Handle(Geom2d_Curve)& theC2d2,
const Bnd_Box2d& theBound1,
const Bnd_Box2d& theBound2,
GeomInt_VectorOfReal& theArrayOfParameters)
{
//Rectangular boundaries of two surfaces: [0]:U=Ufirst, [1]:U=Ulast,
// [2]:V=Vfirst, [3]:V=Vlast
const Standard_Integer aNumberOfCurves = 4;
Handle(Geom2d_Curve) aCurS1Bounds[aNumberOfCurves];
Handle(Geom2d_Curve) aCurS2Bounds[aNumberOfCurves];
Standard_Real aU1f=0.0, aV1f=0.0, aU1l=0.0, aV1l=0.0;
Standard_Real aU2f=0.0, aV2f=0.0, aU2l=0.0, aV2l=0.0;
theBound1.Get(aU1f, aV1f, aU1l, aV1l);
theBound2.Get(aU2f, aV2f, aU2l, aV2l);
Standard_Real aDelta = aV1l-aV1f;
if(Abs(aDelta) > RealSmall())
{
if(!Precision::IsInfinite(aU1f))
{
aCurS1Bounds[0] = new Geom2d_Line(gp_Pnt2d(aU1f, aV1f), gp_Dir2d(0.0, 1.0));
if(!Precision::IsInfinite(aDelta))
aCurS1Bounds[0] = new Geom2d_TrimmedCurve(aCurS1Bounds[0], 0, aDelta);
}
if(!Precision::IsInfinite(aU1l))
{
aCurS1Bounds[1] = new Geom2d_Line(gp_Pnt2d(aU1l, aV1f), gp_Dir2d(0.0, 1.0));
if(!Precision::IsInfinite(aDelta))
aCurS1Bounds[1] = new Geom2d_TrimmedCurve(aCurS1Bounds[1], 0, aDelta);
}
}
aDelta = aU1l-aU1f;
if(Abs(aDelta) > RealSmall())
{
if(!Precision::IsInfinite(aV1f))
{
aCurS1Bounds[2] = new Geom2d_Line(gp_Pnt2d(aU1f, aV1f), gp_Dir2d(1.0, 0.0));
if(!Precision::IsInfinite(aDelta))
aCurS1Bounds[2] = new Geom2d_TrimmedCurve(aCurS1Bounds[2], 0, aDelta);
}
if(!Precision::IsInfinite(aV1l))
{
aCurS1Bounds[3] = new Geom2d_Line(gp_Pnt2d(aU1l, aV1l), gp_Dir2d(1.0, 0.0));
if(!Precision::IsInfinite(aDelta))
aCurS1Bounds[3] = new Geom2d_TrimmedCurve(aCurS1Bounds[3], 0, aDelta);
}
}
aDelta = aV2l-aV2f;
if(Abs(aDelta) > RealSmall())
{
if(!Precision::IsInfinite(aU2f))
{
aCurS2Bounds[0] = new Geom2d_Line(gp_Pnt2d(aU2f, aV2f), gp_Dir2d(0.0, 1.0));
if(!Precision::IsInfinite(aDelta))
aCurS2Bounds[0] = new Geom2d_TrimmedCurve(aCurS2Bounds[0], 0, aDelta);
}
if(!Precision::IsInfinite(aU2l))
{
aCurS2Bounds[1] = new Geom2d_Line(gp_Pnt2d(aU2l, aV2f), gp_Dir2d(0.0, 1.0));
if(!Precision::IsInfinite(aDelta))
aCurS2Bounds[1] = new Geom2d_TrimmedCurve(aCurS2Bounds[1], 0, aDelta);
}
}
aDelta = aU2l-aU2f;
if(Abs(aDelta) > RealSmall())
{
if(!Precision::IsInfinite(aV2f))
{
aCurS2Bounds[2] = new Geom2d_Line(gp_Pnt2d(aU2f, aV2f), gp_Dir2d(1.0, 0.0));
if(!Precision::IsInfinite(aDelta))
aCurS2Bounds[2] = new Geom2d_TrimmedCurve(aCurS2Bounds[2], 0, aDelta);
}
if(!Precision::IsInfinite(aV2l))
{
aCurS2Bounds[3] = new Geom2d_Line(gp_Pnt2d(aU2l, aV2l), gp_Dir2d(1.0, 0.0));
if(!Precision::IsInfinite(aDelta))
aCurS2Bounds[3] = new Geom2d_TrimmedCurve(aCurS2Bounds[3], 0, aDelta);
}
}
const Standard_Real anIntTol = 10.0*Precision::Confusion();
IntersectCurveAndBoundary(theC2d1, aCurS1Bounds,
aNumberOfCurves, anIntTol, theArrayOfParameters);
IntersectCurveAndBoundary(theC2d2, aCurS2Bounds,
aNumberOfCurves, anIntTol, theArrayOfParameters);
std::sort(theArrayOfParameters.begin(), theArrayOfParameters.end());
}
//=======================================================================
//function : MakeBSpline
//purpose :
//=======================================================================
Handle(Geom_Curve) GeomInt_IntSS::MakeBSpline (const Handle(IntPatch_WLine)& WL,
const Standard_Integer ideb,
const Standard_Integer ifin)
{
const Standard_Integer nbpnt = ifin-ideb+1;
TColgp_Array1OfPnt poles(1,nbpnt);
TColStd_Array1OfReal knots(1,nbpnt);
TColStd_Array1OfInteger mults(1,nbpnt);
Standard_Integer i = 1, ipidebm1 = ideb;
for(; i<=nbpnt; ipidebm1++, i++)
{
poles(i) = WL->Point(ipidebm1).Value();
mults(i) = 1;
knots(i) = i-1;
}
mults(1) = mults(nbpnt) = 2;
return new Geom_BSplineCurve(poles,knots,mults,1);
}
//=======================================================================
//function : MakeBSpline2d
//purpose :
//=======================================================================
Handle(Geom2d_BSplineCurve) GeomInt_IntSS::
MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
const Standard_Integer ideb,
const Standard_Integer ifin,
const Standard_Boolean onFirst)
{
const Standard_Integer nbpnt = ifin-ideb+1;
TColgp_Array1OfPnt2d poles(1,nbpnt);
TColStd_Array1OfReal knots(1,nbpnt);
TColStd_Array1OfInteger mults(1,nbpnt);
Standard_Integer i = 1, ipidebm1 = ideb;
for(; i <= nbpnt; ipidebm1++, i++)
{
Standard_Real U, V;
if(onFirst)
theWLine->Point(ipidebm1).ParametersOnS1(U, V);
else
theWLine->Point(ipidebm1).ParametersOnS2(U, V);
poles(i).SetCoord(U, V);
mults(i) = 1;
knots(i) = i-1;
}
mults(1) = mults(nbpnt) = 2;
return new Geom2d_BSplineCurve(poles,knots,mults,1);
}