Loading files
b8f597c67This file is pinned to the selected release. Download the original to open it in your design tool.
// 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 <IntTools_WLineTool.hxx>
#include <BRep_Tool.hxx>
#include <Extrema_ExtCC.hxx>
#include <Geom2dAPI_InterCurveCurve.hxx>
#include <Geom2d_Circle.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomInt.hxx>
#include <GeomInt_LineConstructor.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Surface.hxx>
#include <gp_Circ.hxx>
#include <IntTools_Context.hxx>
#include <Standard_Integer.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Sequence.hxx>
#include <gp_Pnt2d.hxx>
/////////////////////// NotUseSurfacesForApprox /////////////////////////
// The block is dedicated to determine whether WLine [ifprm, ilprm]
// crosses the degenerated zone on each given surface or not.
// If Yes -> We will not use info about surfaces during approximation
// because inside degenerated zone of the surface the approx. algo.
// uses wrong values of normal, etc., and resulting curve will have
// oscillations that we would not like to have.
//=======================================================================
// function : IsDegeneratedZone
// purpose : static subfunction in IsDegeneratedZone
//=======================================================================
static bool IsDegeneratedZone(const gp_Pnt2d& aP2d,
const occ::handle<Geom_Surface>& aS,
const int iDir)
{
bool bFlag = true;
double US1, US2, VS1, VS2, dY, dX, d1, d2, dD;
double aXm, aYm, aXb, aYb, aXe, aYe;
aS->Bounds(US1, US2, VS1, VS2);
gp_Pnt aPm, aPb, aPe;
aXm = aP2d.X();
aYm = aP2d.Y();
aS->D0(aXm, aYm, aPm);
dX = 1.e-5;
dY = 1.e-5;
dD = 1.e-12;
if (iDir == 1)
{
aXb = aXm;
aXe = aXm;
aYb = aYm - dY;
if (aYb < VS1)
{
aYb = VS1;
}
aYe = aYm + dY;
if (aYe > VS2)
{
aYe = VS2;
}
aS->D0(aXb, aYb, aPb);
aS->D0(aXe, aYe, aPe);
d1 = aPm.Distance(aPb);
d2 = aPm.Distance(aPe);
if (d1 < dD && d2 < dD)
{
return bFlag;
}
return !bFlag;
}
//
else if (iDir == 2)
{
aYb = aYm;
aYe = aYm;
aXb = aXm - dX;
if (aXb < US1)
{
aXb = US1;
}
aXe = aXm + dX;
if (aXe > US2)
{
aXe = US2;
}
aS->D0(aXb, aYb, aPb);
aS->D0(aXe, aYe, aPe);
d1 = aPm.Distance(aPb);
d2 = aPm.Distance(aPe);
if (d1 < dD && d2 < dD)
{
return bFlag;
}
return !bFlag;
}
return !bFlag;
}
//=======================================================================
// function : IsPointInDegeneratedZone
// purpose : static subfunction in NotUseSurfacesForApprox
//=======================================================================
static bool IsPointInDegeneratedZone(const IntSurf_PntOn2S& aP2S,
const TopoDS_Face& aF1,
const TopoDS_Face& aF2)
{
bool bFlag = true;
double US11, US12, VS11, VS12, US21, US22, VS21, VS22;
double U1, V1, U2, V2, aDelta, aD;
gp_Pnt2d aP2d;
occ::handle<Geom_Surface> aS1 = BRep_Tool::Surface(aF1);
aS1->Bounds(US11, US12, VS11, VS12);
GeomAdaptor_Surface aGAS1(aS1);
occ::handle<Geom_Surface> aS2 = BRep_Tool::Surface(aF2);
aS1->Bounds(US21, US22, VS21, VS22);
GeomAdaptor_Surface aGAS2(aS2);
//
// const gp_Pnt& aP=aP2S.Value();
aP2S.Parameters(U1, V1, U2, V2);
//
aDelta = 1.e-7;
// Check on Surf 1
aD = aGAS1.UResolution(aDelta);
aP2d.SetCoord(U1, V1);
if (fabs(U1 - US11) < aD)
{
bFlag = IsDegeneratedZone(aP2d, aS1, 1);
if (bFlag)
{
return bFlag;
}
}
if (fabs(U1 - US12) < aD)
{
bFlag = IsDegeneratedZone(aP2d, aS1, 1);
if (bFlag)
{
return bFlag;
}
}
aD = aGAS1.VResolution(aDelta);
if (fabs(V1 - VS11) < aDelta)
{
bFlag = IsDegeneratedZone(aP2d, aS1, 2);
if (bFlag)
{
return bFlag;
}
}
if (fabs(V1 - VS12) < aDelta)
{
bFlag = IsDegeneratedZone(aP2d, aS1, 2);
if (bFlag)
{
return bFlag;
}
}
// Check on Surf 2
aD = aGAS2.UResolution(aDelta);
aP2d.SetCoord(U2, V2);
if (fabs(U2 - US21) < aDelta)
{
bFlag = IsDegeneratedZone(aP2d, aS2, 1);
if (bFlag)
{
return bFlag;
}
}
if (fabs(U2 - US22) < aDelta)
{
bFlag = IsDegeneratedZone(aP2d, aS2, 1);
if (bFlag)
{
return bFlag;
}
}
aD = aGAS2.VResolution(aDelta);
if (fabs(V2 - VS21) < aDelta)
{
bFlag = IsDegeneratedZone(aP2d, aS2, 2);
if (bFlag)
{
return bFlag;
}
}
if (fabs(V2 - VS22) < aDelta)
{
bFlag = IsDegeneratedZone(aP2d, aS2, 2);
if (bFlag)
{
return bFlag;
}
}
return !bFlag;
}
//=================================================================================================
bool IntTools_WLineTool::NotUseSurfacesForApprox(const TopoDS_Face& aF1,
const TopoDS_Face& aF2,
const occ::handle<IntPatch_WLine>& WL,
const int ifprm,
const int ilprm)
{
bool bPInDZ;
occ::handle<IntSurf_LineOn2S> aLineOn2S = WL->Curve();
const IntSurf_PntOn2S& aP2Sfprm = aLineOn2S->Value(ifprm);
bPInDZ = IsPointInDegeneratedZone(aP2Sfprm, aF1, aF2);
if (bPInDZ)
{
return bPInDZ;
}
const IntSurf_PntOn2S& aP2Slprm = aLineOn2S->Value(ilprm);
bPInDZ = IsPointInDegeneratedZone(aP2Slprm, aF1, aF2);
return bPInDZ;
}
/////////////////////// end of NotUseSurfacesForApprox //////////////////
/////////////////////// DecompositionOfWLine ////////////////////////////
//=======================================================================
// function : IsPointOnBoundary
// purpose : static subfunction in DecompositionOfWLine
//=======================================================================
static bool IsPointOnBoundary(const double theParameter,
const double theFirstBoundary,
const double theSecondBoundary,
const double theResolution,
bool& IsOnFirstBoundary)
{
bool bRet;
int i;
double adist;
//
bRet = false;
for (i = 0; i < 2; ++i)
{
IsOnFirstBoundary = (i == 0);
if (IsOnFirstBoundary)
{
adist = fabs(theParameter - theFirstBoundary);
}
else
{
adist = fabs(theParameter - theSecondBoundary);
}
if (adist < theResolution)
{
return !bRet;
}
}
return bRet;
}
//=======================================================================
// function : AdjustByNeighbour
// purpose : static subfunction in DecompositionOfWLine
//=======================================================================
static gp_Pnt2d AdjustByNeighbour(const gp_Pnt2d& theaNeighbourPoint,
const gp_Pnt2d& theOriginalPoint,
const occ::handle<GeomAdaptor_Surface>& theGASurface)
{
gp_Pnt2d ap1 = theaNeighbourPoint;
gp_Pnt2d ap2 = theOriginalPoint;
if (theGASurface->IsUPeriodic())
{
double aPeriod = theGASurface->UPeriod();
gp_Pnt2d aPTest = ap2;
double aSqDistMin = 1.e+100;
for (int pIt = -1; pIt <= 1; pIt++)
{
aPTest.SetX(theOriginalPoint.X() + aPeriod * pIt);
double dd = ap1.SquareDistance(aPTest);
if (dd < aSqDistMin)
{
ap2 = aPTest;
aSqDistMin = dd;
}
}
}
if (theGASurface->IsVPeriodic())
{
double aPeriod = theGASurface->VPeriod();
gp_Pnt2d aPTest = ap2;
double aSqDistMin = 1.e+100;
for (int pIt = -1; pIt <= 1; pIt++)
{
aPTest.SetY(theOriginalPoint.Y() + aPeriod * pIt);
double dd = ap1.SquareDistance(aPTest);
if (dd < aSqDistMin)
{
ap2 = aPTest;
aSqDistMin = dd;
}
}
}
return ap2;
}
//=======================================================================
// function : RefineVector
// purpose : static subfunction in FindPoint
//=======================================================================
static void RefineVector(gp_Vec2d& aV2D)
{
int k, m;
double aC[2], aEps, aR1, aR2, aNum;
//
aEps = RealEpsilon();
aR1 = 1. - aEps;
aR2 = 1. + aEps;
//
aV2D.Coord(aC[0], aC[1]);
//
for (k = 0; k < 2; ++k)
{
m = (k + 1) % 2;
aNum = fabs(aC[k]);
if (aNum > aR1 && aNum < aR2)
{
if (aC[k] < 0.)
{
aC[k] = -1.;
}
else
{
aC[k] = 1.;
}
aC[m] = 0.;
break;
}
}
aV2D.SetCoord(aC[0], aC[1]);
}
//=======================================================================
// function : FindPoint
// purpose : static subfunction in DecompositionOfWLine
//=======================================================================
static bool FindPoint(const gp_Pnt2d& theFirstPoint,
const gp_Pnt2d& theLastPoint,
const double theUmin,
const double theUmax,
const double theVmin,
const double theVmax,
gp_Pnt2d& theNewPoint)
{
gp_Vec2d aVec(theFirstPoint, theLastPoint);
int i = 0, j = 0;
for (i = 0; i < 4; i++)
{
gp_Vec2d anOtherVec;
gp_Vec2d anOtherVecNormal;
gp_Pnt2d aprojpoint = theLastPoint;
if ((i % 2) == 0)
{
anOtherVec.SetX(0.);
anOtherVec.SetY(1.);
anOtherVecNormal.SetX(1.);
anOtherVecNormal.SetY(0.);
if (i < 2)
{
aprojpoint.SetX(theUmin);
}
else
{
aprojpoint.SetX(theUmax);
}
}
else
{
anOtherVec.SetX(1.);
anOtherVec.SetY(0.);
anOtherVecNormal.SetX(0.);
anOtherVecNormal.SetY(1.);
if (i < 2)
{
aprojpoint.SetY(theVmin);
}
else
{
aprojpoint.SetY(theVmax);
}
}
gp_Vec2d anormvec = aVec;
anormvec.Normalize();
RefineVector(anormvec);
double adot1 = anormvec.Dot(anOtherVecNormal);
if (fabs(adot1) < Precision::Angular())
{
continue;
}
double adist = 0.;
bool bIsOut = false;
if ((i % 2) == 0)
{
adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
bIsOut = (i < 2) ? (theLastPoint.X() < theUmin) : (theLastPoint.X() > theUmax);
}
else
{
adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
bIsOut = (i < 2) ? (theLastPoint.Y() < theVmin) : (theLastPoint.Y() > theVmax);
}
double anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
for (j = 0; j < 2; j++)
{
anoffset = (j == 0) ? anoffset : -anoffset;
gp_Pnt2d acurpoint(aprojpoint.XY() + (anOtherVec.XY() * anoffset));
gp_Vec2d acurvec(theLastPoint, acurpoint);
if (bIsOut)
{
acurvec.Reverse();
}
double aDotX, anAngleX;
//
aDotX = aVec.Dot(acurvec);
anAngleX = aVec.Angle(acurvec);
//
if (aDotX > 0. && fabs(anAngleX) < Precision::PConfusion())
{
if ((i % 2) == 0)
{
if ((acurpoint.Y() >= theVmin) && (acurpoint.Y() <= theVmax))
{
theNewPoint = acurpoint;
return true;
}
}
else
{
if ((acurpoint.X() >= theUmin) && (acurpoint.X() <= theUmax))
{
theNewPoint = acurpoint;
return true;
}
}
}
}
}
return false;
}
//=================================================================================================
bool IntTools_WLineTool::DecompositionOfWLine(
const occ::handle<IntPatch_WLine>& theWLine,
const occ::handle<GeomAdaptor_Surface>& theSurface1,
const occ::handle<GeomAdaptor_Surface>& theSurface2,
const TopoDS_Face& theFace1,
const TopoDS_Face& theFace2,
const GeomInt_LineConstructor& theLConstructor,
const bool theAvoidLConstructor,
const double theTol,
NCollection_Sequence<occ::handle<IntPatch_Line>>& theNewLines,
const occ::handle<IntTools_Context>& aContext)
{
bool bRet, bAvoidLineConstructor;
int aNbPnts, aNbParts;
//
bRet = false;
aNbPnts = theWLine->NbPnts();
bAvoidLineConstructor = theAvoidLConstructor;
//
if (!aNbPnts)
{
return bRet;
}
if (!bAvoidLineConstructor)
{
aNbParts = theLConstructor.NbParts();
if (!aNbParts)
{
return bRet;
}
}
//
bool bIsPrevPointOnBoundary, bIsPointOnBoundary, bIsCurrentPointOnBoundary;
int nblines, pit, i, j;
double aTol;
NCollection_Array1<NCollection_List<int>> anArrayOfLines(1, aNbPnts);
NCollection_Array1<int> anArrayOfLineType(1, aNbPnts);
NCollection_List<int> aListOfPointIndex;
//
nblines = 0;
aTol = Precision::Confusion();
aTol = 0.5 * aTol;
bIsPrevPointOnBoundary = false;
bIsPointOnBoundary = false;
//
// 1. ...
//
// Points
for (pit = 1; pit <= aNbPnts; ++pit)
{
bool bIsOnFirstBoundary, isperiodic;
double aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
double aParameter, anoffset, anAdjustPar;
double umin, umax, vmin, vmax;
//
bIsCurrentPointOnBoundary = false;
const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
//
// Surface
for (i = 0; i < 2; ++i)
{
occ::handle<GeomAdaptor_Surface> aGASurface = (!i) ? theSurface1 : theSurface2;
aGASurface->Surface()->Bounds(umin, umax, vmin, vmax);
if (!i)
{
aPoint.ParametersOnS1(U, V);
}
else
{
aPoint.ParametersOnS2(U, V);
}
// U, V
for (j = 0; j < 2; j++)
{
isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
if (!isperiodic)
{
continue;
}
//
if (!j)
{
aResolution = aGASurface->UResolution(aTol);
aPeriod = aGASurface->UPeriod();
alowerboundary = umin;
aupperboundary = umax;
aParameter = U;
}
else
{
aResolution = aGASurface->VResolution(aTol);
aPeriod = aGASurface->VPeriod();
alowerboundary = vmin;
aupperboundary = vmax;
aParameter = V;
}
GeomInt::AdjustPeriodic(aParameter,
alowerboundary,
aupperboundary,
aPeriod,
anAdjustPar,
anoffset);
//
bIsOnFirstBoundary = true; // ?
bIsPointOnBoundary = IsPointOnBoundary(anAdjustPar,
alowerboundary,
aupperboundary,
aResolution,
bIsOnFirstBoundary);
//
if (bIsPointOnBoundary)
{
bIsCurrentPointOnBoundary = true;
break;
}
} // for(j = 0; j < 2; j++) {
if (bIsCurrentPointOnBoundary)
{
break;
}
} // for(i = 0; i < 2; ++i) {
//
if ((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary))
{
if (!aListOfPointIndex.IsEmpty())
{
nblines++;
anArrayOfLines.SetValue(nblines, aListOfPointIndex);
anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
aListOfPointIndex.Clear();
}
bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
}
aListOfPointIndex.Append(pit);
} // for(pit = 1; pit <= aNbPnts; ++pit) {
//
if (!aListOfPointIndex.IsEmpty())
{
nblines++;
anArrayOfLines.SetValue(nblines, aListOfPointIndex);
anArrayOfLineType.SetValue(nblines, bIsPrevPointOnBoundary);
aListOfPointIndex.Clear();
}
//
if (nblines <= 1)
{
return bRet; // false;
}
//
//
// 2. Correct wlines.begin
NCollection_Array1<NCollection_List<int>> anArrayOfLineEnds(1, nblines);
occ::handle<IntSurf_LineOn2S> aSeqOfPntOn2S = new IntSurf_LineOn2S();
//
for (i = 1; i <= nblines; i++)
{
if (anArrayOfLineType.Value(i) != 0)
{
continue;
}
const NCollection_List<int>& aListOfIndex = anArrayOfLines.Value(i);
NCollection_List<int> aListOfFLIndex;
for (j = 0; j < 2; j++)
{
int aneighbourindex = (j == 0) ? (i - 1) : (i + 1);
if ((aneighbourindex < 1) || (aneighbourindex > nblines))
{
continue;
}
if (anArrayOfLineType.Value(aneighbourindex) == 0)
{
continue;
}
const NCollection_List<int>& aNeighbour = anArrayOfLines.Value(aneighbourindex);
int anIndex = (j == 0) ? aNeighbour.Last() : aNeighbour.First();
const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
IntSurf_PntOn2S aNewP = aPoint;
if (aListOfIndex.Extent() < 2)
{
aSeqOfPntOn2S->Add(aNewP);
aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
continue;
}
//
int iFirst = aListOfIndex.First();
int iLast = aListOfIndex.Last();
//
for (int surfit = 0; surfit < 2; surfit++)
{
occ::handle<GeomAdaptor_Surface> aGASurface = (surfit == 0) ? theSurface1 : theSurface2;
double umin = 0., umax = 0., vmin = 0., vmax = 0.;
aGASurface->Surface()->Bounds(umin, umax, vmin, vmax);
double U = 0., V = 0.;
if (surfit == 0)
{
aNewP.ParametersOnS1(U, V);
}
else
{
aNewP.ParametersOnS2(U, V);
}
int nbboundaries = 0;
bool bIsNearBoundary = false;
// int aZoneIndex = 0;
int bIsUBoundary = false; // use if nbboundaries == 1
int bIsFirstBoundary = false; // use if nbboundaries == 1
for (int parit = 0; parit < 2; parit++)
{
bool isperiodic = (parit == 0) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
double aResolution =
(parit == 0) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
double alowerboundary = (parit == 0) ? umin : vmin;
double aupperboundary = (parit == 0) ? umax : vmax;
double aParameter = (parit == 0) ? U : V;
bool bIsOnFirstBoundary = true;
if (!isperiodic)
{
bIsPointOnBoundary = IsPointOnBoundary(aParameter,
alowerboundary,
aupperboundary,
aResolution,
bIsOnFirstBoundary);
if (bIsPointOnBoundary)
{
bIsUBoundary = (parit == 0);
bIsFirstBoundary = bIsOnFirstBoundary;
nbboundaries++;
}
}
else
{
double aPeriod = (parit == 0) ? aGASurface->UPeriod() : aGASurface->VPeriod();
double anoffset, anAdjustPar;
GeomInt::AdjustPeriodic(aParameter,
alowerboundary,
aupperboundary,
aPeriod,
anAdjustPar,
anoffset);
bIsPointOnBoundary = IsPointOnBoundary(anAdjustPar,
alowerboundary,
aupperboundary,
aResolution,
bIsOnFirstBoundary);
if (bIsPointOnBoundary)
{
bIsUBoundary = (parit == 0);
bIsFirstBoundary = bIsOnFirstBoundary;
nbboundaries++;
}
else
{
// check neighbourhood of boundary
double anEpsilon = aResolution * 100.;
double aPart = (aupperboundary - alowerboundary) * 0.1;
anEpsilon = (anEpsilon > aPart) ? aPart : anEpsilon;
bIsNearBoundary = IsPointOnBoundary(anAdjustPar,
alowerboundary,
aupperboundary,
anEpsilon,
bIsOnFirstBoundary);
}
}
}
bool bComputeLineEnd = false;
if (nbboundaries == 2)
{
// xf
bComputeLineEnd = true;
// xt
}
else if (nbboundaries == 1)
{
bool isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
if (isperiodic)
{
double alowerboundary = (bIsUBoundary) ? umin : vmin;
double aupperboundary = (bIsUBoundary) ? umax : vmax;
double aPeriod = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
double aParameter = (bIsUBoundary) ? U : V;
double anoffset, anAdjustPar;
GeomInt::AdjustPeriodic(aParameter,
alowerboundary,
aupperboundary,
aPeriod,
anAdjustPar,
anoffset);
double adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary)
: fabs(anAdjustPar - aupperboundary);
double anotherPar =
(bIsFirstBoundary) ? (aupperboundary - adist) : (alowerboundary + adist);
anotherPar += anoffset;
int aneighbourpointindex = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex);
double nU1, nV1;
if (surfit == 0)
{
aNeighbourPoint.ParametersOnS1(nU1, nV1);
}
else
{
aNeighbourPoint.ParametersOnS2(nU1, nV1);
}
double adist1 = (bIsUBoundary) ? fabs(nU1 - U) : fabs(nV1 - V);
double adist2 = (bIsUBoundary) ? fabs(nU1 - anotherPar) : fabs(nV1 - anotherPar);
bComputeLineEnd = true;
bool bCheckAngle1 = false;
bool bCheckAngle2 = false;
gp_Vec2d aNewVec;
double anewU = (bIsUBoundary) ? anotherPar : U;
double anewV = (bIsUBoundary) ? V : anotherPar;
if (((adist1 - adist2) > Precision::PConfusion()) && (adist2 < (aPeriod / 4.)))
{
bCheckAngle1 = true;
aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
if (aNewVec.SquareMagnitude() < gp::Resolution())
{
aNewP.SetValue((surfit == 0), anewU, anewV);
bCheckAngle1 = false;
}
}
else if (adist1 < (aPeriod / 4.))
{
bCheckAngle2 = true;
aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
if (aNewVec.SquareMagnitude() < gp::Resolution())
{
bCheckAngle2 = false;
}
}
if (bCheckAngle1 || bCheckAngle2)
{
// assume there are at least two points in line (see "if" above)
int anindexother = aneighbourpointindex;
while ((anindexother <= iLast) && (anindexother >= iFirst))
{
anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
double nU2, nV2;
if (surfit == 0)
{
aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
}
else
{
aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
}
gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
if (aVecOld.SquareMagnitude() <= gp::Resolution())
{
continue;
}
else
{
double anAngle = aNewVec.Angle(aVecOld);
if ((fabs(anAngle) < (M_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.))
{
if (bCheckAngle1)
{
double U1, U2, V1, V2;
IntSurf_PntOn2S atmppoint = aNewP;
atmppoint.SetValue((surfit == 0), anewU, anewV);
atmppoint.Parameters(U1, V1, U2, V2);
gp_Pnt P1 = theSurface1->Value(U1, V1);
gp_Pnt P2 = theSurface2->Value(U2, V2);
gp_Pnt P0 = aPoint.Value();
if (P0.IsEqual(P1, aTol) && P0.IsEqual(P2, aTol) && P1.IsEqual(P2, aTol))
{
bComputeLineEnd = false;
aNewP.SetValue((surfit == 0), anewU, anewV);
}
}
if (bCheckAngle2)
{
bComputeLineEnd = false;
}
}
break;
}
} // end while(anindexother...)
}
}
}
else if (bIsNearBoundary)
{
bComputeLineEnd = true;
}
if (bComputeLineEnd)
{
gp_Pnt2d anewpoint;
bool found = false;
if (bIsNearBoundary)
{
// re-compute point near natural boundary or near tangent zone
double u1, v1, u2, v2;
aNewP.Parameters(u1, v1, u2, v2);
if (surfit == 0)
{
anewpoint = gp_Pnt2d(u1, v1);
}
else
{
anewpoint = gp_Pnt2d(u2, v2);
}
int aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
double nU1, nV1;
if (surfit == 0)
{
aNeighbourPoint.ParametersOnS1(nU1, nV1);
}
else
{
aNeighbourPoint.ParametersOnS2(nU1, nV1);
}
gp_Pnt2d ap1(nU1, nV1);
gp_Pnt2d ap2;
if (aGASurface->IsUPeriodic() || aGASurface->IsVPeriodic())
{
// re-compute point near boundary if shifted on a period
ap2 = AdjustByNeighbour(ap1, anewpoint, aGASurface);
if ((ap2.X() < umin) || (ap2.X() > umax) || (ap2.Y() < vmin) || (ap2.Y() > vmax))
{
found = FindPoint(ap1, ap2, umin, umax, vmin, vmax, anewpoint);
}
else
{
anewpoint = ap2;
aNewP.SetValue((surfit == 0), anewpoint.X(), anewpoint.Y());
}
}
}
else
{
int aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
double nU1, nV1;
if (surfit == 0)
{
aNeighbourPoint.ParametersOnS1(nU1, nV1);
}
else
{
aNeighbourPoint.ParametersOnS2(nU1, nV1);
}
gp_Pnt2d ap1(nU1, nV1);
gp_Pnt2d ap2(nU1, nV1);
int aneighbourpointindex2 = aneighbourpointindex1;
while ((aneighbourpointindex2 <= iLast) && (aneighbourpointindex2 >= iFirst))
{
aneighbourpointindex2 =
(j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
double nU2, nV2;
if (surfit == 0)
{
aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
}
else
{
aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
}
ap2.SetX(nU2);
ap2.SetY(nV2);
if (ap1.SquareDistance(ap2) > gp::Resolution())
{
break;
}
}
found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
}
if (found)
{
// check point
double aCriteria = theTol;
GeomAPI_ProjectPointOnSurf& aProjector =
(surfit == 0) ? aContext->ProjPS(theFace2) : aContext->ProjPS(theFace1);
occ::handle<GeomAdaptor_Surface> aSurface = (surfit == 0) ? theSurface1 : theSurface2;
occ::handle<GeomAdaptor_Surface> aSurfaceOther =
(surfit == 0) ? theSurface2 : theSurface1;
gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
aProjector.Perform(aP3d);
if (aProjector.IsDone())
{
if (aProjector.LowerDistance() < aCriteria)
{
double foundU = U, foundV = V;
aProjector.LowerDistanceParameters(foundU, foundV);
// Correction of projected coordinates. Begin
// Note, it may be shifted on a period
int aneindex1 = (j == 0) ? iFirst : iLast;
const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneindex1);
double nUn, nVn;
if (surfit == 0)
{
aNeighbourPoint.ParametersOnS2(nUn, nVn);
}
else
{
aNeighbourPoint.ParametersOnS1(nUn, nVn);
}
gp_Pnt2d aNeighbour2d(nUn, nVn);
gp_Pnt2d anAdjustedPoint =
AdjustByNeighbour(aNeighbour2d, gp_Pnt2d(foundU, foundV), aSurfaceOther);
foundU = anAdjustedPoint.X();
foundV = anAdjustedPoint.Y();
if ((anAdjustedPoint.X() < umin) && (anAdjustedPoint.X() > umax)
&& (anAdjustedPoint.Y() < vmin) && (anAdjustedPoint.Y() > vmax))
{
// attempt to roughly re-compute point
foundU = (foundU < umin) ? umin : foundU;
foundU = (foundU > umax) ? umax : foundU;
foundV = (foundV < vmin) ? vmin : foundV;
foundV = (foundV > vmax) ? vmax : foundV;
GeomAPI_ProjectPointOnSurf& aProjector2 =
(surfit == 0) ? aContext->ProjPS(theFace1) : aContext->ProjPS(theFace2);
aP3d = aSurfaceOther->Value(foundU, foundV);
aProjector2.Perform(aP3d);
if (aProjector2.IsDone())
{
if (aProjector2.LowerDistance() < aCriteria)
{
double foundU2 = anewpoint.X(), foundV2 = anewpoint.Y();
aProjector2.LowerDistanceParameters(foundU2, foundV2);
anewpoint.SetX(foundU2);
anewpoint.SetY(foundV2);
}
}
}
// Correction of projected coordinates. End
if (surfit == 0)
{
aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
}
else
{
aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
}
}
}
}
}
}
aSeqOfPntOn2S->Add(aNewP);
aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
}
anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
}
// Correct wlines.end
// Split wlines.begin
int nbiter;
//
nbiter = 1;
if (!bAvoidLineConstructor)
{
nbiter = theLConstructor.NbParts();
}
//
for (j = 1; j <= nbiter; ++j)
{
double fprm, lprm;
int ifprm, ilprm;
//
if (bAvoidLineConstructor)
{
ifprm = 1;
ilprm = theWLine->NbPnts();
}
else
{
theLConstructor.Part(j, fprm, lprm);
ifprm = (int)fprm;
ilprm = (int)lprm;
}
occ::handle<IntSurf_LineOn2S> aLineOn2S = new IntSurf_LineOn2S();
//
for (i = 1; i <= nblines; i++)
{
if (anArrayOfLineType.Value(i) != 0)
{
continue;
}
const NCollection_List<int>& aListOfIndex = anArrayOfLines.Value(i);
const NCollection_List<int>& aListOfFLIndex = anArrayOfLineEnds.Value(i);
bool bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
bool bhaslastpoint = (aListOfFLIndex.Extent() == 2);
if (!bhasfirstpoint && !aListOfFLIndex.IsEmpty())
{
bhasfirstpoint = (i != 1);
}
if (!bhaslastpoint && !aListOfFLIndex.IsEmpty())
{
bhaslastpoint = (i != nblines);
}
int iFirst = aListOfIndex.First();
int iLast = aListOfIndex.Last();
bool bIsFirstInside = ((ifprm >= iFirst) && (ifprm <= iLast));
bool bIsLastInside = ((ilprm >= iFirst) && (ilprm <= iLast));
if (!bIsFirstInside && !bIsLastInside)
{
if ((ifprm < iFirst) && (ilprm > iLast))
{
// append whole line, and boundaries if necessary
if (bhasfirstpoint)
{
pit = aListOfFLIndex.First();
const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
aLineOn2S->Add(aP);
}
NCollection_List<int>::Iterator anIt(aListOfIndex);
for (; anIt.More(); anIt.Next())
{
pit = anIt.Value();
const IntSurf_PntOn2S& aP = theWLine->Point(pit);
aLineOn2S->Add(aP);
}
if (bhaslastpoint)
{
pit = aListOfFLIndex.Last();
const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
aLineOn2S->Add(aP);
}
// check end of split line (end is almost always)
int aneighbour = i + 1;
bool bIsEndOfLine = true;
if (aneighbour <= nblines)
{
const NCollection_List<int>& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
if ((anArrayOfLineType.Value(aneighbour) != 0) && (aListOfNeighbourIndex.IsEmpty()))
{
bIsEndOfLine = false;
}
}
if (bIsEndOfLine)
{
if (aLineOn2S->NbPoints() > 1)
{
occ::handle<IntPatch_WLine> aNewWLine = new IntPatch_WLine(aLineOn2S, false);
aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
theNewLines.Append(aNewWLine);
}
aLineOn2S = new IntSurf_LineOn2S();
}
}
continue;
}
// end if(!bIsFirstInside && !bIsLastInside)
if (bIsFirstInside && bIsLastInside)
{
// append inside points between ifprm and ilprm
NCollection_List<int>::Iterator anIt(aListOfIndex);
for (; anIt.More(); anIt.Next())
{
pit = anIt.Value();
if ((pit < ifprm) || (pit > ilprm))
{
continue;
}
const IntSurf_PntOn2S& aP = theWLine->Point(pit);
aLineOn2S->Add(aP);
}
}
else
{
if (bIsFirstInside)
{
// append points from ifprm to last point + boundary point
NCollection_List<int>::Iterator anIt(aListOfIndex);
for (; anIt.More(); anIt.Next())
{
pit = anIt.Value();
if (pit < ifprm)
{
continue;
}
const IntSurf_PntOn2S& aP = theWLine->Point(pit);
aLineOn2S->Add(aP);
}
if (bhaslastpoint)
{
pit = aListOfFLIndex.Last();
const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
aLineOn2S->Add(aP);
}
// check end of split line (end is almost always)
int aneighbour = i + 1;
bool bIsEndOfLine = true;
if (aneighbour <= nblines)
{
const NCollection_List<int>& aListOfNeighbourIndex = anArrayOfLines.Value(aneighbour);
if ((anArrayOfLineType.Value(aneighbour) != 0) && (aListOfNeighbourIndex.IsEmpty()))
{
bIsEndOfLine = false;
}
}
if (bIsEndOfLine)
{
if (aLineOn2S->NbPoints() > 1)
{
occ::handle<IntPatch_WLine> aNewWLine = new IntPatch_WLine(aLineOn2S, false);
aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
theNewLines.Append(aNewWLine);
}
aLineOn2S = new IntSurf_LineOn2S();
}
}
// end if(bIsFirstInside)
if (bIsLastInside)
{
// append points from first boundary point to ilprm
if (bhasfirstpoint)
{
pit = aListOfFLIndex.First();
const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
aLineOn2S->Add(aP);
}
NCollection_List<int>::Iterator anIt(aListOfIndex);
for (; anIt.More(); anIt.Next())
{
pit = anIt.Value();
if (pit > ilprm)
{
continue;
}
const IntSurf_PntOn2S& aP = theWLine->Point(pit);
aLineOn2S->Add(aP);
}
}
// end if(bIsLastInside)
}
}
if (aLineOn2S->NbPoints() > 1)
{
occ::handle<IntPatch_WLine> aNewWLine = new IntPatch_WLine(aLineOn2S, false);
aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
theNewLines.Append(aNewWLine);
}
}
// Split wlines.end
return true;
}
///////////////////// end of DecompositionOfWLine ///////////////////////