Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1993-03-22
// Created by: Laurent BUCHARD
// Copyright (c) 1993-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 <NCollection_Array1.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec2d.hxx>
#include <gp_Vec.hxx>
#include <IntSurf_LineOn2S.hxx>
#include <Precision.hxx>
#include <math_Vector.hxx>
#ifdef DRAW
#include <DrawTrSurf.hxx>
#endif
//=================================================================================================
ApproxInt_MultiLine::ApproxInt_MultiLine()
{
PtrOnmySvSurfaces = NULL;
myLine = NULL;
indicemin = 0;
indicemax = 0;
nbp3d = 0;
nbp2d = 0;
myApproxU1V1 = false;
myApproxU2V2 = false;
p2donfirst = true;
Xo = 0.;
Yo = 0.;
Zo = 0.;
U1o = 0.;
V1o = 0.;
U2o = 0.;
V2o = 0.;
}
//=================================================================================================
ApproxInt_MultiLine::ApproxInt_MultiLine(const Handle_TheLine& line,
void* const svsurf,
const int NbP3d,
const int NbP2d,
const bool ApproxU1V1,
const bool ApproxU2V2,
const double xo,
const double yo,
const double zo,
const double u1o,
const double v1o,
const double u2o,
const double v2o,
const bool P2DOnFirst,
const int IndMin,
const int IndMax)
: PtrOnmySvSurfaces(svsurf),
myLine(line),
indicemin(std::min(IndMin, IndMax)),
indicemax(std::max(IndMin, IndMax)),
nbp3d(NbP3d),
nbp2d(NbP2d),
myApproxU1V1(ApproxU1V1),
myApproxU2V2(ApproxU2V2),
p2donfirst(P2DOnFirst),
Xo(xo),
Yo(yo),
Zo(zo),
U1o(u1o),
V1o(v1o),
U2o(u2o),
V2o(v2o)
{
#ifdef OCCT_DEBUG
// if(indicemin == indicemax)
//{
// cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
// }
#endif
}
//=================================================================================================
ApproxInt_MultiLine::ApproxInt_MultiLine(const Handle_TheLine& line,
const int NbP3d,
const int NbP2d,
const bool ApproxU1V1,
const bool ApproxU2V2,
const double xo,
const double yo,
const double zo,
const double u1o,
const double v1o,
const double u2o,
const double v2o,
const bool P2DOnFirst,
const int IndMin,
const int IndMax)
: PtrOnmySvSurfaces(nullptr),
myLine(line),
indicemin(std::min(IndMin, IndMax)),
indicemax(std::max(IndMin, IndMax)),
nbp3d(NbP3d),
nbp2d(NbP2d),
myApproxU1V1(ApproxU1V1),
myApproxU2V2(ApproxU2V2),
p2donfirst(P2DOnFirst),
Xo(xo),
Yo(yo),
Zo(zo),
U1o(u1o),
V1o(v1o),
U2o(u2o),
V2o(v2o)
{
#ifdef OCCT_DEBUG
// if(indicemin == indicemax)
//{
// cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
// }
#endif
}
//=================================================================================================
int ApproxInt_MultiLine::FirstPoint() const
{
return indicemin;
}
//=================================================================================================
int ApproxInt_MultiLine::LastPoint() const
{
return indicemax;
}
//=================================================================================================
Approx_Status ApproxInt_MultiLine::WhatStatus() const
{
if (PtrOnmySvSurfaces)
return Approx_PointsAdded;
else
return Approx_NoPointsAdded;
}
//=================================================================================================
int ApproxInt_MultiLine::NbP3d() const
{
return nbp3d;
}
//=================================================================================================
int ApproxInt_MultiLine::NbP2d() const
{
return nbp2d;
}
//=================================================================================================
void ApproxInt_MultiLine::Value(const int Index, NCollection_Array1<gp_Pnt>& TabPnt) const
{
const gp_Pnt aP = myLine->Point(Index).Value();
TabPnt(1).SetCoord(aP.X() + Xo, aP.Y() + Yo, aP.Z() + Zo);
}
//=================================================================================================
void ApproxInt_MultiLine::Value(const int Index, NCollection_Array1<gp_Pnt2d>& TabPnt2d) const
{
IntSurf_PntOn2S POn2S(myLine->Point(Index));
double u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
POn2S.Parameters(u1, v1, u2, v2);
if (nbp2d == 1)
{
if (p2donfirst)
{
TabPnt2d(1).SetCoord(u1 + U1o, v1 + V1o);
}
else
{
TabPnt2d(1).SetCoord(u2 + U2o, v2 + V2o);
}
}
else
{
TabPnt2d(1).SetCoord(u1 + U1o, v1 + V1o);
if (TabPnt2d.Length() >= 2)
{
TabPnt2d(2).SetCoord(u2 + U2o, v2 + V2o);
}
}
}
//=================================================================================================
void ApproxInt_MultiLine::Value(const int Index,
NCollection_Array1<gp_Pnt>& TabPnt,
NCollection_Array1<gp_Pnt2d>& TabPnt2d) const
{
Value(Index, TabPnt);
Value(Index, TabPnt2d);
}
//=================================================================================================
bool ApproxInt_MultiLine::Tangency(const int Index, NCollection_Array1<gp_Vec>& TabVec) const
{
if (PtrOnmySvSurfaces == NULL)
return false;
const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
double u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
POn2S.Parameters(u1, v1, u2, v2);
bool ret = ((TheSvSurfaces*)PtrOnmySvSurfaces)->Tangency(u1, v1, u2, v2, TabVec(1));
if (!ret)
{
TabVec(1).SetCoord(0.0, 0.0, 0.0);
}
return ret;
}
//=================================================================================================
bool ApproxInt_MultiLine::Tangency(const int Index, NCollection_Array1<gp_Vec2d>& TabVec2d) const
{
if (PtrOnmySvSurfaces == NULL)
return false;
const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
double u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
POn2S.Parameters(u1, v1, u2, v2);
bool ret = false;
if (nbp2d == 1)
{
if (p2donfirst)
{
ret = ((TheSvSurfaces*)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
}
else
{
ret = ((TheSvSurfaces*)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(1));
}
}
else
{
ret = ((TheSvSurfaces*)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
if (ret)
{
if (TabVec2d.Length() >= 2)
{
ret =
(ret
&& ((TheSvSurfaces*)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(2)));
}
}
}
if (!ret)
{
TabVec2d(1) = gp_Vec2d(0.0, 0.0);
if (TabVec2d.Length() >= 2)
{
TabVec2d(2) = gp_Vec2d(0.0, 0.0);
}
}
return ret;
}
//=================================================================================================
bool ApproxInt_MultiLine::Tangency(const int Index,
NCollection_Array1<gp_Vec>& TabVec,
NCollection_Array1<gp_Vec2d>& TabVec2d) const
{
return (Tangency(Index, TabVec) && Tangency(Index, TabVec2d));
}
//=================================================================================================
ApproxInt_MultiLine ApproxInt_MultiLine::MakeMLBetween(const int Low,
const int High,
const int aNbPntsToInsert) const
{
if (PtrOnmySvSurfaces == NULL)
{
//-- cout<<"\n Erreur dans : ApproxInt_MultiLine ApproxInt_MultiLine::MakeMLBetween "<<endl;
occ::handle<IntSurf_LineOn2S> vide1 = new IntSurf_LineOn2S();
occ::handle<TheLine> vide = new TheLine(vide1, false);
return (ApproxInt_MultiLine(vide,
NULL,
nbp3d,
nbp2d,
myApproxU1V1,
myApproxU2V2,
Xo,
Yo,
Zo,
U1o,
V1o,
U2o,
V2o,
p2donfirst,
1,
1));
//-- return(*this);
}
bool aSaveUseSolver = ((TheSvSurfaces*)PtrOnmySvSurfaces)->GetUseSolver();
if (!aSaveUseSolver)
{
((TheSvSurfaces*)PtrOnmySvSurfaces)->SetUseSolver(true);
}
int NbPntsToInsert = aNbPntsToInsert;
if (NbPntsToInsert < (High - Low))
NbPntsToInsert = (High - Low);
int NbPnts = NbPntsToInsert + High - Low + 1;
int NbPntsmin = High - Low;
NbPntsmin += NbPntsmin;
if (NbPnts < NbPntsmin)
NbPnts = NbPntsmin;
gp_Vec T;
gp_Vec2d TS1, TS2;
gp_Pnt P;
//-----------------------l-------------------------------------------
//-- Indice : Low Low+1 I I+1 High --
//-- --
//-- Abs.Curv. : S(Low) S(I) S(I+1) S(High) --
//-- --
//-- On echantillonne a abcisse curviligne --
//-- constante. --
//-- L abcisse est calculee sur les params U1,V1 --
//------------------------------------------------------------------
NCollection_Array1<double> U1(Low, High);
NCollection_Array1<double> V1(Low, High);
NCollection_Array1<double> U2(Low, High);
NCollection_Array1<double> V2(Low, High);
NCollection_Array1<double> AC(Low, High);
double s, ds;
//------------------------------------------------------------
//-- Creation des Tableaux U1 .. V2 et AC
//--
double u1, v1, u2, v2;
int i;
myLine->Point(Low).Parameters(u1, v1, u2, v2);
U1(Low) = u1;
V1(Low) = v1;
U2(Low) = u2;
V2(Low) = v2;
AC(Low) = 0.0;
#if 0
for( i=Low+1; i<=High; i++) {
myLine->Point(i).Parameters(u1,v1,u2,v2);
U1(i) = u1;
V1(i) = v1;
U2(i) = u2;
V2(i) = v2;
double du1=u1-U1(i-1);
double dv1=v1-V1(i-1);
AC(i) = AC(i-1) + sqrt((du1*du1)+(dv1*dv1));
}
#else
//-- Essai du 19 juin 96 (parametrage selon abs curv en XYZ)
for (i = Low + 1; i <= High; i++)
{
myLine->Point(i).Parameters(u1, v1, u2, v2);
U1(i) = u1;
V1(i) = v1;
U2(i) = u2;
V2(i) = v2;
AC(i) = AC(i - 1) + (myLine->Point(i - 1).Value()).Distance(myLine->Point(i).Value());
}
#endif
//-------------------------------------------------------------
//-- Creation des structures contenant les resultats
occ::handle<IntSurf_LineOn2S> ResultPntOn2SLine = new IntSurf_LineOn2S();
IntSurf_PntOn2S StartPOn2S;
NCollection_Array1<double> StartParams(1, 4);
ds = AC(High) / (NbPnts - 1);
int Indice = Low;
bool HasBeenInserted = false;
double dsmin = ds * 0.3;
double smax = AC(High);
for (i = 2, s = ds; (s < smax && Indice <= High - 1); i++, s += ds)
{
//----------------------------------------------------------
//-- Recherche des indices des points --
//-- Point : 2 i NbPnts-1 --
//-- s s --
//-- Current Indice tel que AC(Indice)<= s < AC(Indice+1) --
//----------------------------------------------------------
while (AC(Indice + 1) <= s)
{
if (!HasBeenInserted)
ResultPntOn2SLine->Add(myLine->Point(Indice));
HasBeenInserted = false;
Indice++;
if (Indice == High)
break;
}
if (Indice == High)
break;
if (!HasBeenInserted && AC(Indice) <= s)
{
ResultPntOn2SLine->Add(myLine->Point(Indice));
HasBeenInserted = true;
}
double a = s - AC(Indice);
double b = AC(Indice + 1) - s;
double nab = 1.0 / (a + b);
//----------------------------------------------------------
//-- Verification : Si Dist au prochain point < dsmin --
//-- Si Dist au precedent point < dsmin --
//-- --
//----------------------------------------------------------
if ((a > dsmin) && (b > dsmin))
{
u1 = (U1(Indice) * b + U1(Indice + 1) * a) * nab;
v1 = (V1(Indice) * b + V1(Indice + 1) * a) * nab;
u2 = (U2(Indice) * b + U2(Indice + 1) * a) * nab;
v2 = (V2(Indice) * b + V2(Indice + 1) * a) * nab;
if (((TheSvSurfaces*)PtrOnmySvSurfaces)->Compute(u1, v1, u2, v2, P, T, TS1, TS2))
{
StartPOn2S.SetValue(P, u1, v1, u2, v2);
//-- cout<<" Insertion du point calcule : "<<u1<<","<<v1<<","<<u2<<","<<v2<<",";
//-- cout<<P.X()<<","<<P.Y()<<","<<P.Z()<<endl;
ResultPntOn2SLine->Add(StartPOn2S);
}
else
{
//-- cout<<" Probleme Non Traite ds ApproxInt_ApproxIntIntersection "<<endl;
}
}
else
{
//-- Point non situe a distance suffisante de 2 pts existants
//-- avec le point p[indice] deja insere
if (b < 0.0)
{
while (AC(Indice + 1) <= s)
{
if (!HasBeenInserted)
ResultPntOn2SLine->Add(myLine->Point(Indice));
//-- cout<<" Insertion du point :"<<Indice<<endl;
HasBeenInserted = false;
Indice++;
if (Indice == High)
break;
}
if (Indice == High)
break;
if (!HasBeenInserted && AC(Indice) <= s)
{
ResultPntOn2SLine->Add(myLine->Point(Indice));
HasBeenInserted = true;
}
}
else
{
s += (dsmin - ds);
}
}
}
ResultPntOn2SLine->Add(myLine->Point(High)); //-- Point NbPnts
occ::handle<TheLine> temp = new TheLine(ResultPntOn2SLine, false);
//-- Verification a posteriori
//-- On verifie qu il n y a pas de virage trop important en 2d et en 3d
temp->Point(1).Parameters(u1, v1, u2, v2);
gp_Pnt2d P1A(u1, v1);
gp_Pnt2d P2A(u2, v2);
temp->Point(2).Parameters(u1, v1, u2, v2);
gp_Pnt2d P1B(u1, v1);
gp_Pnt2d P2B(u2, v2);
gp_Pnt2d P1C, P2C;
int CodeErreur = 0;
for (i = 3, NbPnts = temp->NbPnts(); CodeErreur == 0 && i <= NbPnts; i++)
{
double d, du, dv, duv2;
temp->Point(i).Parameters(u1, v1, u2, v2);
//-- Virage P1A P1B P1C
P1C.SetCoord(u1, v1);
du = P1B.X() - P1A.X();
dv = P1B.Y() - P1A.Y();
duv2 = 0.25 * (du * du + dv * dv);
u1 = P1B.X() + du;
v1 = P1B.Y() + dv;
du = P1C.X() - u1;
dv = P1C.Y() - v1;
d = du * du + dv * dv;
if (d > duv2)
{
CodeErreur = 1;
CodeErreur = 1;
break;
}
//-- Virage P2A P2B P2C
P2C.SetCoord(u2, v2);
du = P2B.X() - P2A.X();
dv = P2B.Y() - P2A.Y();
duv2 = 0.25 * (du * du + dv * dv);
u2 = P2B.X() + du;
v2 = P2B.Y() + dv;
du = P2C.X() - u2;
dv = P2C.Y() - v2;
d = du * du + dv * dv;
if (d > duv2)
{
CodeErreur = 2;
break;
}
P1A = P1B;
P2A = P2B;
P1B = P1C;
P2B = P2C;
}
#ifdef OCCT_DEBUG
// if (temp->NbPnts() < NbPntsToInsert + High - Low + 1)
//{
// cout<<" *** Pas assez de points entre :"<<
// Low<<" et "<<High<<" -> "<<temp->NbPnts()<<endl;
// }
// if(CodeErreur)
//{
// cout<<" *** CodeErreur : "<<CodeErreur<<endl;
// }
#endif
if ((temp->NbPnts() >= NbPntsToInsert + High - Low + 1) && (CodeErreur == 0))
{
((TheSvSurfaces*)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
return (ApproxInt_MultiLine(temp,
(High - Low > 10) ? PtrOnmySvSurfaces : NULL,
nbp3d,
nbp2d,
myApproxU1V1,
myApproxU2V2,
Xo,
Yo,
Zo,
U1o,
V1o,
U2o,
V2o,
p2donfirst,
1,
ResultPntOn2SLine->NbPoints()));
}
else
{
//-- cout<<" ApproxInt_MultiLine "<<endl;
//-- cout<<" Pas de Rajout de points ds1min = "<<minds1<<" ds2min = "<<minds2<<endl;
((TheSvSurfaces*)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
occ::handle<IntSurf_LineOn2S> vide1 = new IntSurf_LineOn2S();
occ::handle<TheLine> vide = new TheLine(vide1, false);
return (ApproxInt_MultiLine(vide,
NULL,
nbp3d,
nbp2d,
myApproxU1V1,
myApproxU2V2,
Xo,
Yo,
Zo,
U1o,
V1o,
U2o,
V2o,
p2donfirst,
1,
1));
}
}
//=================================================================================================
bool ApproxInt_MultiLine::MakeMLOneMorePoint(const int theLow,
const int theHigh,
const int theIndbad,
ApproxInt_MultiLine& theNewMultiLine) const
{
bool OtherLineMade = false;
if (PtrOnmySvSurfaces == NULL)
return false;
bool aSaveUseSolver = ((TheSvSurfaces*)PtrOnmySvSurfaces)->GetUseSolver();
if (!aSaveUseSolver)
{
((TheSvSurfaces*)PtrOnmySvSurfaces)->SetUseSolver(true);
}
constexpr double SqTol3d = Precision::SquareConfusion();
math_Vector tolerance(1, 2);
tolerance(1) = tolerance(2) = 1.e-8;
occ::handle<IntSurf_LineOn2S> ResultPntOn2SLine = new IntSurf_LineOn2S();
for (int Indice = theLow; Indice <= theHigh; Indice++)
ResultPntOn2SLine->Add(myLine->Point(Indice));
// Insert new point between (theIndbad-1) and theIndbad
// Using <thePtrSVSurf> for Rsnld: it may be ImpPrm or PrmPrm
gp_Pnt PrevPnt = myLine->Point(theIndbad - 1).Value();
gp_Pnt CurPnt = myLine->Point(theIndbad).Value();
double uprev1, vprev1, uprev2, vprev2, ucur1, vcur1, ucur2, vcur2;
myLine->Point(theIndbad - 1).Parameters(uprev1, vprev1, uprev2, vprev2);
myLine->Point(theIndbad).Parameters(ucur1, vcur1, ucur2, vcur2);
double umid1, vmid1, umid2, vmid2;
umid1 = (uprev1 + ucur1) / 2;
vmid1 = (vprev1 + vcur1) / 2;
umid2 = (uprev2 + ucur2) / 2;
vmid2 = (vprev2 + vcur2) / 2;
IntSurf_PntOn2S MidPoint;
bool IsNewPointInvalid = false;
IsNewPointInvalid = myApproxU1V1 && std::abs(ucur1 - umid1) <= tolerance(1)
&& std::abs(vcur1 - vmid1) <= tolerance(2);
if (!IsNewPointInvalid)
{
IsNewPointInvalid = myApproxU2V2 && std::abs(ucur2 - umid2) <= tolerance(1)
&& std::abs(vcur2 - vmid2) <= tolerance(2);
if (!IsNewPointInvalid
&& ((TheSvSurfaces*)PtrOnmySvSurfaces)->SeekPoint(umid1, vmid1, umid2, vmid2, MidPoint))
{
const gp_Pnt& NewPnt = MidPoint.Value();
double SqDistNewPrev = NewPnt.SquareDistance(PrevPnt);
double SqDistNewCur = NewPnt.SquareDistance(CurPnt);
IsNewPointInvalid = (SqDistNewPrev <= SqTol3d || SqDistNewCur <= SqTol3d);
if (!IsNewPointInvalid)
{
double unew1, vnew1, unew2, vnew2;
MidPoint.Parameters(unew1, vnew1, unew2, vnew2);
if (myApproxU1V1)
{
double SqDistCurMid1 =
(ucur1 - umid1) * (ucur1 - umid1) + (vcur1 - vmid1) * (vcur1 - vmid1);
double SqDistMidNew1 =
(umid1 - unew1) * (umid1 - unew1) + (vmid1 - vnew1) * (vmid1 - vnew1);
IsNewPointInvalid = (SqDistMidNew1 > SqDistCurMid1);
}
if (!IsNewPointInvalid)
{
if (myApproxU2V2)
{
double SqDistCurMid2 =
(ucur2 - umid2) * (ucur2 - umid2) + (vcur2 - vmid2) * (vcur2 - vmid2);
double SqDistMidNew2 =
(umid2 - unew2) * (umid2 - unew2) + (vmid2 - vnew2) * (vmid2 - vnew2);
IsNewPointInvalid = (SqDistMidNew2 > SqDistCurMid2);
}
if (!IsNewPointInvalid)
{
ResultPntOn2SLine->InsertBefore(theIndbad - theLow + 1, MidPoint);
OtherLineMade = true;
}
}
}
}
}
if (!OtherLineMade)
{
((TheSvSurfaces*)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
return false;
}
#ifdef DRAW
char* name = new char[100];
int indc = 1;
bool onfirst = true;
for (int i = 1; i <= ResultPntOn2SLine->NbPoints(); i++)
{
const IntSurf_PntOn2S& thePoint = ResultPntOn2SLine->Value(i);
gp_Pnt curPnt = thePoint.Value();
Sprintf(name, "p%d_%d", indc, i);
DrawTrSurf::Set(name, curPnt);
gp_Pnt2d curPnt2d = thePoint.ValueOnSurface(onfirst);
Sprintf(name, "pp%d_%d", indc, i);
DrawTrSurf::Set(name, curPnt2d);
}
#endif
occ::handle<TheLine> temp = new TheLine(ResultPntOn2SLine, false);
((TheSvSurfaces*)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
theNewMultiLine = ApproxInt_MultiLine(temp,
PtrOnmySvSurfaces,
nbp3d,
nbp2d,
myApproxU1V1,
myApproxU2V2,
Xo,
Yo,
Zo,
U1o,
V1o,
U2o,
V2o,
p2donfirst,
1,
ResultPntOn2SLine->NbPoints());
return true;
}
//=================================================================================================
void ApproxInt_MultiLine::Dump() const
{
NCollection_Array1<gp_Pnt> anArr1(1, 1);
NCollection_Array1<gp_Pnt2d> anArr2(1, 2);
const int anIndF = FirstPoint(), anIndL = LastPoint();
for (int ind = anIndF; ind <= anIndL; ind++)
{
Value(ind, anArr1, anArr2);
printf("%4d [%+10.20f %+10.20f %+10.20f] "
"[%+10.20f %+10.20f] [%+10.20f %+10.20f]\n",
ind,
anArr1(1).X(),
anArr1(1).Y(),
anArr1(1).Z(),
anArr2(1).X(),
anArr2(1).Y(),
anArr2(2).X(),
anArr2(2).Y());
}
}