mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
Now, the algorithm tries to estimate U- and V-ranges of future intersection curve(s) on the surface. This information is used in stop-criterium of the algorithm instead of full surface range used earlier. It allows reducing dependencies of intersection result on the surface ranges. Tuning of test case bugs/modalg_6/bug27937_1
358 lines
11 KiB
Plaintext
358 lines
11 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.
|
|
|
|
#ifdef CHRONO
|
|
#include <OSD_Chronometer.hxx>
|
|
OSD_Chronometer Chronrsnld;
|
|
|
|
#endif
|
|
|
|
#include <NCollection_IncAllocator.hxx>
|
|
#include <Precision.hxx>
|
|
|
|
//==================================================================================
|
|
// function : IsTangentExtCheck
|
|
// purpose : Additional check if the point (theU, theV) in parametric surface
|
|
// is a tangent point.
|
|
// If that is TRUE then we can go along any (!) direction in order to
|
|
// obtain next intersection point. At present, this case is difficult
|
|
// for processing. Therefore, we will return an empty intersection line
|
|
// in this case.
|
|
//==================================================================================
|
|
static Standard_Boolean IsTangentExtCheck(TheIWFunction& theFunc,
|
|
const Standard_Real theU,
|
|
const Standard_Real theV,
|
|
const Standard_Real theStepU,
|
|
const Standard_Real theStepV,
|
|
const Standard_Real theUinf,
|
|
const Standard_Real theUsup,
|
|
const Standard_Real theVinf,
|
|
const Standard_Real theVsup)
|
|
{
|
|
const Standard_Real aTol = theFunc.Tolerance();
|
|
const Standard_Integer aNbItems = 4;
|
|
const Standard_Real aParU[aNbItems] = { Min(theU + theStepU, theUsup),
|
|
Max(theU - theStepU, theUinf),
|
|
theU, theU};
|
|
const Standard_Real aParV[aNbItems] = { theV, theV,
|
|
Min(theV + theStepV, theVsup),
|
|
Max(theV - theStepV, theVinf)};
|
|
|
|
math_Vector aX(1, 2), aVal(1, 1);
|
|
|
|
for(Standard_Integer i = 0; i < aNbItems; i++)
|
|
{
|
|
aX.Value(1) = aParU[i];
|
|
aX.Value(2) = aParV[i];
|
|
|
|
if(!theFunc.Value(aX, aVal))
|
|
continue;
|
|
|
|
if(aVal(1) > aTol)
|
|
return Standard_False;
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
|
|
|
|
IntWalk_IWalking::IntWalk_IWalking (const Standard_Real Epsilon,
|
|
const Standard_Real Deflection,
|
|
const Standard_Real Increment,
|
|
const Standard_Boolean theToFillHoles) :
|
|
done(Standard_False),
|
|
fleche(Deflection),
|
|
pas(Increment),
|
|
tolerance(1,2),
|
|
epsilon(Epsilon*Epsilon),
|
|
wd1 (IntWalk_VectorOfWalkingData::allocator_type (new NCollection_IncAllocator)),
|
|
wd2 (wd1.get_allocator()),
|
|
nbMultiplicities (wd1.get_allocator()),
|
|
ToFillHoles(theToFillHoles)
|
|
{
|
|
}
|
|
|
|
|
|
//=======================================================================
|
|
//function : Reset
|
|
//purpose : Clears NCollection_Vector-based containers and adds
|
|
// dummy data to maintain start index of 1 and consistent with
|
|
// previous TCollection_Sequence-based implementation and other
|
|
// used TCollection-based containers
|
|
//=======================================================================
|
|
|
|
void IntWalk_IWalking::Clear()
|
|
{
|
|
wd1.clear();
|
|
wd2.clear();
|
|
IntWalk_WalkingData aDummy;
|
|
aDummy.etat = -10;
|
|
aDummy.ustart = aDummy.vstart = 0.;
|
|
wd1.push_back (aDummy);
|
|
wd2.push_back (aDummy);
|
|
nbMultiplicities.clear();
|
|
nbMultiplicities.push_back (-1);
|
|
|
|
done = Standard_False;
|
|
seqAjout.Clear();
|
|
lines.Clear();
|
|
}
|
|
|
|
// ***************************************************************************
|
|
// etat1=12 not tangent, not passes
|
|
// etat1=11 tangent, not passes
|
|
// etat1=2 not tangent, passes
|
|
// etat1=1 tangent, passes
|
|
// after a point is processed its state becomes negative.
|
|
// ***************************************************************************
|
|
// etat2=13 interior start point on closed line
|
|
// etat2=12 interior start point on open line
|
|
// (line initially closed -> la line s is open)
|
|
// after a point is processed (or if it is passed over during
|
|
// routing) its state becomes negative.
|
|
// ****************************************************************************
|
|
|
|
//
|
|
// Perform with interior points
|
|
//
|
|
void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
|
|
const ThePOLIterator& Pnts2,
|
|
TheIWFunction& Func,
|
|
const ThePSurface& Caro,
|
|
const Standard_Boolean Reversed)
|
|
|
|
{
|
|
Standard_Integer I;
|
|
Standard_Boolean Rajout = Standard_False;
|
|
Standard_Integer nbPnts1 = Pnts1.Length();
|
|
Standard_Integer nbPnts2 = Pnts2.Length();
|
|
Standard_Real U,V;
|
|
|
|
Clear();
|
|
reversed = Reversed;
|
|
|
|
Um = ThePSurfaceTool::FirstUParameter(Caro);
|
|
Vm = ThePSurfaceTool::FirstVParameter(Caro);
|
|
UM = ThePSurfaceTool::LastUParameter(Caro);
|
|
VM = ThePSurfaceTool::LastVParameter(Caro);
|
|
|
|
if (UM < Um) {
|
|
Standard_Real utemp = UM;
|
|
UM = Um;
|
|
Um = utemp;
|
|
}
|
|
if (VM < Vm) {
|
|
Standard_Real vtemp = VM;
|
|
VM = Vm;
|
|
Vm = vtemp;
|
|
}
|
|
|
|
const Standard_Real aStepU = pas*(UM-Um), aStepV = pas*(VM-Vm);
|
|
|
|
// Loading of etat1 and etat2 as well as ustart and vstart.
|
|
|
|
TColStd_SequenceOfReal Umult;
|
|
TColStd_SequenceOfReal Vmult;
|
|
|
|
Standard_Integer decal=0;
|
|
wd1.reserve (nbPnts1+decal);
|
|
nbMultiplicities.reserve (nbPnts1+decal);
|
|
for (I=1;I <= nbPnts1+decal; I++) {
|
|
const ThePointOfPath& PathPnt = Pnts1.Value(I-decal);
|
|
IntWalk_WalkingData aWD1;
|
|
aWD1.etat = 1;
|
|
if (!ThePointOfPathTool::IsPassingPnt(PathPnt))
|
|
aWD1.etat = 11;
|
|
if (!ThePointOfPathTool::IsTangent(PathPnt))
|
|
++aWD1.etat;
|
|
|
|
if(aWD1.etat==2) {
|
|
aWD1.etat=11;
|
|
}
|
|
|
|
ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
|
|
mySRangeU.Add(aWD1.ustart);
|
|
mySRangeV.Add(aWD1.vstart);
|
|
|
|
wd1.push_back (aWD1);
|
|
Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
|
|
nbMultiplicities.push_back(aNbMult);
|
|
|
|
for (Standard_Integer J = 1; J <= aNbMult; J++) {
|
|
ThePointOfPathTool::Parameters(PathPnt, J, U, V);
|
|
Umult.Append(U);
|
|
Vmult.Append(V);
|
|
}
|
|
}
|
|
|
|
wd2.reserve (nbPnts2);
|
|
for (I = 1; I <= nbPnts2; I++) {
|
|
IntWalk_WalkingData aWD2;
|
|
aWD2.etat = 1;
|
|
const IntSurf_InteriorPoint& anIP = Pnts2.Value(I);
|
|
ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
|
|
mySRangeU.Add(aWD2.ustart);
|
|
mySRangeV.Add(aWD2.vstart);
|
|
|
|
if (!IsTangentExtCheck(Func, aWD2.ustart, aWD2.vstart, aStepU, aStepV, Um, UM, Vm, VM))
|
|
aWD2.etat = 13;
|
|
|
|
wd2.push_back (aWD2);
|
|
}
|
|
|
|
tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
|
|
tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
|
|
|
|
Func.Set(Caro);
|
|
|
|
if (mySRangeU.Delta() > Max(tolerance(1), Precision::PConfusion()))
|
|
{
|
|
mySRangeU.Enlarge(mySRangeU.Delta());
|
|
mySRangeU.Common(Bnd_Range(Um, UM));
|
|
}
|
|
else
|
|
{
|
|
mySRangeU = Bnd_Range(Um, UM);
|
|
}
|
|
|
|
if (mySRangeV.Delta() > Max(tolerance(2), Precision::PConfusion()))
|
|
{
|
|
mySRangeV.Enlarge(mySRangeV.Delta());
|
|
mySRangeV.Common(Bnd_Range(Vm, VM));
|
|
}
|
|
else
|
|
{
|
|
mySRangeV = Bnd_Range(Vm, VM);
|
|
}
|
|
|
|
// calculation of all open lines
|
|
if (nbPnts1 != 0)
|
|
ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout);
|
|
|
|
// calculation of all closed lines
|
|
if (nbPnts2 != 0)
|
|
ComputeCloseLine(Umult,Vmult,Pnts1,Pnts2,Func,Rajout);
|
|
|
|
if (ToFillHoles)
|
|
{
|
|
Standard_Integer MaxNbIter = 10, nb_iter = 0;
|
|
while (seqAlone.Length() > 1 && nb_iter < MaxNbIter)
|
|
{
|
|
nb_iter++;
|
|
IntSurf_SequenceOfInteriorPoint PntsInHoles;
|
|
TColStd_SequenceOfInteger CopySeqAlone = seqAlone;
|
|
FillPntsInHoles(Func, CopySeqAlone, PntsInHoles);
|
|
wd2.clear();
|
|
IntWalk_WalkingData aDummy;
|
|
aDummy.etat = -10;
|
|
aDummy.ustart = aDummy.vstart = 0.;
|
|
wd2.push_back (aDummy);
|
|
Standard_Integer nbHoles = PntsInHoles.Length();
|
|
wd2.reserve(nbHoles);
|
|
for (I = 1; I <= nbHoles; I++)
|
|
{
|
|
IntWalk_WalkingData aWD2;
|
|
aWD2.etat = 13;
|
|
const IntSurf_InteriorPoint& anIP = PntsInHoles.Value(I);
|
|
ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
|
|
wd2.push_back (aWD2);
|
|
}
|
|
ComputeCloseLine(Umult,Vmult,Pnts1,PntsInHoles,Func,Rajout);
|
|
}
|
|
}
|
|
|
|
for (I = 1; I <= nbPnts1; I++) {
|
|
if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
|
|
}
|
|
done = Standard_True;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Perform without interior point
|
|
//
|
|
|
|
void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
|
|
TheIWFunction& Func,
|
|
const ThePSurface& Caro,
|
|
const Standard_Boolean Reversed)
|
|
|
|
{
|
|
Standard_Integer I;
|
|
Standard_Boolean Rajout = Standard_False;
|
|
Standard_Integer nbPnts1 = Pnts1.Length();
|
|
Standard_Real U,V;
|
|
|
|
reversed = Reversed;
|
|
|
|
|
|
// Loading of etat1 as well as ustart1 and vstart1.
|
|
|
|
TColStd_SequenceOfReal Umult;
|
|
TColStd_SequenceOfReal Vmult;
|
|
|
|
wd1.reserve (nbPnts1);
|
|
for (I=1;I <= nbPnts1; I++) {
|
|
const ThePointOfPath& PathPnt = Pnts1.Value(I);
|
|
IntWalk_WalkingData aWD1;
|
|
aWD1.etat = 1;
|
|
if (!ThePointOfPathTool::IsPassingPnt(PathPnt)) aWD1.etat = 11;
|
|
if (!ThePointOfPathTool::IsTangent(PathPnt)) ++aWD1.etat;
|
|
ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
|
|
wd1.push_back (aWD1);
|
|
Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
|
|
nbMultiplicities.push_back(aNbMult);
|
|
|
|
for (Standard_Integer J = 1; J <= aNbMult; J++) {
|
|
ThePointOfPathTool::Parameters(PathPnt, J, U, V);
|
|
Umult.Append(U);
|
|
Vmult.Append(V);
|
|
}
|
|
}
|
|
|
|
tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
|
|
tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
|
|
|
|
Um = ThePSurfaceTool::FirstUParameter(Caro);
|
|
Vm = ThePSurfaceTool::FirstVParameter(Caro);
|
|
UM = ThePSurfaceTool::LastUParameter(Caro);
|
|
VM = ThePSurfaceTool::LastVParameter(Caro);
|
|
|
|
if (UM < Um) {
|
|
Standard_Real utemp = UM;
|
|
UM = Um;
|
|
Um = utemp;
|
|
}
|
|
if (VM < Vm) {
|
|
Standard_Real vtemp = VM;
|
|
VM = Vm;
|
|
Vm = vtemp;
|
|
}
|
|
|
|
Func.Set(Caro);
|
|
|
|
// calcul de toutes les lignes ouvertes
|
|
if (nbPnts1 != 0) ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout);
|
|
|
|
for (I = 1; I <= nbPnts1; I++) {
|
|
if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
|
|
}
|
|
done = Standard_True;
|
|
}
|
|
|
|
|
|
|