1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00
occt/src/IntWalk/IntWalk_IWalking_6.gxx
ifv 9a640cbe72 0030703: Modeling Algorithms - Intersector returns overlapping curves
IntPatch/IntPatch_ImpPrmIntersection.cxx - calculation of step depending on resolution of surface

IntWalk_IWalking_6.gxx - calculation of point-line coincidence is improved

Correction of tests according to current results

lowalgos/intss/bug30703 - new test case added
2020-11-28 12:36:05 +03:00

273 lines
8.0 KiB
Plaintext

// 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.
#ifndef OCCT_DEBUG
#define No_Standard_RangeError
#define No_Standard_OutOfRange
#endif
void IntWalk_IWalking::AddPointInCurrentLine
(const Standard_Integer N,
const ThePointOfPath& PathPnt,
const Handle(IntWalk_TheIWLine)& CurrentLine) const {
IntSurf_PntOn2S Psol;
Psol.SetValue(ThePointOfPathTool::Value3d(PathPnt),
reversed,wd1[N].ustart,wd1[N].vstart);
CurrentLine->AddPoint(Psol);
}
void IntWalk_IWalking::MakeWalkingPoint
(const Standard_Integer Case,
const Standard_Real U,
const Standard_Real V,
TheIWFunction& sp,
IntSurf_PntOn2S& Psol )
{
// Case == 1 : make a WalkinkPoint.
// Case == 2 : make a WalkinkPoint.
// The computation of the tangency on is done
// Case == 10 + i : make a WalkinkPoint according to i.
// but F is updated according to U and V
// Case == other : the exception Standard_Failure is raised.
if ((Case == 1) || (Case == 2))
{
Psol.SetValue(sp.Point(), reversed, U, V);
}
else if (Case == 11 || Case == 12)
{
Standard_Real aUV[2], aFF[1], aDD[1][2];
math_Vector UV(aUV, 1, 2);
math_Vector FF(aFF, 1, 1);
math_Matrix DD(aDD, 1, 1, 1, 2);
UV(1) = U;
UV(2) = V;
sp.Values(UV, FF, DD);
MakeWalkingPoint(Case - 10, U, V, sp, Psol);
}
else
{
throw Standard_ConstructionError();
}
}
void IntWalk_IWalking::OpenLine(const Standard_Integer N,
const IntSurf_PntOn2S& Psol,
const ThePOPIterator& Pnts1,
TheIWFunction& sp,
const Handle(IntWalk_TheIWLine)& Line )
// **************** open the line and restart in the other direction********
{
ThePointOfPath PathPnt;
Standard_Real aUV[2], aFF[1], aDD[1][2];
math_Vector UV(aUV,1, 2);
math_Vector FF(aFF,1, 1);
math_Matrix DD(aDD,1, 1, 1, 2);
previousPoint = Line->Value(1);
if (!reversed) {
previousPoint.ParametersOnS2(UV(1),UV(2));
}
else {
previousPoint.ParametersOnS1(UV(1),UV(2));
}
sp.Values(UV, FF, DD);
previousd3d = sp.Direction3d();
previousd2d = sp.Direction2d();
if (N>0) { //departure point given at input
PathPnt = Pnts1.Value(N);
//mark the line as open with a given stop point
Line->AddStatusFirst(Standard_False,Standard_True,N,PathPnt);
AddPointInCurrentLine(N,PathPnt,Line);
}
else {
if (N <0) Line->AddPoint(Psol);
Line->AddStatusFirst(Standard_False,Standard_False);
//mark the line as open without given stop point
}
Line->Reverse(); //inverser la ligne
Line->SetTangentVector(previousd3d.Reversed(),Line->NbPoints());
}
Standard_Boolean IntWalk_IWalking::IsValidEndPoint(const Standard_Integer IndOfPoint,
const Standard_Integer IndOfLine)
{
if (PointLineLine.IsEmpty())
return Standard_True;
TColStd_ListIteratorOfListOfInteger itl(PointLineLine(IndOfPoint));
for (; itl.More(); itl.Next())
if (itl.Value() == IndOfLine)
{
PointLineLine(IndOfPoint).Remove(itl);
return Standard_True;
}
return Standard_False;
}
void IntWalk_IWalking::RemoveTwoEndPoints(const Standard_Integer IndOfPoint)
{
if (PointLineLine.IsBound(IndOfPoint))
{
Standard_Integer Line1 = PointLineLine(IndOfPoint).First();
Standard_Integer Line2 = PointLineLine(IndOfPoint).Last();
for (Standard_Integer iseq = 1; iseq <= seqAlone.Length(); iseq++)
{
if (seqAlone(iseq) == Line1 ||
seqAlone(iseq) == Line2)
seqAlone.Remove(iseq--);
}
}
}
Standard_Boolean IntWalk_IWalking::IsPointOnLine(const gp_Pnt2d& theP2d,
const Standard_Integer Irang)
{
const Handle(IntWalk_TheIWLine)& aLine = lines.Value(Abs(Irang));
for (Standard_Integer i = 1; i <= aLine->NbPoints(); i++)
{
gp_Pnt2d P2d1 = aLine->Value(i).ValueOnSurface(reversed);
if (Abs(P2d1.X() - theP2d.X()) <= tolerance(1) &&
Abs(P2d1.Y() - theP2d.Y()) <= tolerance(2))
return Standard_True;
if (i < aLine->NbPoints())
{
gp_Pnt2d P2d2 = aLine->Value(i+1).ValueOnSurface(reversed);
gp_Vec2d PP1(theP2d, P2d1);
gp_Vec2d PP2(theP2d, P2d2);
if (PP1 * PP2 < 0)
return Standard_True;
}
}
return Standard_False;
}
//==================================================================================
//function : IsPointOnLine
//purpose : Projects thePOn2S on the nearest segment of the already computed line.
// The retrieved projection point (aPa) is refined using theSolver.
// After the refinement, we will obtain a point aPb.
// If thePOn2S is quite far from aPb then thePOn2S is not
// in the line.
// Every already computed line is checked.
//==================================================================================
Standard_Boolean IntWalk_IWalking::IsPointOnLine(const IntSurf_PntOn2S& thePOn2S,
const math_Vector& theInfBounds,
const math_Vector& theSupBounds,
math_FunctionSetRoot& theSolver,
TheIWFunction& theFunc)
{
const Standard_Real eps = Epsilon(1.);
const gp_Pnt &aP3d = thePOn2S.Value();
for (Standard_Integer aLIdx = 1; aLIdx <= lines.Length(); aLIdx++)
{
const Handle(IntSurf_LineOn2S) &aL = lines(aLIdx)->Line();
if (aL->IsOutBox(aP3d))
continue;
//Look for the nearest segment
Standard_Real aUMin = 0.0, aVMin = 0.0;
Standard_Real aMinSqDist = RealLast();
for (Standard_Integer aPtIdx = 1; aPtIdx < aL->NbPoints(); aPtIdx++)
{
const gp_Pnt &aP1 = aL->Value(aPtIdx).Value();
const gp_Pnt &aP2 = aL->Value(aPtIdx + 1).Value();
const gp_XYZ aP1P(aP3d.XYZ() - aP1.XYZ());
const gp_XYZ aP1P2(aP2.XYZ() - aP1.XYZ());
const Standard_Real aSq12 = aP1P2.SquareModulus();
if (aSq12 < gp::Resolution())
continue;
const Standard_Real aDP = aP1P.Dot(aP1P2);
Standard_Real aSqD = RealLast();
if (aDP < 0.0)
{
continue;
}
else if (aDP > aSq12)
{
continue;
}
else
{
aSqD = aP1P.CrossSquareMagnitude(aP1P2) / aSq12;
}
if (aSqD < aMinSqDist)
{
aMinSqDist = aSqD;
const Standard_Real aL1 = aDP / aSq12;
const Standard_Real aL2 = 1.0 - aL1;
if (aL1 < eps || aL2 < eps)
{
return Standard_True;
}
Standard_Real aU1, aV1, aU2, aV2;
aL->Value(aPtIdx).ParametersOnSurface(reversed, aU1, aV1);
aL->Value(aPtIdx + 1).ParametersOnSurface(reversed, aU2, aV2);
aUMin = aL1*aU2 + aL2*aU1;
aVMin = aL1*aV2 + aL2*aV1;
}
}
if (aMinSqDist > Precision::Infinite())
continue;
math_Vector aVecPrms(1, 2);
aVecPrms(1) = aUMin;
aVecPrms(2) = aVMin;
theSolver.Perform(theFunc, aVecPrms, theInfBounds, theSupBounds);
if (!theSolver.IsDone())
continue;
theSolver.Root(aVecPrms);
const gp_Pnt aPa(theFunc.PSurface()->Value(aUMin, aVMin)),
aPb(theFunc.PSurface()->Value(aVecPrms(1), aVecPrms(2)));
const Standard_Real aSqD1 = aPb.SquareDistance(aP3d);
const Standard_Real aSqD2 = aPa.SquareDistance(aPb);
if (aSqD1 < 4.0*aSqD2)
{
return Standard_True;
}
}
return Standard_False;
}