1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/Approx/Approx_BSplComputeLine.gxx
oan 2956d432e2 0033560: PARASOLID Import - XT importer raises exception SIGFPE Arithmetic Exception
Prevent division by zero in exceptional cases when vector of parameters contains only a single value.
2024-03-28 13:58:36 +00:00

1440 lines
43 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.
#include <stdio.h>
#include <Approx_ParametrizationType.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <TColgp_Array1OfVec.hxx>
#include <TColgp_Array1OfVec2d.hxx>
#include <AppParCurves_Constraint.hxx>
#include <AppParCurves_HArray1OfConstraintCouple.hxx>
#include <AppParCurves_MultiPoint.hxx>
#include <Precision.hxx>
#include <math_IntegerVector.hxx>
#include <math_Gauss.hxx>
#include <math_Uzawa.hxx>
#include <AppParCurves_ConstraintCouple.hxx>
#include Approx_BSpParLeastSquareOfMyBSplGradient_hxx
#if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT )
static Standard_Boolean mydebug = Standard_False;
#include <Draw.hxx>
#include <Draw_Appli.hxx>
#include <DrawTrSurf.hxx>
#include <Draw_Text2D.hxx>
#include <Draw_Text3D.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom_Line.hxx>
#include <Geom2d_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
static void DUMP(const MultiLine& Line)
{
Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
firstP = LineTool::FirstPoint(Line);
lastP = LineTool::LastPoint(Line);
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
if (nbP3d == 0) mynbP3d = 1;
if (nbP2d == 0) mynbP2d = 1;
TColgp_Array1OfPnt tabP(1, mynbP3d);
TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
TColgp_Array1OfVec TabV(1, mynbP3d);
TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
Standard_Boolean Ok;
Handle(Geom_Line) L3d;
Handle(Geom2d_Line) L2d;
Handle(Geom_TrimmedCurve) L3dt;
Handle(Geom2d_TrimmedCurve) L2dt;
Handle(Draw_Text2D) T2D;
Handle(Draw_Text3D) T3D;
char solname[100];
char mytext[10];
for (i = firstP; i <= lastP; i++) {
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d);
else if (nbP2d != 0) LineTool::Value(Line, i, tabP2d);
else if (nbP3d != 0) LineTool::Value(Line, i, tabP);
for (j = 1; j <= nbP3d; j++) {
sprintf(solname, "%s%i%s_%i", "p", j, "3d", i);
char* Temp = solname;
DrawTrSurf::Set(Temp, tabP(j));
// DrawTrSurf::Set(solname, tabP(j));
if (i == firstP || i == lastP) {
sprintf(mytext, "%s%i", " ", i);
T3D = new Draw_Text3D(tabP(j), mytext, Draw_vert);
dout << T3D;
}
}
for (j = 1; j <= nbP2d; j++) {
sprintf(solname, "%s%i%s_%i", "p", j, "2d", i);
char* Temp = solname;
DrawTrSurf::Set(Temp, tabP2d(j));
// DrawTrSurf::Set(solname, tabP2d(j));
if (i == firstP || i == lastP) {
sprintf(mytext, "%s%i", " ", i);
T2D = new Draw_Text2D(tabP2d(j), mytext, Draw_vert);
dout << T2D;
}
}
// le cas des tangentes aux extremites:
if (i == firstP || i == lastP) {
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, i, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, i, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, i, TabV);
if (Ok) {
for (j = 1; j <= nbP3d; j++) {
sprintf(solname, "%s%i%s_%i", "t", j, "3d", i);
L3d = new Geom_Line(tabP(j), gp_Dir(TabV(j)));
L3dt = new Geom_TrimmedCurve(L3d, 0.0, 0.3);
char* Temp = solname;
DrawTrSurf::Set(Temp, L3dt);
// DrawTrSurf::Set(solname, L3dt);
}
for (j = 1; j <= nbP2d; j++) {
sprintf(solname, "%s%i%s_%i", "t", j, "2d", i);
L2d = new Geom2d_Line(tabP2d(j), gp_Dir2d(TabV2d(j)));
L2dt = new Geom2d_TrimmedCurve(L2d, 0.0, 0.3);
char* Temp = solname;
DrawTrSurf::Set(Temp, L2dt);
// DrawTrSurf::Set(solname, L2dt);
}
}
}
}
dout.Flush();
}
static void DUMP(const AppParCurves_MultiBSpCurve& C)
{
static Standard_Integer nbappel = 0;
Standard_Integer i, j, nbP2d, nbP3d;
Standard_Integer nbpoles = C.NbPoles();
Standard_Integer deg = C.Degree();
const TColStd_Array1OfReal& Knots = C.Knots();
const TColStd_Array1OfInteger& Mults = C.Multiplicities();
Handle(Geom_BSplineCurve) BSp;
Handle(Geom2d_BSplineCurve) BSp2d;
TColgp_Array1OfPnt tabPoles(1, nbpoles);
TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
char solname[100];
nbappel++;
for (i = 1; i <= C.NbCurves(); i++) {
if (C.Dimension(i) == 3) {
C.Curve(i, tabPoles);
BSp = new Geom_BSplineCurve(tabPoles, Knots, Mults, deg);
sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
char* Temp = solname;
DrawTrSurf::Set(Temp, BSp);
// DrawTrSurf::Set(solname, BSp);
}
else {
C.Curve(i, tabPoles2d);
BSp2d = new Geom2d_BSplineCurve(tabPoles2d, Knots, Mults, deg);
sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
char* Temp = solname;
DrawTrSurf::Set(Temp, BSp2d);
// DrawTrSurf::Set(solname, BSp2d);
}
}
dout.Flush();
}
#endif
//=======================================================================
//function : FirstTangencyVector
//purpose :
//=======================================================================
void Approx_BSplComputeLine::FirstTangencyVector(const MultiLine& Line,
const Standard_Integer index,
math_Vector& V)
const {
Standard_Integer i, j, nbP2d, nbP3d;
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
if (nbP3d == 0) mynbP3d = 1;
if (nbP2d == 0) mynbP2d = 1;
Standard_Boolean Ok = Standard_False;
TColgp_Array1OfVec TabV(1, mynbP3d);
TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, index, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, index, TabV);
if (Ok) {
if (nbP3d != 0) {
j = 1;
for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
V(j) = TabV(i).X();
V(j + 1) = TabV(i).Y();
V(j + 2) = TabV(i).Z();
j += 3;
}
}
if (nbP2d != 0) {
j = nbP3d * 3 + 1;
for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
V(j) = TabV2d(i).X();
V(j + 1) = TabV2d(i).Y();
j += 2;
}
}
}
else {
// recherche d un vecteur tangent par construction d une parabole:
AppParCurves_Constraint firstC, lastC;
firstC = lastC = AppParCurves_PassPoint;
Standard_Integer nbpoles = 3;
math_Vector mypar(index, index + 2);
Parameters(Line, index, index + 2, mypar);
Approx_BSpParLeastSquareOfMyBSplGradient
LSQ(Line, index, index + 2, firstC, lastC, mypar, nbpoles);
AppParCurves_MultiCurve C = LSQ.BezierValue();
gp_Pnt myP;
gp_Vec myV;
gp_Pnt2d myP2d;
gp_Vec2d myV2d;
j = 1;
for (i = 1; i <= nbP3d; i++) {
C.D1(i, 0.0, myP, myV);
V(j) = myV.X();
V(j + 1) = myV.Y();
V(j + 2) = myV.Z();
j += 3;
}
j = nbP3d * 3 + 1;
for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) {
C.D1(i, 0.0, myP2d, myV2d);
V(j) = myV2d.X();
V(j + 1) = myV2d.Y();
j += 2;
}
}
}
//=======================================================================
//function : LastTangencyVector
//purpose :
//=======================================================================
void Approx_BSplComputeLine::LastTangencyVector(const MultiLine& Line,
const Standard_Integer index,
math_Vector& V)
const {
Standard_Integer i, j, nbP2d, nbP3d;
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
if (nbP3d == 0) mynbP3d = 1;
if (nbP2d == 0) mynbP2d = 1;
Standard_Boolean Ok = Standard_False;
TColgp_Array1OfVec TabV(1, mynbP3d);
TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, index, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, index, TabV);
if (Ok) {
if (nbP3d != 0) {
j = 1;
for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
V(j) = TabV(i).X();
V(j + 1) = TabV(i).Y();
V(j + 2) = TabV(i).Z();
j += 3;
}
}
if (nbP2d != 0) {
j = nbP3d * 3 + 1;
for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
V(j) = TabV2d(i).X();
V(j + 1) = TabV2d(i).Y();
j += 2;
}
}
}
else {
// recherche d un vecteur tangent par construction d une parabole:
AppParCurves_Constraint firstC, lastC;
firstC = lastC = AppParCurves_PassPoint;
Standard_Integer nbpoles = 3;
math_Vector mypar(index - 2, index);
Parameters(Line, index - 2, index, mypar);
Approx_BSpParLeastSquareOfMyBSplGradient
LSQ(Line, index - 2, index, firstC, lastC, mypar, nbpoles);
AppParCurves_MultiCurve C = LSQ.BezierValue();
gp_Pnt myP;
gp_Vec myV;
gp_Pnt2d myP2d;
gp_Vec2d myV2d;
j = 1;
for (i = 1; i <= nbP3d; i++) {
C.D1(i, 1.0, myP, myV);
V(j) = myV.X();
V(j + 1) = myV.Y();
V(j + 2) = myV.Z();
j += 3;
}
j = nbP3d * 3 + 1;
for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) {
C.D1(i, 1.0, myP2d, myV2d);
V(j) = myV2d.X();
V(j + 1) = myV2d.Y();
j += 2;
}
}
}
//=======================================================================
//function : SearchFirstLambda
//purpose :
//=======================================================================
Standard_Real Approx_BSplComputeLine::
SearchFirstLambda(const MultiLine& Line,
const math_Vector& aPar,
const TColStd_Array1OfReal& Theknots,
const math_Vector& V,
const Standard_Integer index) const {
// dq/dw = lambda* V = (p2-p1)/(u2-u1)
Standard_Integer nbP2d, nbP3d;
gp_Pnt P1, P2;
gp_Pnt2d P12d, P22d;
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
if (nbP3d == 0) mynbP3d = 1;
if (nbP2d == 0) mynbP2d = 1;
TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
else if (nbP2d != 0) LineTool::Value(Line, index, tabP12d);
else if (nbP3d != 0) LineTool::Value(Line, index, tabP1);
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index + 1, tabP2, tabP22d);
else if (nbP2d != 0) LineTool::Value(Line, index + 1, tabP22d);
else if (nbP3d != 0) LineTool::Value(Line, index + 1, tabP2);
Standard_Real U1 = aPar(index), U2 = aPar(index + 1);
Standard_Real lambda, S;
Standard_Integer low = V.Lower();
Standard_Integer nbknots = Theknots.Length();
if (nbP3d != 0) {
P1 = tabP1(1);
P2 = tabP2(1);
gp_Vec P1P2(P1, P2), myV;
myV.SetCoord(V(low), V(low + 1), V(low + 2));
lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
}
else {
P12d = tabP12d(1);
P22d = tabP22d(1);
gp_Vec2d P1P2(P12d, P22d), myV;
myV.SetCoord(V(low), V(low + 1));
lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
}
return ((S*lambda)*(Theknots(2) - Theknots(1)) / (Theknots(nbknots) - Theknots(1)));
}
//=======================================================================
//function : SearchLastLambda
//purpose :
//=======================================================================
Standard_Real Approx_BSplComputeLine::
SearchLastLambda(const MultiLine& Line,
const math_Vector& aPar,
const TColStd_Array1OfReal& Theknots,
const math_Vector& V,
const Standard_Integer index) const
{
// dq/dw = lambda* V = (p2-p1)/(u2-u1)
Standard_Integer nbP2d, nbP3d;
gp_Pnt P1, P2;
gp_Pnt2d P12d, P22d;
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
if (nbP3d == 0) mynbP3d = 1;
if (nbP2d == 0) mynbP2d = 1;
TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index - 1, tabP, tabP2d);
else if (nbP2d != 0) LineTool::Value(Line, index - 1, tabP2d);
else if (nbP3d != 0) LineTool::Value(Line, index - 1, tabP);
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
else if (nbP2d != 0) LineTool::Value(Line, index, tabP22d);
else if (nbP3d != 0) LineTool::Value(Line, index, tabP2);
Standard_Real U1 = aPar(index - 1), U2 = aPar(index);
Standard_Real lambda, S;
Standard_Integer low = V.Lower();
Standard_Integer nbknots = Theknots.Length();
if (nbP3d != 0) {
P1 = tabP(1);
P2 = tabP2(1);
gp_Vec P1P2(P1, P2), myV;
myV.SetCoord(V(low), V(low + 1), V(low + 2));
lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
}
else {
P12d = tabP2d(1);
P22d = tabP22d(1);
gp_Vec2d P1P2(P12d, P22d), myV;
myV.SetCoord(V(low), V(low + 1));
lambda = (P1P2.Magnitude()) / (myV.Magnitude()*(U2 - U1));
S = (P1P2.Dot(myV) > 0.0) ? 1.0 : -1.0;
}
return ((S*lambda)*(Theknots(nbknots) - Theknots(nbknots - 1))
/ (Theknots(nbknots) - Theknots(1)));
}
//=======================================================================
//function : Approx_BSplComputeLine
//purpose :
//=======================================================================
Approx_BSplComputeLine::Approx_BSplComputeLine
(const MultiLine& Line,
const math_Vector& Parameters,
const Standard_Integer degreemin,
const Standard_Integer degreemax,
const Standard_Real Tolerance3d,
const Standard_Real Tolerance2d,
const Standard_Integer NbIterations,
const Standard_Boolean cutting,
const Standard_Boolean Squares)
{
myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
Parameters.Upper());
for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
myfirstParam->SetValue(i, Parameters(i));
}
myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
Par = Approx_IsoParametric;
myPeriodic = Standard_False;
mydegremin = degreemin;
mydegremax = degreemax;
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
mysquares = Squares;
mycut = cutting;
myitermax = NbIterations;
alldone = Standard_False;
mycont = -1;
myfirstC = AppParCurves_TangencyPoint;
mylastC = AppParCurves_TangencyPoint;
myhasknots = Standard_False;
myhasmults = Standard_False;
currenttol3d = currenttol2d = RealLast();
tolreached = Standard_False;
Perform(Line);
}
//=======================================================================
//function : Approx_BSplComputeLine
//purpose :
//=======================================================================
Approx_BSplComputeLine::Approx_BSplComputeLine
(const math_Vector& Parameters,
const Standard_Integer degreemin,
const Standard_Integer degreemax,
const Standard_Real Tolerance3d,
const Standard_Real Tolerance2d,
const Standard_Integer NbIterations,
const Standard_Boolean cutting,
const Standard_Boolean Squares)
{
myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
Parameters.Upper());
for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
myfirstParam->SetValue(i, Parameters(i));
}
myfirstC = AppParCurves_TangencyPoint;
mylastC = AppParCurves_TangencyPoint;
myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
Par = Approx_IsoParametric;
myPeriodic = Standard_False;
mydegremin = degreemin;
mydegremax = degreemax;
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
mysquares = Squares;
mycut = cutting;
myitermax = NbIterations;
alldone = Standard_False;
myhasknots = Standard_False;
myhasmults = Standard_False;
mycont = -1;
currenttol3d = currenttol2d = RealLast();
tolreached = Standard_False;
}
//=======================================================================
//function : Approx_BSplComputeLine
//purpose :
//=======================================================================
Approx_BSplComputeLine::Approx_BSplComputeLine
(const Standard_Integer degreemin,
const Standard_Integer degreemax,
const Standard_Real Tolerance3d,
const Standard_Real Tolerance2d,
const Standard_Integer NbIterations,
const Standard_Boolean cutting,
const Approx_ParametrizationType parametrization,
const Standard_Boolean Squares)
{
myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
Par = parametrization;
myPeriodic = Standard_False;
mydegremin = degreemin;
mydegremax = degreemax;
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
mysquares = Squares;
mycut = cutting;
myitermax = NbIterations;
myfirstC = AppParCurves_TangencyPoint;
mylastC = AppParCurves_TangencyPoint;
alldone = Standard_False;
myhasknots = Standard_False;
myhasmults = Standard_False;
mycont = -1;
currenttol3d = currenttol2d = RealLast();
tolreached = Standard_False;
}
//=======================================================================
//function : Approx_BSplComputeLine
//purpose :
//=======================================================================
Approx_BSplComputeLine::Approx_BSplComputeLine
(const MultiLine& Line,
const Standard_Integer degreemin,
const Standard_Integer degreemax,
const Standard_Real Tolerance3d,
const Standard_Real Tolerance2d,
const Standard_Integer NbIterations,
const Standard_Boolean cutting,
const Approx_ParametrizationType parametrization,
const Standard_Boolean Squares)
{
myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
alldone = Standard_False;
mydegremin = degreemin;
mydegremax = degreemax;
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
mysquares = Squares;
mycut = cutting;
myitermax = NbIterations;
Par = parametrization;
myPeriodic = Standard_False;
myfirstC = AppParCurves_TangencyPoint;
mylastC = AppParCurves_TangencyPoint;
myhasknots = Standard_False;
myhasmults = Standard_False;
mycont = -1;
currenttol3d = currenttol2d = RealLast();
tolreached = Standard_False;
Perform(Line);
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void Approx_BSplComputeLine::Perform(const MultiLine& Line)
{
#if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT )
if (mydebug) DUMP(Line);
#endif
Standard_Integer i, Thefirstpt, Thelastpt;
Standard_Boolean Finish = Standard_False, begin = Standard_True;
// recherche des vraies contraintes donnees par la Line:
FindRealConstraints(Line);
Thefirstpt = LineTool::FirstPoint(Line);
Thelastpt = LineTool::LastPoint(Line);
Standard_Integer myfirstpt = Thefirstpt;
Standard_Integer mylastpt = Thelastpt;
AppParCurves_ConstraintCouple myCouple1(myfirstpt, realfirstC);
AppParCurves_ConstraintCouple myCouple2(mylastpt, reallastC);
myConstraints->SetValue(1, myCouple1);
myConstraints->SetValue(2, myCouple2);
math_Vector TheParam(Thefirstpt, Thelastpt, 0.0);
if (myfirstParam.IsNull()) {
Parameters(Line, Thefirstpt, Thelastpt, TheParam);
}
else {
for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
TheParam(i + Thefirstpt - 1) = myfirstParam->Value(i);
}
}
myParameters = new TColStd_HArray1OfReal(TheParam.Lower(), TheParam.Upper());
for (i = TheParam.Lower(); i <= TheParam.Upper(); i++) {
myParameters->SetValue(i, TheParam(i));
}
Standard_Integer nbknots = 2;
Standard_Real l;
alldone = Standard_False;
if (!mycut) {
// cas ou on ne desire pas de noeuds supplementaires.
// ==================================================
if (!myhasknots) {
TColStd_Array1OfReal theknots(1, 2);
TColStd_Array1OfInteger themults(1, 2);
theknots(1) = 0.0;
theknots(2) = 1.0;
alldone = Compute(Line, myfirstpt, mylastpt, TheParam, theknots, themults);
}
else {
if (!myhasmults) {
TColStd_Array1OfInteger themults(1, myknots->Length());
alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
myknots->Array1(), themults);
}
else {
alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
myknots->Array1(), mymults->ChangeArray1());
}
}
}
else {
// cas ou on va iterer a partir de noeuds donnes par l''utilisateur
// ou a partir d''une bezier.
// ================================================================
while (!Finish) {
currenttol3d = currenttol2d = RealLast();
if (myhasknots && begin) {
if (!myhasmults) {
// 1er cas: l''utilisateur donne des noeuds de depart mais
// a nous de fixer les multiplicites en fonction de la
// continuite desiree.
// ========================================================
TColStd_Array1OfInteger TheMults(1, myknots->Length());
alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
myknots->Array1(), TheMults);
}
else {
// 2eme cas: l''utilisateur donne des noeuds de depart
// avec leurs multiplicites.
// ===================================================
alldone = Compute(Line, myfirstpt, mylastpt, TheParam,
myknots->Array1(), mymults->ChangeArray1());
}
begin = Standard_False;
}
else {
// 3eme cas: l''utilisateur ne donne aucun noeuds de depart
// ========================================================
TColStd_Array1OfReal Theknots(1, nbknots);
TColStd_Array1OfInteger TheMults(1, nbknots);
Theknots(1) = 0.0;
Theknots(nbknots) = 1.0;
for (i = 2; i <= nbknots - 1; i++) {
l = (mylastpt - myfirstpt)*Standard_Real(i - 1)
/ Standard_Real(nbknots - 1);
Standard_Integer ll = (Standard_Integer)(l);
Standard_Real a = l - ll;
Standard_Real p1 = TheParam(ll + myfirstpt);
Standard_Real p2 = TheParam(ll + 1 + myfirstpt);
Theknots(i) = (1. - a)*p1 + a*p2;
}
alldone = Compute(Line, myfirstpt, mylastpt, TheParam, Theknots, TheMults);
}
if (!alldone) nbknots++;
else Finish = Standard_True;
}
}
#if defined(OCCT_DEBUG) && defined( DRAW ) && !defined( WNT )
if (mydebug) DUMP(TheMultiBSpCurve);
#endif
}
//=======================================================================
//function : Parameters
//purpose :
//=======================================================================
const TColStd_Array1OfReal& Approx_BSplComputeLine::Parameters() const
{
return myParameters->Array1();
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
const AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::Value() const
{
return TheMultiBSpCurve;
}
//=======================================================================
//function : ChangeValue
//purpose :
//=======================================================================
AppParCurves_MultiBSpCurve& Approx_BSplComputeLine::ChangeValue()
{
return TheMultiBSpCurve;
}
//=======================================================================
//function : Parameters
//purpose :
//=======================================================================
void Approx_BSplComputeLine::Parameters(const MultiLine& Line,
const Standard_Integer firstP,
const Standard_Integer lastP,
math_Vector& TheParameters) const
{
Standard_Integer i, j, nbP2d, nbP3d;
Standard_Real dist;
const Standard_Integer aNbp = lastP - firstP + 1;
// The first parameter should always be zero according to all the logic below,
// so division by any value will give zero anyway, so it should never be scaled
// to avoid case when there is only one parameter in the array thus division by zero happens.
TheParameters(firstP) = 0.0;
if (aNbp == 2) {
TheParameters(lastP) = 1.0;
}
else if (Par == Approx_ChordLength || Par == Approx_Centripetal)
{
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
if (nbP3d == 0) mynbP3d = 1;
if (nbP2d == 0) mynbP2d = 1;
dist = 0.0;
TColgp_Array1OfPnt tabP(1, mynbP3d);
TColgp_Array1OfPnt tabPP(1, mynbP3d);
TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
for (i = firstP + 1; i <= lastP; i++)
{
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i - 1, tabP, tabP2d);
else if (nbP2d != 0) LineTool::Value(Line, i - 1, tabP2d);
else if (nbP3d != 0) LineTool::Value(Line, i - 1, tabP);
if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
else if (nbP2d != 0) LineTool::Value(Line, i, tabPP2d);
else if (nbP3d != 0) LineTool::Value(Line, i, tabPP);
dist = 0.0;
for (j = 1; j <= nbP3d; j++)
{
const gp_Pnt &aP1 = tabP(j),
&aP2 = tabPP(j);
dist += aP2.SquareDistance(aP1);
}
for (j = 1; j <= nbP2d; j++)
{
const gp_Pnt2d &aP12d = tabP2d(j),
&aP22d = tabPP2d(j);
dist += aP22d.SquareDistance(aP12d);
}
dist = Sqrt(dist);
if (Par == Approx_ChordLength)
{
TheParameters(i) = TheParameters(i - 1) + dist;
}
else
{// Par == Approx_Centripetal
TheParameters(i) = TheParameters(i - 1) + Sqrt(dist);
}
}
for (i = firstP + 1; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
}
else {
for (i = firstP + 1; i <= lastP; i++) {
TheParameters(i) = (Standard_Real(i) - firstP) /
(Standard_Real(lastP - Standard_Real(firstP)));
}
}
}
//=======================================================================
//function : Compute
//purpose :
//=======================================================================
Standard_Boolean Approx_BSplComputeLine::Compute(const MultiLine& Line,
const Standard_Integer fpt,
const Standard_Integer lpt,
math_Vector& Para,
const TColStd_Array1OfReal& Knots,
TColStd_Array1OfInteger& Mults)
{
Standard_Integer i, deg, nbpoles, multinter;
Standard_Boolean mydone;
Standard_Real Fv, TheTol3d, TheTol2d, l1, l2;
Standard_Integer nbp = lpt - fpt + 1;
mylambda1 = 0.0;
mylambda2 = 0.0;
math_Vector aParams(Para.Lower(), Para.Upper());
for (deg = mydegremin; deg <= mydegremax; deg++) {
aParams = Para;
if (!myhasmults) {
Mults(Mults.Lower()) = deg + 1;
Mults(Mults.Upper()) = deg + 1;
nbpoles = deg + 1;
if (mycont == -1) multinter = 1;
else multinter = Max(1, deg - mycont);
for (i = Mults.Lower() + 1; i <= Mults.Upper() - 1; i++) {
Mults(i) = multinter;
nbpoles += multinter;
}
}
else {
nbpoles = -deg - 1;
for (i = Mults.Lower(); i <= Mults.Upper(); i++) {
nbpoles += Mults.Value(i);
}
}
Standard_Integer nbpolestocompare = nbpoles;
if (realfirstC == AppParCurves_TangencyPoint) nbpolestocompare++;
if (reallastC == AppParCurves_TangencyPoint) nbpolestocompare++;
if (realfirstC == AppParCurves_CurvaturePoint) nbpolestocompare++;
if (reallastC == AppParCurves_CurvaturePoint) nbpolestocompare++;
if (nbpolestocompare > nbp) {
Interpol(Line);
tolreached = Standard_True;
return Standard_True;
}
AppParCurves_MultiBSpCurve mySCU(nbpoles);
if (mysquares) {
Approx_BSpParLeastSquareOfMyBSplGradient SQ(Line, Knots, Mults, fpt, lpt,
realfirstC, reallastC, aParams, nbpoles);
mydone = SQ.IsDone();
if (mydone) {
mySCU = SQ.BSplineValue();
SQ.Error(Fv, TheTol3d, TheTol2d);
}
else continue;
}
else {
if (nbpoles != deg + 1) {
if (deg == mydegremin && (realfirstC >= AppParCurves_TangencyPoint ||
reallastC >= AppParCurves_TangencyPoint)) {
Approx_BSpParLeastSquareOfMyBSplGradient
thefitt(Line, Knots, Mults, fpt, lpt, realfirstC, reallastC, aParams, nbpoles);
mylambda1 = thefitt.FirstLambda()*deg;
mylambda2 = thefitt.LastLambda()*deg;
}
l1 = mylambda1 / deg;
l2 = mylambda2 / deg;
Approx_MyBSplGradient GRAD(Line, fpt, lpt, myConstraints,
aParams, Knots, Mults, deg, mytol3d,
mytol2d, myitermax, l1, l2);
mydone = GRAD.IsDone();
if (mydone) {
mySCU = GRAD.Value();
TheTol3d = GRAD.MaxError3d();
TheTol2d = GRAD.MaxError2d();
}
else continue;
}
else {
Approx_MyGradientbis GRAD2(Line, fpt, lpt, myConstraints,
aParams, deg, mytol3d,
mytol2d, myitermax);
mydone = GRAD2.IsDone();
if (mydone) {
if (GRAD2.Value().NbCurves() == 0)
continue;
mySCU = AppParCurves_MultiBSpCurve(GRAD2.Value(), Knots, Mults);
TheTol3d = GRAD2.MaxError3d();
TheTol2d = GRAD2.MaxError2d();
}
else continue;
}
}
Standard_Boolean save = Standard_True;
for (i = aParams.Lower(); i <= aParams.Upper(); i++) {
if (aParams(i) <= -0.000001 || aParams(i) >= 1.000001) {
save = Standard_False;
break;
}
}
if (mydone) {
if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
// Stockage de la multicurve approximee.
tolreached = Standard_True;
TheMultiBSpCurve = mySCU;
currenttol3d = TheTol3d;
currenttol2d = TheTol2d;
if (save) {
for (i = aParams.Lower(); i <= aParams.Upper(); i++) {
myParameters->SetValue(i, aParams(i));
}
}
return Standard_True;
}
}
if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
TheMultiBSpCurve = mySCU;
currenttol3d = TheTol3d;
currenttol2d = TheTol2d;
if (save) {
for (i = aParams.Lower(); i <= aParams.Upper(); i++) {
myParameters->SetValue(i, aParams(i));
}
}
}
}
return Standard_False;
}
//=======================================================================
//function : SetParameters
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetParameters(const math_Vector& ThePar)
{
myfirstParam = new TColStd_HArray1OfReal(ThePar.Lower(),
ThePar.Upper());
for (Standard_Integer i = ThePar.Lower(); i <= ThePar.Upper(); i++) {
myfirstParam->SetValue(i, ThePar(i));
}
}
//=======================================================================
//function : SetKnots
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetKnots(const TColStd_Array1OfReal& Knots)
{
myhasknots = Standard_True;
myknots = new TColStd_HArray1OfReal(Knots.Lower(), Knots.Upper());
for (Standard_Integer i = Knots.Lower(); i <= Knots.Upper(); i++) {
myknots->SetValue(i, Knots(i));
}
}
//=======================================================================
//function : SetKnotsAndMultiplicities
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetKnotsAndMultiplicities
(const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults)
{
myhasknots = Standard_True;
myhasmults = Standard_True;
Standard_Integer i;
myknots = new TColStd_HArray1OfReal(Knots.Lower(), Knots.Upper());
for (i = Knots.Lower(); i <= Knots.Upper(); i++) {
myknots->SetValue(i, Knots(i));
}
mymults = new TColStd_HArray1OfInteger(Mults.Lower(), Mults.Upper());
for (i = Mults.Lower(); i <= Mults.Upper(); i++) {
mymults->SetValue(i, Mults(i));
}
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void Approx_BSplComputeLine::Init(const Standard_Integer degreemin,
const Standard_Integer degreemax,
const Standard_Real Tolerance3d,
const Standard_Real Tolerance2d,
const Standard_Integer NbIterations,
const Standard_Boolean cutting,
const Approx_ParametrizationType parametrization,
const Standard_Boolean Squares)
{
mydegremin = degreemin;
mydegremax = degreemax;
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
Par = parametrization;
mysquares = Squares;
mycut = cutting;
myitermax = NbIterations;
}
//=======================================================================
//function : SetDegrees
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetDegrees(const Standard_Integer degreemin,
const Standard_Integer degreemax)
{
mydegremin = degreemin;
mydegremax = degreemax;
}
//=======================================================================
//function : SetTolerances
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetTolerances(const Standard_Real Tolerance3d,
const Standard_Real Tolerance2d)
{
mytol3d = Tolerance3d;
mytol2d = Tolerance2d;
}
//=======================================================================
//function : SetConstraints
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
const AppParCurves_Constraint LastC)
{
myfirstC = FirstC;
mylastC = LastC;
}
//=======================================================================
//function : SetPeriodic
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetPeriodic(const Standard_Boolean thePeriodic)
{
myPeriodic = thePeriodic;
}
//=======================================================================
//function : IsAllApproximated
//purpose :
//=======================================================================
Standard_Boolean Approx_BSplComputeLine::IsAllApproximated() const
{
return alldone;
}
//=======================================================================
//function : IsToleranceReached
//purpose :
//=======================================================================
Standard_Boolean Approx_BSplComputeLine::IsToleranceReached() const
{
return tolreached;
}
//=======================================================================
//function : Error
//purpose :
//=======================================================================
void Approx_BSplComputeLine::Error(Standard_Real& tol3d,
Standard_Real& tol2d) const
{
tol3d = currenttol3d;
tol2d = currenttol2d;
}
//=======================================================================
//function : SetContinuity
//purpose :
//=======================================================================
void Approx_BSplComputeLine::SetContinuity(const Standard_Integer C)
{
mycont = C;
}
//=======================================================================
//function : FindRealConstraints
//purpose :
//=======================================================================
void Approx_BSplComputeLine::FindRealConstraints(const MultiLine& Line)
{
realfirstC = myfirstC;
reallastC = mylastC;
Standard_Integer nbP2d, nbP3d;
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
Standard_Boolean Ok = Standard_False;
TColgp_Array1OfVec TabV(1, Max(1, nbP3d));
TColgp_Array1OfVec2d TabV2d(1, Max(1, nbP2d));
Standard_Integer Thefirstpt = LineTool::FirstPoint(Line);
Standard_Integer Thelastpt = LineTool::LastPoint(Line);
if (myfirstC >= AppParCurves_TangencyPoint) {
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, Thefirstpt, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, Thefirstpt, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, Thefirstpt, TabV);
realfirstC = AppParCurves_PassPoint;
if (Ok) {
realfirstC = AppParCurves_TangencyPoint;
if (myfirstC == AppParCurves_CurvaturePoint) {
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, Thefirstpt, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, Thefirstpt, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, Thefirstpt, TabV);
if (Ok) {
realfirstC = AppParCurves_CurvaturePoint;
}
}
}
}
if (mylastC >= AppParCurves_TangencyPoint) {
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, Thelastpt, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, Thelastpt, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, Thelastpt, TabV);
reallastC = AppParCurves_PassPoint;
if (Ok) {
reallastC = AppParCurves_TangencyPoint;
if (mylastC == AppParCurves_CurvaturePoint) {
if (nbP3d != 0 && nbP2d != 0)
Ok = LineTool::Tangency(Line, Thelastpt, TabV, TabV2d);
else if (nbP2d != 0)
Ok = LineTool::Tangency(Line, Thelastpt, TabV2d);
else if (nbP3d != 0)
Ok = LineTool::Tangency(Line, Thelastpt, TabV);
if (Ok) {
reallastC = AppParCurves_CurvaturePoint;
}
}
}
}
}
//=======================================================================
//function : Interpol
//purpose :
//=======================================================================
void Approx_BSplComputeLine::Interpol(const MultiLine& Line)
{
Standard_Integer i, Thefirstpt, Thelastpt, deg = 3;
mycont = 2;
Thefirstpt = LineTool::FirstPoint(Line);
Thelastpt = LineTool::LastPoint(Line);
math_Vector TheParam(Thefirstpt, Thelastpt, 0.0);
//Par = Approx_ChordLength;
if (myfirstParam.IsNull()) {
Parameters(Line, Thefirstpt, Thelastpt, TheParam);
}
else {
for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
TheParam(i + Thefirstpt - 1) = myfirstParam->Value(i);
}
}
AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
Standard_Real lambda1, lambda2;
Standard_Real Fv;
// Recherche du nombre de noeuds.
Standard_Integer nbknots, nbpoles, nbpoints;
nbpoints = Thelastpt - Thefirstpt + 1;
if (nbpoints == 2) {
Cons = AppParCurves_NoConstraint;
Standard_Integer mydeg = 1;
Approx_BSpParLeastSquareOfMyBSplGradient
LSQ(Line, Thefirstpt, Thelastpt, Cons, Cons, TheParam, mydeg + 1);
alldone = LSQ.IsDone();
TColStd_Array1OfReal TheKnots(1, 2);
TColStd_Array1OfInteger TheMults(1, 2);
TheKnots(1) = TheParam(Thefirstpt); TheKnots(2) = TheParam(Thelastpt);
TheMults(1) = TheMults(2) = mydeg + 1;
TheMultiBSpCurve =
AppParCurves_MultiBSpCurve(LSQ.BezierValue(), TheKnots, TheMults);
LSQ.Error(Fv, currenttol3d, currenttol2d);
}
else {
nbpoles = nbpoints + 2;
nbknots = nbpoints;
// Resolution:
TColStd_Array1OfReal Theknots(1, nbknots);
Theknots(1) = TheParam(Thefirstpt);
Theknots(nbknots) = TheParam(Thelastpt);
TColStd_Array1OfInteger TheMults(1, nbknots);
TheMults(1) = deg + 1;
TheMults(nbknots) = deg + 1;
Standard_Integer low = TheParam.Lower();
for (i = 2; i <= nbknots - 1; i++) {
Theknots(i) = TheParam(i + low - 1);
TheMults(i) = 1;
}
Standard_Integer nbP = 3 * LineTool::NbP3d(Line) + 2 * LineTool::NbP2d(Line);
math_Vector V1(1, nbP), V2(1, nbP);
if (nbpoints == 3 || nbpoints == 4) {
FirstTangencyVector(Line, Thefirstpt, V1);
lambda1 = SearchFirstLambda(Line, TheParam, Theknots, V1, Thefirstpt);
LastTangencyVector(Line, Thelastpt, V2);
lambda2 = SearchLastLambda(Line, TheParam, Theknots, V2, Thelastpt);
lambda1 = lambda1 / deg;
lambda2 = lambda2 / deg;
}
else {
Standard_Integer nnpol, nnp = Min(nbpoints, 9);
nnpol = nnp;
Standard_Integer lastp = Min(Thelastpt, Thefirstpt + nnp - 1);
Standard_Real U;
Approx_BSpParLeastSquareOfMyBSplGradient
SQ1(Line, Thefirstpt, lastp, Cons, Cons, nnpol);
math_Vector P1(Thefirstpt, lastp);
for (i = Thefirstpt; i <= lastp; i++) P1(i) = TheParam(i);
SQ1.Perform(P1);
const AppParCurves_MultiCurve& C1 = SQ1.BezierValue();
U = 0.0;
TangencyVector(Line, C1, U, V1);
Standard_Integer firstp = Max(Thefirstpt, Thelastpt - nnp + 1);
if (firstp == Thefirstpt && lastp == Thelastpt) {
U = 1.0;
TangencyVector(Line, C1, U, V2);
}
else {
Approx_BSpParLeastSquareOfMyBSplGradient
SQ2(Line, firstp, Thelastpt, Cons, Cons, nnpol);
math_Vector P2(firstp, Thelastpt);
for (i = firstp; i <= Thelastpt; i++) P2(i) = TheParam(i);
SQ2.Perform(P2);
const AppParCurves_MultiCurve& C2 = SQ2.BezierValue();
U = 1.0;
TangencyVector(Line, C2, U, V2);
}
lambda1 = 1. / deg;
lambda1 = lambda1*(Theknots(2) - Theknots(1))
/ (Theknots(nbknots) - Theknots(1));
lambda2 = 1. / deg;
lambda2 = lambda2*(Theknots(nbknots) - Theknots(nbknots - 1))
/ (Theknots(nbknots) - Theknots(1));
}
if (myPeriodic)
{
V1 = 0.5 * (V1 + V2);
V2 = V1;
}
Approx_BSpParLeastSquareOfMyBSplGradient
SQ(Line, Theknots, TheMults, Thefirstpt, Thelastpt,
Cons, Cons, nbpoles);
SQ.Perform(TheParam, V1, V2, lambda1, lambda2);
alldone = SQ.IsDone();
TheMultiBSpCurve = SQ.BSplineValue();
SQ.Error(Fv, currenttol3d, currenttol2d);
tolreached = Standard_True;
}
myParameters = new TColStd_HArray1OfReal(TheParam.Lower(), TheParam.Upper());
for (i = TheParam.Lower(); i <= TheParam.Upper(); i++) {
myParameters->SetValue(i, TheParam(i));
}
}
//=======================================================================
//function : TangencyVector
//purpose :
//=======================================================================
void Approx_BSplComputeLine::TangencyVector(
const MultiLine& Line,
const AppParCurves_MultiCurve& C,
const Standard_Real U,
math_Vector& V) const
{
Standard_Integer i, j, nbP2d, nbP3d;
nbP3d = LineTool::NbP3d(Line);
nbP2d = LineTool::NbP2d(Line);
gp_Pnt myP;
gp_Vec myV;
gp_Pnt2d myP2d;
gp_Vec2d myV2d;
j = 1;
for (i = 1; i <= nbP3d; i++) {
C.D1(i, U, myP, myV);
V(j) = myV.X();
V(j + 1) = myV.Y();
V(j + 2) = myV.Z();
j += 3;
}
j = nbP3d * 3 + 1;
for (i = nbP3d + 1; i <= nbP3d + nbP2d; i++) {
C.D1(i, U, myP2d, myV2d);
V(j) = myV2d.X();
V(j + 1) = myV2d.Y();
j += 2;
}
}