1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-30 12:14:08 +03:00
occt/src/AppDef/AppDef_Variational.cxx
dpasukhi a5a7b3185b Coding - Apply .clang-format formatting #286
Update empty method guards to new style with regex (see PR).
Used clang-format 18.1.8.
New actions to validate code formatting is added.
Update .clang-format with disabling of include sorting.
  It is temporary changes, then include will be sorted.
Apply formatting for /src and /tools folder.
The files with .hxx,.cxx,.lxx,.h,.pxx,.hpp,*.cpp extensions.
2025-01-26 00:43:57 +00:00

3294 lines
98 KiB
C++

// Copyright (c) 1996-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.
// Jeannine PANCIATICI le 06/06/96
// Igor FEOKTISTOV 14/12/98 - correction of Approximate() and Init().
// Approximation d une MultiLine de points decrite par le tool MLineTool.
// avec criteres variationnels
#include <AppDef_MultiLine.hxx>
#include <AppDef_Variational.hxx>
#include <AppParCurves_MultiBSpCurve.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_DomainError.hxx>
#define No_Standard_RangeError
#define No_Standard_OutOfRange
#define No_Standard_DimensionError
#define No_Standard_ConstructionError
#include <Standard_Stream.hxx>
#include <AppParCurves.hxx>
#include <AppParCurves_Constraint.hxx>
#include <AppParCurves_HArray1OfConstraintCouple.hxx>
#include <AppParCurves_Array1OfMultiPoint.hxx>
#include <AppParCurves_MultiPoint.hxx>
#include <AppDef_LinearCriteria.hxx>
#include <Convert_CompPolynomialToPoles.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColgp_Array1OfVec.hxx>
#include <TColgp_Array1OfVec2d.hxx>
#include <TColStd_HArray1OfInteger.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColStd_HArray2OfReal.hxx>
#include <StdFail_NotDone.hxx>
#include <Precision.hxx>
#include <AppDef_MyLineTool.hxx>
#include <TColStd_HArray2OfInteger.hxx>
#include <TColStd_Array2OfReal.hxx>
#include <FEmTool_Assembly.hxx>
#include <FEmTool_Curve.hxx>
#include <math_Vector.hxx>
#include <PLib_HermitJacobi.hxx>
#include <FEmTool_HAssemblyTable.hxx>
// Add this line:
#include <algorithm>
#if defined(_MSC_VER)
#include <stdio.h>
#endif /* _MSC_VER */
//
//=======================================================================
// function : AppDef_Variational
// purpose : Initialization of the fields.
//=======================================================================
//
AppDef_Variational::AppDef_Variational(
const AppDef_MultiLine& SSP,
const Standard_Integer FirstPoint,
const Standard_Integer LastPoint,
const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
const Standard_Integer MaxDegree,
const Standard_Integer MaxSegment,
const GeomAbs_Shape Continuity,
const Standard_Boolean WithMinMax,
const Standard_Boolean WithCutting,
const Standard_Real Tolerance,
const Standard_Integer NbIterations)
: mySSP(SSP),
myFirstPoint(FirstPoint),
myLastPoint(LastPoint),
myConstraints(TheConstraints),
myMaxDegree(MaxDegree),
myMaxSegment(MaxSegment),
myNbIterations(NbIterations),
myTolerance(Tolerance),
myContinuity(Continuity),
myWithMinMax(WithMinMax),
myWithCutting(WithCutting)
{
// Verifications:
if (myMaxDegree < 1)
throw Standard_DomainError();
myMaxDegree = Min(30, myMaxDegree);
//
if (myMaxSegment < 1)
throw Standard_DomainError();
//
if (myWithMinMax != 0 && myWithMinMax != 1)
throw Standard_DomainError();
if (myWithCutting != 0 && myWithCutting != 1)
throw Standard_DomainError();
//
myIsOverConstr = Standard_False;
myIsCreated = Standard_False;
myIsDone = Standard_False;
switch (myContinuity)
{
case GeomAbs_C0:
myNivCont = 0;
break;
case GeomAbs_C1:
myNivCont = 1;
break;
case GeomAbs_C2:
myNivCont = 2;
break;
default:
throw Standard_ConstructionError();
}
//
myNbP2d = AppDef_MyLineTool::NbP2d(SSP);
myNbP3d = AppDef_MyLineTool::NbP3d(SSP);
myDimension = 2 * myNbP2d + 3 * myNbP3d;
//
myPercent[0] = 0.4;
myPercent[1] = 0.2;
myPercent[2] = 0.4;
myKnots = new TColStd_HArray1OfReal(1, 2);
myKnots->SetValue(1, 0.);
myKnots->SetValue(2, 1.);
// Declaration
//
mySmoothCriterion = new AppDef_LinearCriteria(mySSP, myFirstPoint, myLastPoint);
myParameters = new TColStd_HArray1OfReal(myFirstPoint, myLastPoint);
myNbPoints = myLastPoint - myFirstPoint + 1;
if (myNbPoints <= 0)
throw Standard_ConstructionError();
//
myTabPoints = new TColStd_HArray1OfReal(1, myDimension * myNbPoints);
//
// Table of Points initialization
//
Standard_Integer ipoint, jp2d, jp3d, index;
TColgp_Array1OfPnt TabP3d(1, Max(1, myNbP3d));
TColgp_Array1OfPnt2d TabP2d(1, Max(1, myNbP2d));
gp_Pnt2d P2d;
gp_Pnt P3d;
index = 1;
for (ipoint = myFirstPoint; ipoint <= myLastPoint; ipoint++)
{
if (myNbP2d != 0 && myNbP3d == 0)
{
AppDef_MyLineTool::Value(mySSP, ipoint, TabP2d);
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
P2d = TabP2d.Value(jp2d);
myTabPoints->SetValue(index++, P2d.X());
myTabPoints->SetValue(index++, P2d.Y());
}
}
if (myNbP3d != 0 && myNbP2d == 0)
{
AppDef_MyLineTool::Value(mySSP, ipoint, TabP3d);
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
P3d = TabP3d.Value(jp3d);
myTabPoints->SetValue(index++, P3d.X());
myTabPoints->SetValue(index++, P3d.Y());
myTabPoints->SetValue(index++, P3d.Z());
}
}
if (myNbP3d != 0 && myNbP2d != 0)
{
AppDef_MyLineTool::Value(mySSP, ipoint, TabP3d, TabP2d);
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
P3d = TabP3d.Value(jp3d);
myTabPoints->SetValue(index++, P3d.X());
myTabPoints->SetValue(index++, P3d.Y());
myTabPoints->SetValue(index++, P3d.Z());
}
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
P2d = TabP2d.Value(jp2d);
myTabPoints->SetValue(index++, P2d.X());
myTabPoints->SetValue(index++, P2d.Y());
}
}
}
Init();
}
//
//=======================================================================
// function : Init
// purpose : Initializes the tables of constraints
// and verifies if the problem is not over-constrained.
// This method is used in the Create and the method SetConstraint.
//=======================================================================
//
void AppDef_Variational::Init()
{
Standard_Integer ipoint, jp2d, jp3d, index, jndex;
Standard_Integer CurMultyPoint;
TColgp_Array1OfVec TabV3d(1, Max(1, myNbP3d));
TColgp_Array1OfVec2d TabV2d(1, Max(1, myNbP2d));
TColgp_Array1OfVec TabV3dcurv(1, Max(1, myNbP3d));
TColgp_Array1OfVec2d TabV2dcurv(1, Max(1, myNbP2d));
gp_Vec Vt3d, Vc3d;
gp_Vec2d Vt2d, Vc2d;
myNbConstraints = myConstraints->Length();
if (myNbConstraints < 0)
throw Standard_ConstructionError();
myTypConstraints = new TColStd_HArray1OfInteger(1, Max(1, 2 * myNbConstraints));
myTabConstraints = new TColStd_HArray1OfReal(1, Max(1, 2 * myDimension * myNbConstraints));
myTtheta = new TColStd_HArray1OfReal(1, Max(1, (2 * myNbP2d + 6 * myNbP3d) * myNbConstraints));
myTfthet = new TColStd_HArray1OfReal(1, Max(1, (2 * myNbP2d + 6 * myNbP3d) * myNbConstraints));
//
// Table of types initialization
Standard_Integer iconstr;
index = 1;
jndex = 1;
CurMultyPoint = 1;
myNbPassPoints = 0;
myNbTangPoints = 0;
myNbCurvPoints = 0;
AppParCurves_Constraint valcontr;
for (iconstr = myConstraints->Lower(); iconstr <= myConstraints->Upper(); iconstr++)
{
ipoint = (myConstraints->Value(iconstr)).Index();
valcontr = (myConstraints->Value(iconstr)).Constraint();
switch (valcontr)
{
case AppParCurves_NoConstraint:
CurMultyPoint -= myNbP3d * 6 + myNbP2d * 2;
break;
case AppParCurves_PassPoint:
myTypConstraints->SetValue(index++, ipoint);
myTypConstraints->SetValue(index++, 0);
myNbPassPoints++;
if (myNbP2d != 0)
jndex = jndex + 4 * myNbP2d;
if (myNbP3d != 0)
jndex = jndex + 6 * myNbP3d;
break;
case AppParCurves_TangencyPoint:
myTypConstraints->SetValue(index++, ipoint);
myTypConstraints->SetValue(index++, 1);
myNbTangPoints++;
if (myNbP2d != 0 && myNbP3d == 0)
{
if (AppDef_MyLineTool::Tangency(mySSP, ipoint, TabV2d) == Standard_False)
throw Standard_ConstructionError();
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
Vt2d = TabV2d.Value(jp2d);
Vt2d.Normalize();
myTabConstraints->SetValue(jndex++, Vt2d.X());
myTabConstraints->SetValue(jndex++, Vt2d.Y());
jndex = jndex + 2;
InitTthetaF(2, valcontr, CurMultyPoint + (jp2d - 1) * 2, jndex - 4);
}
}
if (myNbP3d != 0 && myNbP2d == 0)
{
if (AppDef_MyLineTool::Tangency(mySSP, ipoint, TabV3d) == Standard_False)
throw Standard_ConstructionError();
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
Vt3d = TabV3d.Value(jp3d);
Vt3d.Normalize();
myTabConstraints->SetValue(jndex++, Vt3d.X());
myTabConstraints->SetValue(jndex++, Vt3d.Y());
myTabConstraints->SetValue(jndex++, Vt3d.Z());
jndex = jndex + 3;
InitTthetaF(3, valcontr, CurMultyPoint + (jp3d - 1) * 6, jndex - 6);
}
}
if (myNbP3d != 0 && myNbP2d != 0)
{
if (AppDef_MyLineTool::Tangency(mySSP, ipoint, TabV3d, TabV2d) == Standard_False)
throw Standard_ConstructionError();
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
Vt3d = TabV3d.Value(jp3d);
Vt3d.Normalize();
myTabConstraints->SetValue(jndex++, Vt3d.X());
myTabConstraints->SetValue(jndex++, Vt3d.Y());
myTabConstraints->SetValue(jndex++, Vt3d.Z());
jndex = jndex + 3;
InitTthetaF(3, valcontr, CurMultyPoint + (jp3d - 1) * 6, jndex - 6);
}
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
Vt2d = TabV2d.Value(jp2d);
Vt2d.Normalize();
myTabConstraints->SetValue(jndex++, Vt2d.X());
myTabConstraints->SetValue(jndex++, Vt2d.Y());
jndex = jndex + 2;
InitTthetaF(2, valcontr, CurMultyPoint + (jp2d - 1) * 2 + myNbP3d * 6, jndex - 4);
}
}
break;
case AppParCurves_CurvaturePoint:
myTypConstraints->SetValue(index++, ipoint);
myTypConstraints->SetValue(index++, 2);
myNbCurvPoints++;
if (myNbP2d != 0 && myNbP3d == 0)
{
if (AppDef_MyLineTool::Tangency(mySSP, ipoint, TabV2d) == Standard_False)
throw Standard_ConstructionError();
if (AppDef_MyLineTool::Curvature(mySSP, ipoint, TabV2dcurv) == Standard_False)
throw Standard_ConstructionError();
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
Vt2d = TabV2d.Value(jp2d);
Vt2d.Normalize();
Vc2d = TabV2dcurv.Value(jp2d);
if (Abs(Abs(Vc2d.Angle(Vt2d)) - M_PI / 2.) > Precision::Angular())
throw Standard_ConstructionError();
myTabConstraints->SetValue(jndex++, Vt2d.X());
myTabConstraints->SetValue(jndex++, Vt2d.Y());
myTabConstraints->SetValue(jndex++, Vc2d.X());
myTabConstraints->SetValue(jndex++, Vc2d.Y());
InitTthetaF(2, valcontr, CurMultyPoint + (jp2d - 1) * 2, jndex - 4);
}
}
if (myNbP3d != 0 && myNbP2d == 0)
{
if (AppDef_MyLineTool::Tangency(mySSP, ipoint, TabV3d) == Standard_False)
throw Standard_ConstructionError();
if (AppDef_MyLineTool::Curvature(mySSP, ipoint, TabV3dcurv) == Standard_False)
throw Standard_ConstructionError();
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
Vt3d = TabV3d.Value(jp3d);
Vt3d.Normalize();
Vc3d = TabV3dcurv.Value(jp3d);
if ((Vc3d.Normalized()).IsNormal(Vt3d, Precision::Angular()) == Standard_False)
throw Standard_ConstructionError();
myTabConstraints->SetValue(jndex++, Vt3d.X());
myTabConstraints->SetValue(jndex++, Vt3d.Y());
myTabConstraints->SetValue(jndex++, Vt3d.Z());
myTabConstraints->SetValue(jndex++, Vc3d.X());
myTabConstraints->SetValue(jndex++, Vc3d.Y());
myTabConstraints->SetValue(jndex++, Vc3d.Z());
InitTthetaF(3, valcontr, CurMultyPoint + (jp3d - 1) * 6, jndex - 6);
}
}
if (myNbP3d != 0 && myNbP2d != 0)
{
if (AppDef_MyLineTool::Tangency(mySSP, ipoint, TabV3d, TabV2d) == Standard_False)
throw Standard_ConstructionError();
if (AppDef_MyLineTool::Curvature(mySSP, ipoint, TabV3dcurv, TabV2dcurv) == Standard_False)
throw Standard_ConstructionError();
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
Vt3d = TabV3d.Value(jp3d);
Vt3d.Normalize();
Vc3d = TabV3dcurv.Value(jp3d);
if ((Vc3d.Normalized()).IsNormal(Vt3d, Precision::Angular()) == Standard_False)
throw Standard_ConstructionError();
myTabConstraints->SetValue(jndex++, Vt3d.X());
myTabConstraints->SetValue(jndex++, Vt3d.Y());
myTabConstraints->SetValue(jndex++, Vt3d.Z());
myTabConstraints->SetValue(jndex++, Vc3d.X());
myTabConstraints->SetValue(jndex++, Vc3d.Y());
myTabConstraints->SetValue(jndex++, Vc3d.Z());
InitTthetaF(3, valcontr, CurMultyPoint + (jp3d - 1) * 6, jndex - 6);
}
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
Vt2d = TabV2d.Value(jp2d);
Vt2d.Normalize();
Vc2d = TabV2dcurv.Value(jp2d);
if (Abs(Abs(Vc2d.Angle(Vt2d)) - M_PI / 2.) > Precision::Angular())
throw Standard_ConstructionError();
myTabConstraints->SetValue(jndex++, Vt2d.X());
myTabConstraints->SetValue(jndex++, Vt2d.Y());
myTabConstraints->SetValue(jndex++, Vc2d.X());
myTabConstraints->SetValue(jndex++, Vc2d.Y());
InitTthetaF(2, valcontr, CurMultyPoint + (jp2d - 1) * 2 + myNbP3d * 6, jndex - 4);
}
}
break;
default:
throw Standard_ConstructionError();
}
CurMultyPoint += myNbP3d * 6 + myNbP2d * 2;
}
// OverConstraint Detection
Standard_Integer MaxSeg;
if (myWithCutting == Standard_True)
MaxSeg = myMaxSegment;
else
MaxSeg = 1;
if (((myMaxDegree - myNivCont) * MaxSeg - myNbPassPoints - 2 * myNbTangPoints
- 3 * myNbCurvPoints)
< 0)
{
myIsOverConstr = Standard_True;
myIsCreated = Standard_False;
}
else
{
InitSmoothCriterion();
myIsCreated = Standard_True;
}
}
//
//=======================================================================
// function : Approximate
// purpose : Makes the approximation with the current fields.
//=======================================================================
//
void AppDef_Variational::Approximate()
{
if (myIsCreated == Standard_False)
throw StdFail_NotDone();
Standard_Real WQuadratic, WQuality;
TColStd_Array1OfReal Ecarts(myFirstPoint, myLastPoint);
mySmoothCriterion->GetWeight(WQuadratic, WQuality);
Handle(FEmTool_Curve) TheCurve;
mySmoothCriterion->GetCurve(TheCurve);
//---------------------------------------------------------------------
TheMotor(mySmoothCriterion, WQuadratic, WQuality, TheCurve, Ecarts);
if (myWithMinMax && myTolerance < myMaxError)
Adjusting(mySmoothCriterion, WQuadratic, WQuality, TheCurve, Ecarts);
//---------------------------------------------------------------------
Standard_Integer jp2d, jp3d, ipole, NbElem = TheCurve->NbElements();
TColgp_Array1OfPnt TabP3d(1, Max(1, myNbP3d));
TColgp_Array1OfPnt2d TabP2d(1, Max(1, myNbP2d));
Standard_Real debfin[2] = {-1., 1};
gp_Pnt2d P2d;
gp_Pnt P3d;
{
Handle(TColStd_HArray2OfReal) PolynomialIntervalsPtr =
new TColStd_HArray2OfReal(1, NbElem, 1, 2);
Handle(TColStd_HArray1OfInteger) NbCoeffPtr = new TColStd_HArray1OfInteger(1, myMaxSegment);
Standard_Integer size = myMaxSegment * (myMaxDegree + 1) * myDimension;
Handle(TColStd_HArray1OfReal) CoeffPtr = new TColStd_HArray1OfReal(1, size);
CoeffPtr->Init(0.);
Handle(TColStd_HArray1OfReal) IntervallesPtr = new TColStd_HArray1OfReal(1, NbElem + 1);
IntervallesPtr->ChangeArray1() = TheCurve->Knots();
TheCurve->GetPolynom(CoeffPtr->ChangeArray1());
Standard_Integer ii;
for (ii = 1; ii <= NbElem; ii++)
NbCoeffPtr->SetValue(ii, TheCurve->Degree(ii) + 1);
for (ii = PolynomialIntervalsPtr->LowerRow(); ii <= PolynomialIntervalsPtr->UpperRow(); ii++)
{
PolynomialIntervalsPtr->SetValue(ii, 1, debfin[0]);
PolynomialIntervalsPtr->SetValue(ii, 2, debfin[1]);
}
/*
printf("\n =========== Parameters for converting\n");
printf("nb_courbes : %d \n", NbElem);
printf("tab_option[4] : %d \n", myNivCont);
printf("myDimension : %d \n", myDimension);
printf("myMaxDegree : %d \n", myMaxDegree);
printf("\n NbcoeffPtr :\n");
for(ii = 1; ii <= NbElem; ii++) printf("NbCoeffPtr(%d) = %d \n", ii, NbCoeffPtr->Value(ii));
size = NbElem*(myMaxDegree + 1) * myDimension;
printf("\n CoeffPtr :\n");
for(ii = 1; ii <= size; ii++) printf("CoeffPtr(%d) = %.8e \n", ii, CoeffPtr->Value(ii));
printf("\n PolinimialIntervalsPtr :\n");
for (ii = PolynomialIntervalsPtr->LowerRow() ;
ii <= PolynomialIntervalsPtr->UpperRow() ;ii++)
{
printf(" %d : [%f, %f] \n", ii, PolynomialIntervalsPtr->Value(ii,1),
PolynomialIntervalsPtr->Value(ii,2)) ;
}
printf("\n IntervallesPtr :\n");
for (ii = IntervallesPtr->Lower();
ii <= IntervallesPtr->Upper() - 1; ii++)
{
printf(" %d : [%f, %f] \n", ii, IntervallesPtr->Value(ii),
IntervallesPtr->Value(ii+1)) ;
}
*/
Convert_CompPolynomialToPoles AConverter(NbElem,
myNivCont,
myDimension,
myMaxDegree,
NbCoeffPtr,
CoeffPtr,
PolynomialIntervalsPtr,
IntervallesPtr);
if (AConverter.IsDone())
{
Handle(TColStd_HArray2OfReal) PolesPtr;
Handle(TColStd_HArray1OfInteger) Mults;
Standard_Integer NbPoles = AConverter.NbPoles();
// Standard_Integer Deg=AConverter.Degree();
AppParCurves_Array1OfMultiPoint TabMU(1, NbPoles);
AConverter.Poles(PolesPtr);
AConverter.Knots(myKnots);
AConverter.Multiplicities(Mults);
for (ipole = PolesPtr->LowerRow(); ipole <= PolesPtr->UpperRow(); ipole++)
{
Standard_Integer index = PolesPtr->LowerCol();
/* if(myNbP2d !=0 )
{
for (jp2d=1;jp2d<=myNbP2d;jp2d++)
{
P2d.SetX(PolesPtr->Value(ipole,index++));
P2d.SetY(PolesPtr->Value(ipole,index++));
TabP2d.SetValue(jp2d,P2d);
}
}*/
if (myNbP3d != 0)
{
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
// std::cout << "\n Poles(ipole,1)" <<
// PolesPtr->Value(ipole,index);
P3d.SetX(PolesPtr->Value(ipole, index++));
// std::cout << "\n Poles(ipole,1)" <<
// PolesPtr->Value(ipole,index);
P3d.SetY(PolesPtr->Value(ipole, index++));
// std::cout << "\n Poles(ipole,1)" <<
// PolesPtr->Value(ipole,index);
P3d.SetZ(PolesPtr->Value(ipole, index++));
TabP3d.SetValue(jp3d, P3d);
}
}
if (myNbP2d != 0)
{
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
P2d.SetX(PolesPtr->Value(ipole, index++));
P2d.SetY(PolesPtr->Value(ipole, index++));
TabP2d.SetValue(jp2d, P2d);
}
}
if (myNbP2d != 0 && myNbP3d != 0)
{
AppParCurves_MultiPoint aMultiPoint(TabP3d, TabP2d);
TabMU.SetValue(ipole, aMultiPoint);
}
else if (myNbP2d != 0)
{
AppParCurves_MultiPoint aMultiPoint(TabP2d);
TabMU.SetValue(ipole, aMultiPoint);
}
else
{
AppParCurves_MultiPoint aMultiPoint(TabP3d);
TabMU.SetValue(ipole, aMultiPoint);
}
}
AppParCurves_MultiBSpCurve aCurve(TabMU, myKnots->Array1(), Mults->Array1());
myMBSpCurve = aCurve;
myIsDone = Standard_True;
}
}
}
//
//=======================================================================
// function : IsCreated
// purpose : returns True if the creation is done
//=======================================================================
//
Standard_Boolean AppDef_Variational::IsCreated() const
{
return myIsCreated;
}
//
//=======================================================================
// function : IsDone
// purpose : returns True if the approximation is ok
//=======================================================================
//
Standard_Boolean AppDef_Variational::IsDone() const
{
return myIsDone;
}
//
//=======================================================================
// function : IsOverConstrained
// purpose : returns True if the problem is overconstrained
// in this case, approximation cannot be done.
//=======================================================================
//
Standard_Boolean AppDef_Variational::IsOverConstrained() const
{
return myIsOverConstr;
}
//
//=======================================================================
// function : Value
// purpose : returns all the BSpline curves approximating the
// MultiLine SSP after minimization of the parameter.
//=======================================================================
//
AppParCurves_MultiBSpCurve AppDef_Variational::Value() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myMBSpCurve;
}
//
//=======================================================================
// function : MaxError
// purpose : returns the maximum of the distances between
// the points of the multiline and the approximation
// curves.
//=======================================================================
//
Standard_Real AppDef_Variational::MaxError() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myMaxError;
}
//
//=======================================================================
// function : MaxErrorIndex
// purpose : returns the index of the MultiPoint of ErrorMax
//=======================================================================
//
Standard_Integer AppDef_Variational::MaxErrorIndex() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myMaxErrorIndex;
}
//
//=======================================================================
// function : QuadraticError
// purpose : returns the quadratic average of the distances between
// the points of the multiline and the approximation
// curves.
//=======================================================================
//
Standard_Real AppDef_Variational::QuadraticError() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myCriterium[0];
}
//
//=======================================================================
// function : Distance
// purpose : returns the distances between the points of the
// multiline and the approximation curves.
//=======================================================================
//
void AppDef_Variational::Distance(math_Matrix& mat)
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
Standard_Integer ipoint, jp2d, jp3d, index;
TColgp_Array1OfPnt TabP3d(1, Max(1, myNbP3d));
TColgp_Array1OfPnt2d TabP2d(1, Max(1, myNbP2d));
Standard_Integer j0 = mat.LowerCol() - myFirstPoint;
gp_Pnt2d P2d;
gp_Pnt P3d;
gp_Pnt Pt3d;
gp_Pnt2d Pt2d;
for (ipoint = myFirstPoint; ipoint <= myLastPoint; ipoint++)
{
index = 1;
if (myNbP3d != 0)
{
AppDef_MyLineTool::Value(mySSP, ipoint, TabP3d);
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
P3d = TabP3d.Value(jp3d);
myMBSpCurve.Value(index, myParameters->Value(ipoint), Pt3d);
mat(index++, j0 + ipoint) = P3d.Distance(Pt3d);
}
}
if (myNbP2d != 0)
{
if (myNbP3d == 0)
AppDef_MyLineTool::Value(mySSP, ipoint, TabP2d);
else
AppDef_MyLineTool::Value(mySSP, ipoint, TabP3d, TabP2d);
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
P2d = TabP2d.Value(jp2d);
myMBSpCurve.Value(index, myParameters->Value(ipoint), Pt2d);
mat(index++, j0 + ipoint) = P2d.Distance(Pt2d);
}
}
}
}
//
//=======================================================================
// function : AverageError
// purpose : returns the average error between
// the MultiLine and the approximation.
//=======================================================================
//
Standard_Real AppDef_Variational::AverageError() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myAverageError;
}
//
//=======================================================================
// function : Parameters
// purpose : returns the parameters uses to the approximations
//=======================================================================
//
const Handle(TColStd_HArray1OfReal)& AppDef_Variational::Parameters() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myParameters;
}
//
//=======================================================================
// function : Knots
// purpose : returns the knots uses to the approximations
//=======================================================================
//
const Handle(TColStd_HArray1OfReal)& AppDef_Variational::Knots() const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
return myKnots;
}
//
//=======================================================================
// function : Criterium
// purpose : returns the values of the quality criterium.
//=======================================================================
//
void AppDef_Variational::Criterium(Standard_Real& VFirstOrder,
Standard_Real& VSecondOrder,
Standard_Real& VThirdOrder) const
{
if (myIsDone == Standard_False)
throw StdFail_NotDone();
VFirstOrder = myCriterium[1];
VSecondOrder = myCriterium[2];
VThirdOrder = myCriterium[3];
}
//
//=======================================================================
// function : CriteriumWeight
// purpose : returns the Weights (as percent) associed to the criterium used in
// the optimization.
//=======================================================================
//
void AppDef_Variational::CriteriumWeight(Standard_Real& Percent1,
Standard_Real& Percent2,
Standard_Real& Percent3) const
{
Percent1 = myPercent[0];
Percent2 = myPercent[1];
Percent3 = myPercent[2];
}
//
//=======================================================================
// function : MaxDegree
// purpose : returns the Maximum Degree used in the approximation
//=======================================================================
//
Standard_Integer AppDef_Variational::MaxDegree() const
{
return myMaxDegree;
}
//
//=======================================================================
// function : MaxSegment
// purpose : returns the Maximum of segment used in the approximation
//=======================================================================
//
Standard_Integer AppDef_Variational::MaxSegment() const
{
return myMaxSegment;
}
//
//=======================================================================
// function : Continuity
// purpose : returns the Continuity used in the approximation
//=======================================================================
//
GeomAbs_Shape AppDef_Variational::Continuity() const
{
return myContinuity;
}
//
//=======================================================================
// function : WithMinMax
// purpose : returns if the approximation search to minimize the
// maximum Error or not.
//=======================================================================
//
Standard_Boolean AppDef_Variational::WithMinMax() const
{
return myWithMinMax;
}
//
//=======================================================================
// function : WithCutting
// purpose : returns if the approximation can insert new Knots or not.
//=======================================================================
//
Standard_Boolean AppDef_Variational::WithCutting() const
{
return myWithCutting;
}
//
//=======================================================================
// function : Tolerance
// purpose : returns the tolerance used in the approximation.
//=======================================================================
//
Standard_Real AppDef_Variational::Tolerance() const
{
return myTolerance;
}
//
//=======================================================================
// function : NbIterations
// purpose : returns the number of iterations used in the approximation.
//=======================================================================
//
Standard_Integer AppDef_Variational::NbIterations() const
{
return myNbIterations;
}
//
//=======================================================================
// function : Dump
// purpose : Prints on the stream o information on the current state
// of the object.
//=======================================================================
//
void AppDef_Variational::Dump(Standard_OStream& o) const
{
o << " \nVariational Smoothing " << std::endl;
o << " Number of multipoints " << myNbPoints << std::endl;
o << " Number of 2d par multipoint " << myNbP2d << std::endl;
o << " Nombre of 3d par multipoint " << myNbP3d << std::endl;
o << " Number of PassagePoint " << myNbPassPoints << std::endl;
o << " Number of TangencyPoints " << myNbTangPoints << std::endl;
o << " Number of CurvaturePoints " << myNbCurvPoints << std::endl;
o << " \nTolerance " << o.setf(std::ios::scientific) << std::setprecision(3) << std::setw(9)
<< myTolerance;
if (WithMinMax())
{
o << " as Max Error." << std::endl;
}
else
{
o << " as size Error." << std::endl;
}
o << "CriteriumWeights : " << myPercent[0] << " , " << myPercent[1] << " , " << myPercent[2]
<< std::endl;
if (myIsDone)
{
o << " MaxError " << std::setprecision(3) << std::setw(9) << myMaxError
<< std::endl;
o << " Index of MaxError " << myMaxErrorIndex << std::endl;
o << " Average Error " << std::setprecision(3) << std::setw(9) << myAverageError
<< std::endl;
o << " Quadratic Error " << std::setprecision(3) << std::setw(9) << myCriterium[0]
<< std::endl;
o << " Tension Criterium " << std::setprecision(3) << std::setw(9) << myCriterium[1]
<< std::endl;
o << " Flexion Criterium " << std::setprecision(3) << std::setw(9) << myCriterium[2]
<< std::endl;
o << " Jerk Criterium " << std::setprecision(3) << std::setw(9) << myCriterium[3]
<< std::endl;
o << " NbSegments " << myKnots->Length() - 1 << std::endl;
}
else
{
o << (myIsOverConstr ? " The problem is overconstraint" : " Error in approximation")
<< std::endl;
}
}
//=======================================================================
// function : SetConstraints
// purpose : Define the constraints to approximate
// If this value is incompatible with the others fields
// this method modify nothing and returns false
//=======================================================================
//
Standard_Boolean AppDef_Variational::SetConstraints(
const Handle(AppParCurves_HArray1OfConstraintCouple)& aConstraint)
{
myConstraints = aConstraint;
Init();
if (myIsOverConstr)
return Standard_False;
else
return Standard_True;
}
//
//=======================================================================
// function : SetParameters
// purpose : Defines the parameters used by the approximations.
//=======================================================================
//
void AppDef_Variational::SetParameters(const Handle(TColStd_HArray1OfReal)& param)
{
myParameters->ChangeArray1() = param->Array1();
}
//
//=======================================================================
// function : SetKnots
// purpose : Defines the knots used by the approximations
// -- If this value is incompatible with the others fields
// -- this method modify nothing and returns false
//=======================================================================
//
Standard_Boolean AppDef_Variational::SetKnots(const Handle(TColStd_HArray1OfReal)& knots)
{
myKnots->ChangeArray1() = knots->Array1();
return Standard_True;
}
//
//=======================================================================
// function : SetMaxDegree
// purpose : Define the Maximum Degree used in the approximation
// If this value is incompatible with the others fields
// this method modify nothing and returns false
//=======================================================================
//
Standard_Boolean AppDef_Variational::SetMaxDegree(const Standard_Integer Degree)
{
if (((Degree - myNivCont) * myMaxSegment - myNbPassPoints - 2 * myNbTangPoints
- 3 * myNbCurvPoints)
< 0)
return Standard_False;
else
{
myMaxDegree = Degree;
InitSmoothCriterion();
return Standard_True;
}
}
//
//=======================================================================
// function : SetMaxSegment
// purpose : Define the maximum number of segments used in the approximation
// If this value is incompatible with the others fields
// this method modify nothing and returns false
//=======================================================================
//
Standard_Boolean AppDef_Variational::SetMaxSegment(const Standard_Integer NbSegment)
{
if (myWithCutting == Standard_True
&& ((myMaxDegree - myNivCont) * NbSegment - myNbPassPoints - 2 * myNbTangPoints
- 3 * myNbCurvPoints)
< 0)
return Standard_False;
else
{
myMaxSegment = NbSegment;
return Standard_True;
}
}
//
//=======================================================================
// function : SetContinuity
// purpose : Define the Continuity used in the approximation
// If this value is incompatible with the others fields
// this method modify nothing and returns false
//=======================================================================
//
Standard_Boolean AppDef_Variational::SetContinuity(const GeomAbs_Shape C)
{
Standard_Integer NivCont = 0;
switch (C)
{
case GeomAbs_C0:
NivCont = 0;
break;
case GeomAbs_C1:
NivCont = 1;
break;
case GeomAbs_C2:
NivCont = 2;
break;
default:
throw Standard_ConstructionError();
}
if (((myMaxDegree - NivCont) * myMaxSegment - myNbPassPoints - 2 * myNbTangPoints
- 3 * myNbCurvPoints)
< 0)
return Standard_False;
else
{
myContinuity = C;
myNivCont = NivCont;
InitSmoothCriterion();
return Standard_True;
}
}
//
//=======================================================================
// function : SetWithMinMax
// purpose : Define if the approximation search to minimize the
// maximum Error or not.
//=======================================================================
//
void AppDef_Variational::SetWithMinMax(const Standard_Boolean MinMax)
{
myWithMinMax = MinMax;
InitSmoothCriterion();
}
//
//=======================================================================
// function : SetWithCutting
// purpose : Define if the approximation can insert new Knots or not.
// If this value is incompatible with the others fields
// this method modify nothing and returns false
//=======================================================================
//
Standard_Boolean AppDef_Variational::SetWithCutting(const Standard_Boolean Cutting)
{
if (Cutting == Standard_False)
{
if (((myMaxDegree - myNivCont) * myKnots->Length() - myNbPassPoints - 2 * myNbTangPoints
- 3 * myNbCurvPoints)
< 0)
return Standard_False;
else
{
myWithCutting = Cutting;
InitSmoothCriterion();
return Standard_True;
}
}
else
{
if (((myMaxDegree - myNivCont) * myMaxSegment - myNbPassPoints - 2 * myNbTangPoints
- 3 * myNbCurvPoints)
< 0)
return Standard_False;
else
{
myWithCutting = Cutting;
InitSmoothCriterion();
return Standard_True;
}
}
}
//
//=======================================================================
// function : SetCriteriumWeight
// purpose : define the Weights (as percent) associed to the criterium used in
// the optimization.
//=======================================================================
//
void AppDef_Variational::SetCriteriumWeight(const Standard_Real Percent1,
const Standard_Real Percent2,
const Standard_Real Percent3)
{
if (Percent1 < 0 || Percent2 < 0 || Percent3 < 0)
throw Standard_DomainError();
Standard_Real Total = Percent1 + Percent2 + Percent3;
myPercent[0] = Percent1 / Total;
myPercent[1] = Percent2 / Total;
myPercent[2] = Percent3 / Total;
InitSmoothCriterion();
}
//
//=======================================================================
// function : SetCriteriumWeight
// purpose : define the Weight (as percent) associed to the
// criterium Order used in the optimization : Others
// weights are updated.
//=======================================================================
//
void AppDef_Variational::SetCriteriumWeight(const Standard_Integer Order,
const Standard_Real Percent)
{
if (Percent < 0)
throw Standard_DomainError();
if (Order < 1 || Order > 3)
throw Standard_ConstructionError();
myPercent[Order - 1] = Percent;
Standard_Real Total = myPercent[0] + myPercent[1] + myPercent[2];
myPercent[0] = myPercent[0] / Total;
myPercent[1] = myPercent[1] / Total;
myPercent[2] = myPercent[2] / Total;
InitSmoothCriterion();
}
//
//=======================================================================
// function : SetTolerance
// purpose : define the tolerance used in the approximation.
//=======================================================================
//
void AppDef_Variational::SetTolerance(const Standard_Real Tol)
{
myTolerance = Tol;
InitSmoothCriterion();
}
//
//=======================================================================
// function : SetNbIterations
// purpose : define the number of iterations used in the approximation.
//=======================================================================
//
void AppDef_Variational::SetNbIterations(const Standard_Integer Iter)
{
myNbIterations = Iter;
}
//====================== Private Methodes =============================//
//=======================================================================
// function : TheMotor
// purpose : Smoothing's motor like STRIM routine "MOTLIS"
//=======================================================================
void AppDef_Variational::TheMotor(Handle(AppDef_SmoothCriterion)& J,
// const Standard_Real WQuadratic,
const Standard_Real,
const Standard_Real WQuality,
Handle(FEmTool_Curve)& TheCurve,
TColStd_Array1OfReal& Ecarts)
{
// ...
const Standard_Real BigValue = 1.e37, SmallValue = 1.e-6, SmallestValue = 1.e-9;
Handle(TColStd_HArray1OfReal) CurrentTi, NewTi, OldTi;
Handle(TColStd_HArray2OfInteger) Dependence;
Standard_Boolean lestim, ToOptim, iscut;
Standard_Boolean isnear = Standard_False, again = Standard_True;
Standard_Integer NbEst, ICDANA, NumPnt, Iter;
Standard_Integer MaxNbEst = 5;
Standard_Real VOCRI[3] = {BigValue, BigValue, BigValue}, EROLD = BigValue, VALCRI[3],
ERRMAX = BigValue, ERRMOY, ERRQUA;
Standard_Real CBLONG, LNOLD;
Standard_Integer NbrPnt = myLastPoint - myFirstPoint + 1;
Standard_Integer NbrConstraint = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
Handle(FEmTool_Curve) CCurrent, COld, CNew;
Standard_Real EpsLength = SmallValue;
Standard_Real EpsDeg;
Standard_Real e1, e2, e3;
Standard_Real J1min, J2min, J3min;
Standard_Integer iprog;
// (0) Init
J->GetEstimation(e1, e2, e3);
J1min = 1.e-8;
J2min = J3min = (e1 + 1.e-8) * 1.e-6;
if (e1 < J1min)
e1 = J1min; // Like in
if (e2 < J2min)
e2 = J2min; // MOTLIS
if (e3 < J3min)
e3 = J3min;
J->SetEstimation(e1, e2, e3);
CCurrent = TheCurve;
CurrentTi = new TColStd_HArray1OfReal(1, myParameters->Length());
CurrentTi->ChangeArray1() = myParameters->Array1();
OldTi = new (TColStd_HArray1OfReal)(1, CurrentTi->Length());
OldTi->ChangeArray1() = CurrentTi->Array1();
COld = CCurrent;
LNOLD = CBLONG = J->EstLength();
Dependence = J->DependenceTable();
J->SetCurve(CCurrent);
FEmTool_Assembly* TheAssembly = new FEmTool_Assembly(Dependence->Array2(), J->AssemblyTable());
//============ Optimization ============================
// Standard_Integer inagain = 0;
while (again)
{
// (1) Loop Optimization / Estimation
lestim = Standard_True;
Standard_Boolean lconst = Standard_True;
NbEst = 0;
J->SetCurve(CCurrent);
while (lestim)
{
// (1.1) Curve's Optimization.
EpsLength = SmallValue * CBLONG / NbrPnt;
CNew = new (
FEmTool_Curve)(CCurrent->Dimension(), CCurrent->NbElements(), CCurrent->Base(), EpsLength);
CNew->Knots() = CCurrent->Knots();
J->SetParameters(CurrentTi);
EpsDeg = Min(WQuality * .1, CBLONG * .001);
Optimization(J, *TheAssembly, lconst, EpsDeg, CNew, CurrentTi->Array1());
lconst = Standard_False;
// (1.2) calcul des criteres de qualites et amelioration
// des estimation.
ICDANA = J->QualityValues(J1min, J2min, J3min, VALCRI[0], VALCRI[1], VALCRI[2]);
if (ICDANA > 0)
lconst = Standard_True;
J->ErrorValues(ERRMAX, ERRQUA, ERRMOY);
isnear = ((Sqrt(ERRQUA / NbrPnt) < 2 * WQuality) && (myNbIterations > 1));
// (1.3) Optimisation des ti par proj orthogonale
// et calcul de l'erreur aux points.
if (isnear)
{
NewTi = new (TColStd_HArray1OfReal)(1, CurrentTi->Length());
Project(CNew,
CurrentTi->Array1(),
NewTi->ChangeArray1(),
Ecarts,
NumPnt,
ERRMAX,
ERRQUA,
ERRMOY,
2);
}
else
NewTi = CurrentTi;
// (1.4) Progression's test
iprog = 0;
if ((EROLD > WQuality) && (ERRMAX < 0.95 * EROLD))
iprog++;
if ((EROLD > WQuality) && (ERRMAX < 0.8 * EROLD))
iprog++;
if ((EROLD > WQuality) && (ERRMAX < WQuality))
iprog++;
if ((EROLD > WQuality) && (ERRMAX < 0.99 * EROLD) && (ERRMAX < 1.1 * WQuality))
iprog++;
if (VALCRI[0] < 0.975 * VOCRI[0])
iprog++;
if (VALCRI[0] < 0.9 * VOCRI[0])
iprog++;
if (VALCRI[1] < 0.95 * VOCRI[1])
iprog++;
if (VALCRI[1] < 0.8 * VOCRI[1])
iprog++;
if (VALCRI[2] < 0.95 * VOCRI[2])
iprog++;
if (VALCRI[2] < 0.8 * VOCRI[2])
iprog++;
if ((VOCRI[1] > SmallestValue) && (VOCRI[2] > SmallestValue))
{
if ((VALCRI[1] / VOCRI[1] + 2 * VALCRI[2] / VOCRI[2]) < 2.8)
iprog++;
}
if (iprog < 2 && NbEst == 0)
{
// (1.5) Invalidation of new knots.
VALCRI[0] = VOCRI[0];
VALCRI[1] = VOCRI[1];
VALCRI[2] = VOCRI[2];
ERRMAX = EROLD;
CBLONG = LNOLD;
CCurrent = COld;
CurrentTi = OldTi;
goto L8000; // exit
}
VOCRI[0] = VALCRI[0];
VOCRI[1] = VALCRI[1];
VOCRI[2] = VALCRI[2];
LNOLD = CBLONG;
EROLD = ERRMAX;
CCurrent = CNew;
CurrentTi = NewTi;
// (1.6) Test if the Estimations seems OK, else repeat
NbEst++;
lestim = ((NbEst < MaxNbEst) && (ICDANA == 2) && (iprog > 0));
if (lestim && isnear)
{
// (1.7) Optimization of ti by ACR.
std::stable_sort(CurrentTi->begin(), CurrentTi->end());
Standard_Integer Decima = 4;
CCurrent->Length(0., 1., CBLONG);
J->EstLength() = CBLONG;
ACR(CCurrent, CurrentTi->ChangeArray1(), Decima);
lconst = Standard_True;
}
}
// (2) loop of parametric / geometric optimization
Iter = 1;
ToOptim = ((Iter < myNbIterations) && (isnear));
while (ToOptim)
{
Iter++;
// (2.1) Save current results
VOCRI[0] = VALCRI[0];
VOCRI[1] = VALCRI[1];
VOCRI[2] = VALCRI[2];
EROLD = ERRMAX;
LNOLD = CBLONG;
COld = CCurrent;
OldTi->ChangeArray1() = CurrentTi->Array1();
// (2.2) Optimization des ti by ACR.
std::stable_sort(CurrentTi->begin(), CurrentTi->end());
Standard_Integer Decima = 4;
CCurrent->Length(0., 1., CBLONG);
J->EstLength() = CBLONG;
ACR(CCurrent, CurrentTi->ChangeArray1(), Decima);
lconst = Standard_True;
// (2.3) Optimisation des courbes
EpsLength = SmallValue * CBLONG / NbrPnt;
CNew = new (
FEmTool_Curve)(CCurrent->Dimension(), CCurrent->NbElements(), CCurrent->Base(), EpsLength);
CNew->Knots() = CCurrent->Knots();
J->SetParameters(CurrentTi);
EpsDeg = Min(WQuality * .1, CBLONG * .001);
Optimization(J, *TheAssembly, lconst, EpsDeg, CNew, CurrentTi->Array1());
CCurrent = CNew;
// (2.4) calcul des criteres de qualites et amelioration
// des estimation.
ICDANA = J->QualityValues(J1min, J2min, J3min, VALCRI[0], VALCRI[1], VALCRI[2]);
if (ICDANA > 0)
lconst = Standard_True;
J->GetEstimation(e1, e2, e3);
// (2.5) Optimisation des ti par proj orthogonale
NewTi = new (TColStd_HArray1OfReal)(1, CurrentTi->Length());
Project(CCurrent,
CurrentTi->Array1(),
NewTi->ChangeArray1(),
Ecarts,
NumPnt,
ERRMAX,
ERRQUA,
ERRMOY,
2);
// (2.6) Test de non regression
Standard_Integer iregre = 0;
if (NbrConstraint < NbrPnt)
{
if ((ERRMAX > WQuality) && (ERRMAX > 1.05 * EROLD))
iregre++;
if ((ERRMAX > WQuality) && (ERRMAX > 2 * EROLD))
iregre++;
if ((EROLD > WQuality) && (ERRMAX <= 0.5 * EROLD))
iregre--;
}
Standard_Real E1, E2, E3;
J->GetEstimation(E1, E2, E3);
if ((VALCRI[0] > E1) && (VALCRI[0] > 1.1 * VOCRI[0]))
iregre++;
if ((VALCRI[1] > E2) && (VALCRI[1] > 1.1 * VOCRI[1]))
iregre++;
if ((VALCRI[2] > E3) && (VALCRI[2] > 1.1 * VOCRI[2]))
iregre++;
if (iregre >= 2)
{
// if (iregre >= 1) {
// (2.7) on restaure l'iteration precedente
VALCRI[0] = VOCRI[0];
VALCRI[1] = VOCRI[1];
VALCRI[2] = VOCRI[2];
ERRMAX = EROLD;
CBLONG = LNOLD;
CCurrent = COld;
CurrentTi->ChangeArray1() = OldTi->Array1();
ToOptim = Standard_False;
}
else
{ // Iteration is Ok.
CCurrent = CNew;
CurrentTi = NewTi;
}
if (Iter >= myNbIterations)
ToOptim = Standard_False;
}
// (3) Decoupe eventuelle
if ((CCurrent->NbElements() < myMaxSegment) && myWithCutting)
{
// (3.1) Sauvgarde de l'etat precedent
VOCRI[0] = VALCRI[0];
VOCRI[1] = VALCRI[1];
VOCRI[2] = VALCRI[2];
EROLD = ERRMAX;
COld = CCurrent;
OldTi->ChangeArray1() = CurrentTi->Array1();
// (3.2) On arrange les ti : Trie + recadrage sur (0,1)
// ---> On trie, afin d'assurer l'ordre par la suite.
std::stable_sort(CurrentTi->begin(), CurrentTi->end());
if ((CurrentTi->Value(1) != 0.) || (CurrentTi->Value(NbrPnt) != 1.))
{
Standard_Real t, DelatT = 1.0 / (CurrentTi->Value(NbrPnt) - CurrentTi->Value(1));
for (Standard_Integer ii = 2; ii < NbrPnt; ii++)
{
t = (CurrentTi->Value(ii) - CurrentTi->Value(1)) * DelatT;
CurrentTi->SetValue(ii, t);
}
CurrentTi->SetValue(1, 0.);
CurrentTi->SetValue(NbrPnt, 1.);
}
// (3.3) Insert new Knots
SplitCurve(CCurrent, CurrentTi->Array1(), EpsLength, CNew, iscut);
if (!iscut)
again = Standard_False;
else
{
CCurrent = CNew;
// New Knots => New Assembly.
J->SetCurve(CNew);
delete TheAssembly;
TheAssembly = new FEmTool_Assembly(Dependence->Array2(), J->AssemblyTable());
}
}
else
{
again = Standard_False;
}
}
// ================ Great loop end ===================
L8000:
// (4) Compute the best Error.
NewTi = new (TColStd_HArray1OfReal)(1, CurrentTi->Length());
Project(CCurrent,
CurrentTi->Array1(),
NewTi->ChangeArray1(),
Ecarts,
NumPnt,
ERRMAX,
ERRQUA,
ERRMOY,
10);
// (5) field's update
TheCurve = CCurrent;
J->EstLength() = CBLONG;
myParameters->ChangeArray1() = NewTi->Array1();
myCriterium[0] = ERRQUA;
myCriterium[1] = Sqrt(VALCRI[0]);
myCriterium[2] = Sqrt(VALCRI[1]);
myCriterium[3] = Sqrt(VALCRI[2]);
myMaxError = ERRMAX;
myMaxErrorIndex = NumPnt;
if (NbrPnt > NbrConstraint)
myAverageError = ERRMOY / (NbrPnt - NbrConstraint);
else
myAverageError = ERRMOY / NbrConstraint;
delete TheAssembly;
}
//=======================================================================
// function : Optimization
// purpose : (like FORTRAN subroutine MINIMI)
//=======================================================================
void AppDef_Variational::Optimization(Handle(AppDef_SmoothCriterion)& J,
FEmTool_Assembly& A,
const Standard_Boolean ToAssemble,
const Standard_Real EpsDeg,
Handle(FEmTool_Curve)& Curve,
const TColStd_Array1OfReal& Parameters) const
{
Standard_Integer MxDeg = Curve->Base()->WorkDegree(), NbElm = Curve->NbElements(),
NbDim = Curve->Dimension();
Handle(FEmTool_HAssemblyTable) AssTable;
math_Matrix H(0, MxDeg, 0, MxDeg);
math_Vector G(0, MxDeg), Sol(1, A.NbGlobVar());
Standard_Integer el, dim;
A.GetAssemblyTable(AssTable);
Standard_Integer NbConstr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
Standard_Real CBLONG = J->EstLength();
// Updating Assembly
if (ToAssemble)
A.NullifyMatrix();
A.NullifyVector();
for (el = 1; el <= NbElm; el++)
{
if (ToAssemble)
{
J->Hessian(el, 1, 1, H);
for (dim = 1; dim <= NbDim; dim++)
A.AddMatrix(el, dim, dim, H);
}
for (dim = 1; dim <= NbDim; dim++)
{
J->Gradient(el, dim, G);
A.AddVector(el, dim, G);
}
}
// Solution of system
if (ToAssemble)
{
if (NbConstr != 0)
{ // Treatment of constraints
AssemblingConstraints(Curve, Parameters, CBLONG, A);
}
A.Solve();
}
A.Solution(Sol);
// Updating J
J->SetCurve(Curve);
J->InputVector(Sol, AssTable);
// Updating Curve and reduction of degree
Standard_Integer Newdeg;
Standard_Real MaxError;
if (NbConstr == 0)
{
for (el = 1; el <= NbElm; el++)
{
Curve->ReduceDegree(el, EpsDeg, Newdeg, MaxError);
}
}
else
{
TColStd_Array1OfReal& TabInt = Curve->Knots();
Standard_Integer Icnt = 1, p0 = Parameters.Lower() - myFirstPoint, point;
for (el = 1; el <= NbElm; el++)
{
while ((Icnt < NbConstr)
&& (Parameters(p0 + myTypConstraints->Value(2 * Icnt - 1)) <= TabInt(el)))
Icnt++;
point = p0 + myTypConstraints->Value(2 * Icnt - 1);
if (Parameters(point) <= TabInt(el) || Parameters(point) >= TabInt(el + 1))
Curve->ReduceDegree(el, EpsDeg, Newdeg, MaxError);
else if (Curve->Degree(el) < MxDeg)
Curve->SetDegree(el, MxDeg);
}
}
}
void AppDef_Variational::Project(const Handle(FEmTool_Curve)& C,
const TColStd_Array1OfReal& Ti,
TColStd_Array1OfReal& ProjTi,
TColStd_Array1OfReal& Distance,
Standard_Integer& NumPoints,
Standard_Real& MaxErr,
Standard_Real& QuaErr,
Standard_Real& AveErr,
const Standard_Integer NbIterations) const
{
// Initialisation
const Standard_Real Seuil = 1.e-9, Eps = 1.e-12;
MaxErr = QuaErr = AveErr = 0.;
Standard_Integer Ipnt, NItCv, Iter, i, i0 = -myDimension, d0 = Distance.Lower() - 1;
Standard_Real TNew, Dist, T0, Dist0, F1, F2, Aux, DF, Ecart;
Standard_Boolean EnCour;
TColStd_Array1OfReal ValOfC(1, myDimension), FirstDerOfC(1, myDimension),
SecndDerOfC(1, myDimension);
for (Ipnt = 1; Ipnt <= ProjTi.Length(); Ipnt++)
{
i0 += myDimension;
TNew = Ti(Ipnt);
EnCour = Standard_True;
NItCv = 0;
Iter = 0;
C->D0(TNew, ValOfC);
Dist = 0;
for (i = 1; i <= myDimension; i++)
{
Aux = ValOfC(i) - myTabPoints->Value(i0 + i);
Dist += Aux * Aux;
}
Dist = Sqrt(Dist);
// ------- Newton's method for solving (C'(t),C(t) - P) = 0
while (EnCour)
{
Iter++;
T0 = TNew;
Dist0 = Dist;
C->D2(TNew, SecndDerOfC);
C->D1(TNew, FirstDerOfC);
F1 = F2 = 0.;
for (i = 1; i <= myDimension; i++)
{
Aux = ValOfC(i) - myTabPoints->Value(i0 + i);
DF = FirstDerOfC(i);
F1 += Aux * DF; // (C'(t),C(t) - P)
F2 += DF * DF + Aux * SecndDerOfC(i); // ((C'(t),C(t) - P))'
}
if (Abs(F2) < Eps)
EnCour = Standard_False;
else
{
// Formula of Newton x(k+1) = x(k) - F(x(k))/F'(x(k))
TNew -= F1 / F2;
if (TNew < 0.)
TNew = 0.;
if (TNew > 1.)
TNew = 1.;
// Analysis of result
C->D0(TNew, ValOfC);
Dist = 0;
for (i = 1; i <= myDimension; i++)
{
Aux = ValOfC(i) - myTabPoints->Value(i0 + i);
Dist += Aux * Aux;
}
Dist = Sqrt(Dist);
Ecart = Dist0 - Dist;
if (Ecart <= -Seuil)
{
// Pas d'amelioration on s'arrete
EnCour = Standard_False;
TNew = T0;
Dist = Dist0;
}
else if (Ecart <= Seuil)
// Convergence
NItCv++;
else
NItCv = 0;
if ((NItCv >= 2) || (Iter >= NbIterations))
EnCour = Standard_False;
}
}
ProjTi(Ipnt) = TNew;
Distance(d0 + Ipnt) = Dist;
if (Dist > MaxErr)
{
MaxErr = Dist;
NumPoints = Ipnt;
}
QuaErr += Dist * Dist;
AveErr += Dist;
}
// clang-format off
NumPoints = NumPoints + myFirstPoint - 1;// Setting NumPoints to interval [myFirstPoint, myLastPoint]
// clang-format on
}
void AppDef_Variational::ACR(Handle(FEmTool_Curve)& Curve,
TColStd_Array1OfReal& Ti,
const Standard_Integer Decima) const
{
const Standard_Real Eps = 1.e-8;
TColStd_Array1OfReal& Knots = Curve->Knots();
Standard_Integer NbrPnt = Ti.Length(), TiFirst = Ti.Lower(), TiLast = Ti.Upper(),
KFirst = Knots.Lower(), KLast = Knots.Upper();
Standard_Real CbLong, DeltaT, VTest, UNew, UOld, DU, TPara, TOld, DTInv, Ratio;
Standard_Integer ipnt, ii, IElm, IOld, POld, PCnt, ICnt = 0;
Standard_Integer NbCntr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
// (1) Calcul de la longueur de courbe
Curve->Length(Ti(TiFirst), Ti(TiLast), CbLong);
// (2) Mise de l'acr dans Ti
if (NbrPnt >= 2)
{
// (2.0) Initialisation
DeltaT = (Ti(TiLast) - Ti(TiFirst)) / Decima;
VTest = Ti(TiFirst) + DeltaT;
if (NbCntr > 0)
{
PCnt = myTypConstraints->Value(1) - myFirstPoint + TiFirst;
ICnt = 1;
}
else
PCnt = TiLast + 1;
UOld = 0.;
TOld = Ti(TiFirst);
POld = TiFirst;
IElm = KFirst;
IOld = IElm;
Ti(TiFirst) = 0.;
for (ipnt = TiFirst + 1; ipnt <= TiLast; ipnt++)
{
while ((ICnt <= NbCntr) && (PCnt < ipnt))
{
ICnt++;
PCnt = myTypConstraints->Value(2 * ICnt - 1) - myFirstPoint + TiFirst;
}
TPara = Ti(ipnt);
if (TPara >= VTest || PCnt == ipnt)
{
if (Ti(TiLast) - TPara <= 1.e-2 * DeltaT)
{
ipnt = TiLast;
TPara = Ti(ipnt);
}
// (2.2), (2.3) Cacul la longueur de courbe
Curve->Length(Ti(TiFirst), TPara, UNew);
UNew /= CbLong;
while (Knots(IElm + 1) < TPara && IElm < KLast - 1)
IElm++;
// (2.4) Mise a jours des parametres de decoupe
DTInv = 1. / (TPara - TOld);
DU = UNew - UOld;
for (ii = IOld + 1; ii <= IElm; ii++)
{
Ratio = (Knots(ii) - TOld) * DTInv;
Knots(ii) = UOld + Ratio * DU;
}
// (2.5) Mise a jours des parametres de points.
// Very strange loop, because it never works (POld+1 > ipnt-1)
for (ii = POld + 1; ii <= ipnt - 1; ii++)
{
Ratio = (Ti(ii) - TOld) * DTInv;
Ti(ii) = UOld + Ratio * DU;
}
Ti(ipnt) = UNew;
UOld = UNew;
IOld = IElm;
TOld = TPara;
POld = ipnt;
}
// --> Nouveau seuil parametrique pour le decimage
if (TPara >= VTest)
{
// ii = RealToInt((TPara - VTest + Eps) / DeltaT);
// VTest += (ii + 1) * DeltaT;
VTest += Ceiling((TPara - VTest + Eps) / DeltaT) * DeltaT;
if (VTest > 1. - Eps)
VTest = 1.;
}
}
}
// --- On ajuste les valeurs extremes
Ti(TiFirst) = 0.;
Ti(TiLast) = 1.;
ii = TiLast - 1;
while (Ti(ii) > Knots(KLast))
{
Ti(ii) = 1.;
--ii;
}
Knots(KFirst) = 0.;
Knots(KLast) = 1.;
}
//----------------------------------------------------------//
// Standard_Integer NearIndex //
// Purpose: searching nearest index of TabPar corresponding //
// given value T (is similar to fortran routine MSRRE2) //
//----------------------------------------------------------//
static Standard_Integer NearIndex(const Standard_Real T,
const TColStd_Array1OfReal& TabPar,
const Standard_Real Eps,
Standard_Integer& Flag)
{
Standard_Integer Loi = TabPar.Lower(), Upi = TabPar.Upper();
Flag = 0;
if (T < TabPar(Loi))
{
Flag = -1;
return Loi;
}
if (T > TabPar(Upi))
{
Flag = 1;
return Upi;
}
Standard_Integer Ibeg = Loi, Ifin = Upi, Imidl;
while (Ibeg + 1 != Ifin)
{
Imidl = (Ibeg + Ifin) / 2;
if ((T >= TabPar(Ibeg)) && (T <= TabPar(Imidl)))
Ifin = Imidl;
else
Ibeg = Imidl;
}
if (Abs(T - TabPar(Ifin)) < Eps)
return Ifin;
return Ibeg;
}
//----------------------------------------------------------//
// void GettingKnots //
// Purpose: calculating values of new Knots for elements //
// with degree that is equal Deg //
//----------------------------------------------------------//
static void GettingKnots(const TColStd_Array1OfReal& TabPar,
const Handle(FEmTool_Curve)& InCurve,
const Standard_Integer Deg,
Standard_Integer& NbElm,
TColStd_Array1OfReal& NewKnots)
{
const Standard_Real Eps = 1.e-12;
TColStd_Array1OfReal& OldKnots = InCurve->Knots();
Standard_Integer NbMaxOld = InCurve->NbElements();
Standard_Integer NbMax = NewKnots.Upper(), Ipt, Ipt1, Ipt2;
Standard_Integer el = 0, i1 = OldKnots.Lower(), i0 = i1 - 1, Flag;
Standard_Real TPar;
while ((NbElm < NbMax) && (el < NbMaxOld))
{
el++;
i0++;
i1++; // i0, i1 are indexes of left and right knots of element el
if (InCurve->Degree(el) == Deg)
{
NbElm++;
Ipt1 = NearIndex(OldKnots(i0), TabPar, Eps, Flag);
if (Flag != 0)
Ipt1 = TabPar.Lower();
Ipt2 = NearIndex(OldKnots(i1), TabPar, Eps, Flag);
if (Flag != 0)
Ipt2 = TabPar.Upper();
if (Ipt2 - Ipt1 >= 1)
{
Ipt = (Ipt1 + Ipt2) / 2;
if (2 * Ipt == Ipt1 + Ipt2)
TPar = 2. * TabPar(Ipt);
else
TPar = TabPar(Ipt) + TabPar(Ipt + 1);
NewKnots(NbElm) = (OldKnots(i0) + OldKnots(i1) + TPar) / 4.;
}
else
NewKnots(NbElm) = (OldKnots(i0) + OldKnots(i1)) / 2.;
}
}
}
void AppDef_Variational::SplitCurve(const Handle(FEmTool_Curve)& InCurve,
const TColStd_Array1OfReal& Ti,
const Standard_Real CurveTol,
Handle(FEmTool_Curve)& OutCurve,
Standard_Boolean& iscut) const
{
Standard_Integer NbElmOld = InCurve->NbElements();
if (NbElmOld >= myMaxSegment)
{
iscut = Standard_False;
return;
}
#ifdef OCCT_DEBUG
Standard_Integer MaxDegree =
#endif
InCurve->Base()->WorkDegree();
Standard_Integer NbElm = NbElmOld;
TColStd_Array1OfReal NewKnots(NbElm + 1, myMaxSegment);
#ifndef OCCT_DEBUG
GettingKnots(Ti, InCurve, InCurve->Base()->WorkDegree(), NbElm, NewKnots);
GettingKnots(Ti, InCurve, InCurve->Base()->WorkDegree() - 1, NbElm, NewKnots);
#else
GettingKnots(Ti, InCurve, MaxDegree, NbElm, NewKnots);
GettingKnots(Ti, InCurve, MaxDegree - 1, NbElm, NewKnots);
#endif
if (NbElm > NbElmOld)
{
iscut = Standard_True;
OutCurve = new FEmTool_Curve(InCurve->Dimension(), NbElm, InCurve->Base(), CurveTol);
TColStd_Array1OfReal& OutKnots = OutCurve->Knots();
TColStd_Array1OfReal& InKnots = InCurve->Knots();
Standard_Integer i, i0 = OutKnots.Lower();
for (i = InKnots.Lower(); i <= InKnots.Upper(); i++)
OutKnots(i) = InKnots(i);
for (i = NbElmOld + 1; i <= NbElm; i++)
OutKnots(i + i0) = NewKnots(i);
std::sort(OutKnots.begin(), OutKnots.end());
}
else
iscut = Standard_False;
}
//=======================================================================
// function : InitSmoothCriterion
// purpose : Initializes the SmoothCriterion
//=======================================================================
void AppDef_Variational::InitSmoothCriterion()
{
const Standard_Real Eps2 = 1.e-6, Eps3 = 1.e-9;
// const Standard_Real J1 = .01, J2 = .001, J3 = .001;
Standard_Real Length;
InitParameters(Length);
mySmoothCriterion->SetParameters(myParameters);
Standard_Real E1, E2, E3;
InitCriterionEstimations(Length, E1, E2, E3);
/*
J1 = 1.e-8; J2 = J3 = (E1 + 1.e-8) * 1.e-6;
if(E1 < J1) E1 = J1;
if(E2 < J2) E2 = J2;
if(E3 < J3) E3 = J3;
*/
mySmoothCriterion->EstLength() = Length;
mySmoothCriterion->SetEstimation(E1, E2, E3);
Standard_Real WQuadratic, WQuality;
if (!myWithMinMax && myTolerance != 0.)
WQuality = myTolerance;
else if (myTolerance == 0.)
WQuality = 1.;
else
WQuality = Max(myTolerance, Eps2 * Length);
Standard_Integer NbConstr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
WQuadratic = Sqrt((Standard_Real)(myNbPoints - NbConstr)) * WQuality;
if (WQuadratic > Eps3)
WQuadratic = 1. / WQuadratic;
if (WQuadratic == 0.)
WQuadratic = Max(Sqrt(E1), 1.);
mySmoothCriterion->SetWeight(WQuadratic, WQuality, myPercent[0], myPercent[1], myPercent[2]);
Handle(PLib_Base) TheBase = new PLib_HermitJacobi(myMaxDegree, myContinuity);
Handle(FEmTool_Curve) TheCurve;
Standard_Integer NbElem;
Standard_Real CurvTol = Eps2 * Length / myNbPoints;
// Decoupe de l'intervalle en fonction des contraintes
if (myWithCutting == Standard_True && NbConstr != 0)
{
InitCutting(TheBase, CurvTol, TheCurve);
}
else
{
NbElem = 1;
TheCurve = new FEmTool_Curve(myDimension, NbElem, TheBase, CurvTol);
TheCurve->Knots().SetValue(TheCurve->Knots().Lower(), myParameters->Value(myFirstPoint));
TheCurve->Knots().SetValue(TheCurve->Knots().Upper(), myParameters->Value(myLastPoint));
}
mySmoothCriterion->SetCurve(TheCurve);
return;
}
//
//=======================================================================
// function : InitParameters
// purpose : Calculation of initial estimation of the multicurve's length
// and parameters for multipoints.
//=======================================================================
//
void AppDef_Variational::InitParameters(Standard_Real& Length)
{
constexpr Standard_Real Eps1 = Precision::Confusion() * .01;
Standard_Real aux, dist;
Standard_Integer i, i0, i1 = 0, ipoint;
Length = 0.;
myParameters->SetValue(myFirstPoint, Length);
for (ipoint = myFirstPoint + 1; ipoint <= myLastPoint; ipoint++)
{
i0 = i1;
i1 += myDimension;
dist = 0;
for (i = 1; i <= myDimension; i++)
{
aux = myTabPoints->Value(i1 + i) - myTabPoints->Value(i0 + i);
dist += aux * aux;
}
Length += Sqrt(dist);
myParameters->SetValue(ipoint, Length);
}
if (Length <= Eps1)
throw Standard_ConstructionError("AppDef_Variational::InitParameters");
for (ipoint = myFirstPoint + 1; ipoint <= myLastPoint - 1; ipoint++)
myParameters->SetValue(ipoint, myParameters->Value(ipoint) / Length);
myParameters->SetValue(myLastPoint, 1.);
// Avec peu de point il y a sans doute sous estimation ...
if (myNbPoints < 10)
Length *= (1. + 0.1 / (myNbPoints - 1));
}
//
//=======================================================================
// function : InitCriterionEstimations
// purpose : Calculation of initial estimation of the linear criteria
//
//=======================================================================
//
void AppDef_Variational::InitCriterionEstimations(const Standard_Real Length,
Standard_Real& E1,
Standard_Real& E2,
Standard_Real& E3) const
{
E1 = Length * Length;
constexpr Standard_Real Eps1 = Precision::Confusion() * .01;
math_Vector VTang1(1, myDimension), VTang2(1, myDimension), VTang3(1, myDimension),
VScnd1(1, myDimension), VScnd2(1, myDimension), VScnd3(1, myDimension);
// ========== Treatment of first point =================
Standard_Integer ipnt = myFirstPoint;
EstTangent(ipnt, VTang1);
ipnt++;
EstTangent(ipnt, VTang2);
ipnt++;
EstTangent(ipnt, VTang3);
ipnt = myFirstPoint;
EstSecnd(ipnt, VTang1, VTang2, Length, VScnd1);
ipnt++;
EstSecnd(ipnt, VTang1, VTang3, Length, VScnd2);
// Modified by skv - Fri Apr 8 14:58:12 2005 OCC8559 Begin
// Standard_Real Delta = .5 * (myParameters->Value(ipnt) - myParameters->Value(--ipnt));
Standard_Integer anInd = ipnt;
Standard_Real Delta = .5 * (myParameters->Value(anInd) - myParameters->Value(--ipnt));
// Modified by skv - Fri Apr 8 14:58:12 2005 OCC8559 End
if (Delta <= Eps1)
Delta = 1.;
E2 = VScnd1.Norm2() * Delta;
E3 = (Delta > Eps1) ? VScnd2.Subtracted(VScnd1).Norm2() / (4. * Delta) : 0.;
// ========== Treatment of internal points =================
Standard_Integer CurrPoint = 2;
for (ipnt = myFirstPoint + 1; ipnt < myLastPoint; ipnt++)
{
Delta = .5 * (myParameters->Value(ipnt + 1) - myParameters->Value(ipnt - 1));
if (CurrPoint == 1)
{
if (ipnt + 1 != myLastPoint)
{
EstTangent(ipnt + 2, VTang3);
EstSecnd(ipnt + 1, VTang1, VTang3, Length, VScnd2);
}
else
EstSecnd(ipnt + 1, VTang1, VTang2, Length, VScnd2);
E2 += VScnd1.Norm2() * Delta;
E3 += (Delta > Eps1) ? VScnd2.Subtracted(VScnd3).Norm2() / (4. * Delta) : 0.;
}
else if (CurrPoint == 2)
{
if (ipnt + 1 != myLastPoint)
{
EstTangent(ipnt + 2, VTang1);
EstSecnd(ipnt + 1, VTang2, VTang1, Length, VScnd3);
}
else
EstSecnd(ipnt + 1, VTang2, VTang3, Length, VScnd3);
E2 += VScnd2.Norm2() * Delta;
E3 += (Delta > Eps1) ? VScnd3.Subtracted(VScnd1).Norm2() / (4. * Delta) : 0.;
}
else
{
if (ipnt + 1 != myLastPoint)
{
EstTangent(ipnt + 2, VTang2);
EstSecnd(ipnt + 1, VTang3, VTang2, Length, VScnd1);
}
else
EstSecnd(ipnt + 1, VTang3, VTang1, Length, VScnd1);
E2 += VScnd3.Norm2() * Delta;
E3 += (Delta > Eps1) ? VScnd1.Subtracted(VScnd2).Norm2() / (4. * Delta) : 0.;
}
CurrPoint++;
if (CurrPoint == 4)
CurrPoint = 1;
}
// ========== Treatment of last point =================
Delta = .5 * (myParameters->Value(myLastPoint) - myParameters->Value(myLastPoint - 1));
if (Delta <= Eps1)
Delta = 1.;
Standard_Real aux;
if (CurrPoint == 1)
{
E2 += VScnd1.Norm2() * Delta;
aux = VScnd1.Subtracted(VScnd3).Norm2();
E3 += (Delta > Eps1) ? aux / (4. * Delta) : aux;
}
else if (CurrPoint == 2)
{
E2 += VScnd2.Norm2() * Delta;
aux = VScnd2.Subtracted(VScnd1).Norm2();
E3 += (Delta > Eps1) ? aux / (4. * Delta) : aux;
}
else
{
E2 += VScnd3.Norm2() * Delta;
aux = VScnd3.Subtracted(VScnd2).Norm2();
E3 += (Delta > Eps1) ? aux / (4. * Delta) : aux;
}
aux = Length * Length;
E2 *= aux;
E3 *= aux;
}
//
//=======================================================================
// function : EstTangent
// purpose : Calculation of estimation of the Tangent
// (see fortran routine MMLIPRI)
//=======================================================================
//
void AppDef_Variational::EstTangent(const Standard_Integer ipnt, math_Vector& VTang) const
{
Standard_Integer i;
constexpr Standard_Real Eps1 = Precision::Confusion() * .01;
const Standard_Real EpsNorm = 1.e-9;
Standard_Real Wpnt = 1.;
if (ipnt == myFirstPoint)
{
// Estimation at first point
if (myNbPoints < 3)
Wpnt = 0.;
else
{
Standard_Integer adr1 = 1, adr2 = adr1 + myDimension, adr3 = adr2 + myDimension;
math_Vector Pnt1((Standard_Real*)&myTabPoints->Value(adr1), 1, myDimension);
math_Vector Pnt2((Standard_Real*)&myTabPoints->Value(adr2), 1, myDimension);
math_Vector Pnt3((Standard_Real*)&myTabPoints->Value(adr3), 1, myDimension);
// Parabolic interpolation
// if we have parabolic interpolation: F(t) = A0 + A1*t + A2*t*t,
// first derivative for t=0 is A1 = ((d2-1)*P1 + P2 - d2*P3)/(d*(1-d))
// d= |P2-P1|/(|P2-P1|+|P3-P2|), d2 = d*d
Standard_Real V1 = Pnt2.Subtracted(Pnt1).Norm();
Standard_Real V2 = 0.;
if (V1 > Eps1)
V2 = Pnt3.Subtracted(Pnt2).Norm();
if (V2 > Eps1)
{
Standard_Real d = V1 / (V1 + V2), d1;
d1 = 1. / (d * (1 - d));
d *= d;
VTang = ((d - 1.) * Pnt1 + Pnt2 - d * Pnt3) * d1;
}
else
{
// Simple 2-point estimation
VTang = Pnt2 - Pnt1;
}
}
}
else if (ipnt == myLastPoint)
{
// Estimation at last point
if (myNbPoints < 3)
Wpnt = 0.;
else
{
Standard_Integer adr1 = (myLastPoint - 3) * myDimension + 1, adr2 = adr1 + myDimension,
adr3 = adr2 + myDimension;
math_Vector Pnt1((Standard_Real*)&myTabPoints->Value(adr1), 1, myDimension);
math_Vector Pnt2((Standard_Real*)&myTabPoints->Value(adr2), 1, myDimension);
math_Vector Pnt3((Standard_Real*)&myTabPoints->Value(adr3), 1, myDimension);
// Parabolic interpolation
// if we have parabolic interpolation: F(t) = A0 + A1*t + A2*t*t,
// first derivative for t=1 is 2*A2 + A1 = ((d2+1)*P1 - P2 - d2*P3)/(d*(1-d))
// d= |P2-P1|/(|P2-P1|+|P3-P2|), d2 = d*(d-2)
Standard_Real V1 = Pnt2.Subtracted(Pnt1).Norm();
Standard_Real V2 = 0.;
if (V1 > Eps1)
V2 = Pnt3.Subtracted(Pnt2).Norm();
if (V2 > Eps1)
{
Standard_Real d = V1 / (V1 + V2), d1;
d1 = 1. / (d * (1 - d));
d *= d - 2;
VTang = ((d + 1.) * Pnt1 - Pnt2 - d * Pnt3) * d1;
}
else
{
// Simple 2-point estimation
VTang = Pnt3 - Pnt2;
}
}
}
else
{
Standard_Integer adr1 = (ipnt - myFirstPoint - 1) * myDimension + 1,
adr2 = adr1 + 2 * myDimension;
math_Vector Pnt1((Standard_Real*)&myTabPoints->Value(adr1), 1, myDimension);
math_Vector Pnt2((Standard_Real*)&myTabPoints->Value(adr2), 1, myDimension);
VTang = Pnt2 - Pnt1;
}
Standard_Real Vnorm = VTang.Norm();
if (Vnorm <= EpsNorm)
VTang.Init(0.);
else
VTang /= Vnorm;
// Estimation with constraints
Standard_Real Wcnt = 0.;
Standard_Integer IdCnt = 1;
// Warning!! Here it is suppoused that all points are in range [myFirstPoint, myLastPoint]
Standard_Integer NbConstr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
math_Vector VCnt(1, myDimension, 0.);
if (NbConstr > 0)
{
while (myTypConstraints->Value(2 * IdCnt - 1) < ipnt && IdCnt <= NbConstr)
IdCnt++;
if ((myTypConstraints->Value(2 * IdCnt - 1) == ipnt)
&& (myTypConstraints->Value(2 * IdCnt) >= 1))
{
Wcnt = 1.;
Standard_Integer i0 = 2 * myDimension * (IdCnt - 1), k = 0;
for (i = 1; i <= myNbP3d; i++)
{
for (Standard_Integer j = 1; j <= 3; j++)
VCnt(++k) = myTabConstraints->Value(++i0);
i0 += 3;
}
for (i = 1; i <= myNbP2d; i++)
{
for (Standard_Integer j = 1; j <= 2; j++)
VCnt(++k) = myTabConstraints->Value(++i0);
i0 += 2;
}
}
}
// Averaging of estimation
Standard_Real Denom = Wpnt + Wcnt;
if (Denom == 0.)
Denom = 1.;
else
Denom = 1. / Denom;
VTang = (Wpnt * VTang + Wcnt * VCnt) * Denom;
Vnorm = VTang.Norm();
if (Vnorm <= EpsNorm)
VTang.Init(0.);
else
VTang /= Vnorm;
}
//
//=======================================================================
// function : EstSecnd
// purpose : Calculation of estimation of the second derivative
// (see fortran routine MLIMSCN)
//=======================================================================
//
void AppDef_Variational::EstSecnd(const Standard_Integer ipnt,
const math_Vector& VTang1,
const math_Vector& VTang2,
const Standard_Real Length,
math_Vector& VScnd) const
{
Standard_Integer i;
const Standard_Real Eps = 1.e-9;
Standard_Real Wpnt = 1.;
Standard_Real aux;
if (ipnt == myFirstPoint)
aux = myParameters->Value(ipnt + 1) - myParameters->Value(ipnt);
else if (ipnt == myLastPoint)
aux = myParameters->Value(ipnt) - myParameters->Value(ipnt - 1);
else
aux = myParameters->Value(ipnt + 1) - myParameters->Value(ipnt - 1);
if (aux <= Eps)
aux = 1.;
else
aux = 1. / aux;
VScnd = (VTang2 - VTang1) * aux;
// Estimation with constraints
Standard_Real Wcnt = 0.;
Standard_Integer IdCnt = 1;
// Warning!! Here it is suppoused that all points are in range [myFirstPoint, myLastPoint]
Standard_Integer NbConstr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
math_Vector VCnt(1, myDimension, 0.);
if (NbConstr > 0)
{
while (myTypConstraints->Value(2 * IdCnt - 1) < ipnt && IdCnt <= NbConstr)
IdCnt++;
if ((myTypConstraints->Value(2 * IdCnt - 1) == ipnt)
&& (myTypConstraints->Value(2 * IdCnt) >= 2))
{
Wcnt = 1.;
Standard_Integer i0 = 2 * myDimension * (IdCnt - 1) + 3, k = 0;
for (i = 1; i <= myNbP3d; i++)
{
for (Standard_Integer j = 1; j <= 3; j++)
VCnt(++k) = myTabConstraints->Value(++i0);
i0 += 3;
}
i0--;
for (i = 1; i <= myNbP2d; i++)
{
for (Standard_Integer j = 1; j <= 2; j++)
VCnt(++k) = myTabConstraints->Value(++i0);
i0 += 2;
}
}
}
// Averaging of estimation
Standard_Real Denom = Wpnt + Wcnt;
if (Denom == 0.)
Denom = 1.;
else
Denom = 1. / Denom;
VScnd = (Wpnt * VScnd + (Wcnt * Length) * VCnt) * Denom;
}
//
//=======================================================================
// function : InitCutting
// purpose : Realisation of curve's cutting a priory accordingly to
// constraints (see fortran routine MLICUT)
//=======================================================================
//
void AppDef_Variational::InitCutting(const Handle(PLib_Base)& aBase,
const Standard_Real CurvTol,
Handle(FEmTool_Curve)& aCurve) const
{
// Definition of number of elements
Standard_Integer ORCMx = -1, NCont = 0, i, kk, NbElem;
Standard_Integer NbConstr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
for (i = 1; i <= NbConstr; i++)
{
kk = Abs(myTypConstraints->Value(2 * i)) + 1;
ORCMx = Max(ORCMx, kk);
NCont += kk;
}
if (ORCMx > myMaxDegree - myNivCont)
throw Standard_ConstructionError("AppDef_Variational::InitCutting");
Standard_Integer NLibre = Max(myMaxDegree - myNivCont - (myMaxDegree + 1) / 4, myNivCont + 1);
NbElem = (NCont % NLibre == 0) ? NCont / NLibre : NCont / NLibre + 1;
while ((NbElem > myMaxSegment) && (NLibre < myMaxDegree - myNivCont))
{
NLibre++;
NbElem = (NCont % NLibre == 0) ? NCont / NLibre : NCont / NLibre + 1;
}
if (NbElem > myMaxSegment)
throw Standard_ConstructionError("AppDef_Variational::InitCutting");
aCurve = new FEmTool_Curve(myDimension, NbElem, aBase, CurvTol);
Standard_Integer NCnt = (NCont - 1) / NbElem + 1;
Standard_Integer NPlus = NbElem - (NCnt * NbElem - NCont);
TColStd_Array1OfReal& Knot = aCurve->Knots();
Standard_Integer IDeb = 0, IFin = NbConstr + 1, NDeb = 0, NFin = 0, IndEl = Knot.Lower(),
IUpper = Knot.Upper(), NbEl = 0;
Knot(IndEl) = myParameters->Value(myFirstPoint);
Knot(IUpper) = myParameters->Value(myLastPoint);
while (NbElem - NbEl > 1)
{
IndEl++;
NbEl++;
if (NPlus == 0)
NCnt--;
while (NDeb < NCnt && IDeb < IFin)
{
IDeb++;
NDeb += Abs(myTypConstraints->Value(2 * IDeb)) + 1;
}
if (NDeb == NCnt)
{
NDeb = 0;
if (NPlus == 1
&& myParameters->Value(myTypConstraints->Value(2 * IDeb - 1)) > Knot(IndEl - 1))
Knot(IndEl) = myParameters->Value(myTypConstraints->Value(2 * IDeb - 1));
else
Knot(IndEl) = (myParameters->Value(myTypConstraints->Value(2 * IDeb - 1))
+ myParameters->Value(myTypConstraints->Value(2 * IDeb + 1)))
/ 2;
}
else
{
NDeb -= NCnt;
Knot(IndEl) = myParameters->Value(myTypConstraints->Value(2 * IDeb - 1));
}
NPlus--;
if (NPlus == 0)
NCnt--;
if (NbElem - NbEl == 1)
break;
NbEl++;
while (NFin < NCnt && IDeb < IFin)
{
IFin--;
NFin += Abs(myTypConstraints->Value(2 * IFin)) + 1;
}
if (NFin == NCnt)
{
NFin = 0;
Knot(IUpper + 1 - IndEl) = (myParameters->Value(myTypConstraints->Value(2 * IFin - 1))
+ myParameters->Value(myTypConstraints->Value(2 * IFin - 3)))
/ 2;
}
else
{
NFin -= NCnt;
if (myParameters->Value(myTypConstraints->Value(2 * IFin - 1)) < Knot(IUpper - IndEl + 1))
Knot(IUpper + 1 - IndEl) = myParameters->Value(myTypConstraints->Value(2 * IFin - 1));
else
Knot(IUpper + 1 - IndEl) = (myParameters->Value(myTypConstraints->Value(2 * IFin - 1))
+ myParameters->Value(myTypConstraints->Value(2 * IFin - 3)))
/ 2;
}
}
}
//=======================================================================
// function : Adjusting
// purpose : Smoothing's adjusting like STRIM routine "MAJLIS"
//=======================================================================
void AppDef_Variational::Adjusting(Handle(AppDef_SmoothCriterion)& J,
Standard_Real& WQuadratic,
Standard_Real& WQuality,
Handle(FEmTool_Curve)& TheCurve,
TColStd_Array1OfReal& Ecarts)
{
// std::cout << "=========== Adjusting =============" << std::endl;
/* Initialized data */
const Standard_Integer mxiter = 2;
const Standard_Real eps1 = 1e-6;
Standard_Integer NbrPnt = myLastPoint - myFirstPoint + 1;
Standard_Integer NbrConstraint = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
Standard_Real CurvTol = eps1 * J->EstLength() / NbrPnt;
/* Local variables */
Standard_Integer iter, ipnt;
Standard_Real ecart, emold, erold, tpara;
Standard_Real vocri[4], j1cibl, vtest, vseuil;
Standard_Integer i, numint, flag;
TColStd_Array1OfReal tbpoid(myFirstPoint, myLastPoint);
Standard_Boolean loptim, lrejet;
Handle(AppDef_SmoothCriterion) JNew;
Handle(FEmTool_Curve) CNew;
Standard_Real E1, E2, E3;
/* (0.b) Initialisations */
loptim = Standard_True;
iter = 0;
tbpoid.Init(1.);
/* ============ boucle sur le moteur de lissage ============== */
vtest = WQuality * .9;
j1cibl = Sqrt(myCriterium[0] / (NbrPnt - NbrConstraint));
while (loptim)
{
++iter;
/* (1) Sauvegarde de l'etat precedents */
vocri[0] = myCriterium[0];
vocri[1] = myCriterium[1];
vocri[2] = myCriterium[2];
vocri[3] = myCriterium[3];
erold = myMaxError;
emold = myAverageError;
/* (2) Augmentation du poids des moindre carre */
if (j1cibl > vtest)
{
WQuadratic = j1cibl / vtest * WQuadratic;
}
/* (3) Augmentation du poid associe aux points a problemes */
vseuil = WQuality * .88;
for (ipnt = myFirstPoint; ipnt <= myLastPoint; ++ipnt)
{
if (Ecarts(ipnt) > vtest)
{
ecart = (Ecarts(ipnt) - vseuil) / WQuality;
tbpoid(ipnt) = (ecart * 3 + 1.) * tbpoid(ipnt);
}
}
/* (4) Decoupe force */
if (TheCurve->NbElements() < myMaxSegment && myWithCutting)
{
numint = NearIndex(myParameters->Value(myMaxErrorIndex), TheCurve->Knots(), 0, flag);
tpara = (TheCurve->Knots()(numint) + TheCurve->Knots()(numint + 1)
+ myParameters->Value(myMaxErrorIndex) * 2)
/ 4;
CNew = new FEmTool_Curve(myDimension, TheCurve->NbElements() + 1, TheCurve->Base(), CurvTol);
for (i = 1; i <= numint; i++)
CNew->Knots()(i) = TheCurve->Knots()(i);
for (i = numint + 1; i <= TheCurve->Knots().Length(); i++)
CNew->Knots()(i + 1) = TheCurve->Knots()(i);
CNew->Knots()(numint + 1) = tpara;
}
else
{
CNew = new FEmTool_Curve(myDimension, TheCurve->NbElements(), TheCurve->Base(), CurvTol);
CNew->Knots() = TheCurve->Knots();
}
JNew = new AppDef_LinearCriteria(mySSP, myFirstPoint, myLastPoint);
JNew->EstLength() = J->EstLength();
J->GetEstimation(E1, E2, E3);
JNew->SetEstimation(E1, E2, E3);
JNew->SetParameters(myParameters);
JNew->SetWeight(WQuadratic, WQuality, myPercent[0], myPercent[1], myPercent[2]);
JNew->SetWeight(tbpoid);
JNew->SetCurve(CNew);
/* (5) Relissage */
TheMotor(JNew, WQuadratic, WQuality, CNew, Ecarts);
/* (6) Tests de rejet */
j1cibl = Sqrt(myCriterium[0] / (NbrPnt - NbrConstraint));
vseuil = Sqrt(vocri[1]) + (erold - myMaxError) * 4;
lrejet = ((myMaxError > WQuality) && (myMaxError > erold * 1.01))
|| (Sqrt(myCriterium[1]) > vseuil * 1.05);
if (lrejet)
{
myCriterium[0] = vocri[0];
myCriterium[1] = vocri[1];
myCriterium[2] = vocri[2];
myCriterium[3] = vocri[3];
myMaxError = erold;
myAverageError = emold;
loptim = Standard_False;
}
else
{
J = JNew;
TheCurve = CNew;
J->SetCurve(TheCurve);
}
/* (7) Test de convergence */
if (((iter >= mxiter) && (myMaxSegment == CNew->NbElements())) || myMaxError < WQuality)
{
loptim = Standard_False;
}
}
}
static Standard_Boolean NotParallel(gp_Vec& T, gp_Vec& V)
{
V = T;
V.SetX(V.X() + 1.);
if (V.CrossMagnitude(T) > 1.e-12)
return Standard_True;
V.SetY(V.Y() + 1.);
if (V.CrossMagnitude(T) > 1.e-12)
return Standard_True;
V.SetZ(V.Z() + 1.);
if (V.CrossMagnitude(T) > 1.e-12)
return Standard_True;
return Standard_False;
}
void AppDef_Variational::AssemblingConstraints(const Handle(FEmTool_Curve)& Curve,
const TColStd_Array1OfReal& Parameters,
const Standard_Real CBLONG,
FEmTool_Assembly& A) const
{
Standard_Integer MxDeg = Curve->Base()->WorkDegree(), NbElm = Curve->NbElements(),
NbDim = Curve->Dimension();
TColStd_Array1OfReal G0(0, MxDeg), G1(0, MxDeg), G2(0, MxDeg);
math_Vector V0((Standard_Real*)&G0(0), 0, MxDeg), V1((Standard_Real*)&G1(0), 0, MxDeg),
V2((Standard_Real*)&G2(0), 0, MxDeg);
Standard_Integer IndexOfConstraint, Ng3d, Ng2d, NBeg2d, NPass, NgPC1, NTang3d, NTang2d, Point,
TypOfConstr, p0 = Parameters.Lower() - myFirstPoint, curel = 1, el, i, ipnt, ityp, j, k, pnt,
curdim, jt, Ntheta = 6 * myNbP3d + 2 * myNbP2d;
Standard_Integer NbConstr = myNbPassPoints + myNbTangPoints + myNbCurvPoints;
// Ng3d = 3 * NbConstr + 2 * myNbTangPoints + 5 * myNbCurvPoints;
// Ng2d = 2 * NbConstr + 1 * myNbTangPoints + 3 * myNbCurvPoints;
Ng3d = 3 * NbConstr + 3 * myNbTangPoints + 5 * myNbCurvPoints;
Ng2d = 2 * NbConstr + 2 * myNbTangPoints + 3 * myNbCurvPoints;
NBeg2d = Ng3d * myNbP3d;
// NgPC1 = NbConstr + myNbCurvPoints;
NgPC1 = NbConstr + myNbTangPoints + myNbCurvPoints;
NPass = 0;
NTang3d = 3 * NgPC1;
NTang2d = 2 * NgPC1;
TColStd_Array1OfReal& Intervals = Curve->Knots();
Standard_Real t, R1, R2;
Handle(PLib_Base) myBase = Curve->Base();
Handle(PLib_HermitJacobi) myHermitJacobi = Handle(PLib_HermitJacobi)::DownCast(myBase);
Standard_Integer Order = myHermitJacobi->NivConstr() + 1;
Standard_Real UFirst, ULast, coeff, c0, mfact, mfact1;
A.NullifyConstraint();
ipnt = -1;
ityp = 0;
for (i = 1; i <= NbConstr; i++)
{
ipnt += 2;
ityp += 2;
Point = myTypConstraints->Value(ipnt);
TypOfConstr = myTypConstraints->Value(ityp);
t = Parameters(p0 + Point);
for (el = curel; el <= NbElm;)
{
if (t <= Intervals(++el))
{
curel = el - 1;
break;
}
}
UFirst = Intervals(curel);
ULast = Intervals(curel + 1);
coeff = (ULast - UFirst) / 2.;
c0 = (ULast + UFirst) / 2.;
t = (t - c0) / coeff;
if (TypOfConstr == 0)
{
myBase->D0(t, G0);
for (k = 1; k < Order; k++)
{
mfact = Pow(coeff, k);
G0(k) *= mfact;
G0(k + Order) *= mfact;
}
}
else if (TypOfConstr == 1)
{
myBase->D1(t, G0, G1);
for (k = 1; k < Order; k++)
{
mfact = Pow(coeff, k);
G0(k) *= mfact;
G0(k + Order) *= mfact;
G1(k) *= mfact;
G1(k + Order) *= mfact;
}
mfact = 1. / coeff;
for (k = 0; k <= MxDeg; k++)
{
G1(k) *= mfact;
}
}
else
{
myBase->D2(t, G0, G1, G2);
for (k = 1; k < Order; k++)
{
mfact = Pow(coeff, k);
G0(k) *= mfact;
G0(k + Order) *= mfact;
G1(k) *= mfact;
G1(k + Order) *= mfact;
G2(k) *= mfact;
G2(k + Order) *= mfact;
}
mfact = 1. / coeff;
mfact1 = mfact / coeff;
for (k = 0; k <= MxDeg; k++)
{
G1(k) *= mfact;
G2(k) *= mfact1;
}
}
NPass++;
j = NbDim * (Point - myFirstPoint);
Standard_Integer n0 = NPass;
curdim = 0;
for (pnt = 1; pnt <= myNbP3d; pnt++)
{
IndexOfConstraint = n0;
for (k = 1; k <= 3; k++)
{
curdim++;
A.AddConstraint(IndexOfConstraint, curel, curdim, V0, myTabPoints->Value(j + k));
IndexOfConstraint += NgPC1;
}
j += 3;
n0 += Ng3d;
}
n0 = NPass + NBeg2d;
for (pnt = 1; pnt <= myNbP2d; pnt++)
{
IndexOfConstraint = n0;
for (k = 1; k <= 2; k++)
{
curdim++;
A.AddConstraint(IndexOfConstraint, curel, curdim, V0, myTabPoints->Value(j + k));
IndexOfConstraint += NgPC1;
}
j += 2;
n0 += Ng2d;
}
/* if(TypOfConstr == 1) {
IndexOfConstraint = NTang3d + 1;
jt = Ntheta * (i - 1);
for(pnt = 1; pnt <= myNbP3d; pnt++) {
for(k = 1; k <= 3; k++) {
A.AddConstraint(IndexOfConstraint, curel, k, myTtheta->Value(jt + k) * V1, 0.);
A.AddConstraint(IndexOfConstraint + 1, curel, k, myTtheta->Value(jt + 3 + k) * V1, 0.);
}
IndexOfConstraint += Ng3d;
jt += 6;
}
IndexOfConstraint = NBeg2d + NTang2d + 1;
for(pnt = 1; pnt <= myNbP2d; pnt++) {
for(k = 1; k <= 2; k++) {
A.AddConstraint(IndexOfConstraint, curel, k, myTtheta->Value(jt + k) * V1, 0.);
}
IndexOfConstraint += Ng2d;
jt += 2;
}
NTang3d += 2;
NTang2d += 1;
} */
if (TypOfConstr == 1)
{
NPass++;
n0 = NPass;
j = 2 * NbDim * (i - 1);
curdim = 0;
for (pnt = 1; pnt <= myNbP3d; pnt++)
{
IndexOfConstraint = n0;
for (k = 1; k <= 3; k++)
{
curdim++;
A.AddConstraint(IndexOfConstraint,
curel,
curdim,
V1,
CBLONG * myTabConstraints->Value(j + k));
IndexOfConstraint += NgPC1;
}
n0 += Ng3d;
j += 6;
}
n0 = NPass + NBeg2d;
for (pnt = 1; pnt <= myNbP2d; pnt++)
{
IndexOfConstraint = n0;
for (k = 1; k <= 2; k++)
{
curdim++;
A.AddConstraint(IndexOfConstraint,
curel,
curdim,
V1,
CBLONG * myTabConstraints->Value(j + k));
IndexOfConstraint += NgPC1;
}
n0 += Ng2d;
j += 4;
}
}
if (TypOfConstr == 2)
{
NPass++;
n0 = NPass;
j = 2 * NbDim * (i - 1);
curdim = 0;
for (pnt = 1; pnt <= myNbP3d; pnt++)
{
IndexOfConstraint = n0;
for (k = 1; k <= 3; k++)
{
curdim++;
A.AddConstraint(IndexOfConstraint,
curel,
curdim,
V1,
CBLONG * myTabConstraints->Value(j + k));
IndexOfConstraint += NgPC1;
}
n0 += Ng3d;
j += 6;
}
n0 = NPass + NBeg2d;
for (pnt = 1; pnt <= myNbP2d; pnt++)
{
IndexOfConstraint = n0;
for (k = 1; k <= 2; k++)
{
curdim++;
A.AddConstraint(IndexOfConstraint,
curel,
curdim,
V1,
CBLONG * myTabConstraints->Value(j + k));
IndexOfConstraint += NgPC1;
}
n0 += Ng2d;
j += 4;
}
j = 2 * NbDim * (i - 1) + 3;
jt = Ntheta * (i - 1);
IndexOfConstraint = NTang3d + 1;
curdim = 0;
for (pnt = 1; pnt <= myNbP3d; pnt++)
{
R1 = 0.;
R2 = 0.;
for (k = 1; k <= 3; k++)
{
R1 += myTabConstraints->Value(j + k) * myTtheta->Value(jt + k);
R2 += myTabConstraints->Value(j + k) * myTtheta->Value(jt + 3 + k);
}
R1 *= CBLONG * CBLONG;
R2 *= CBLONG * CBLONG;
for (k = 1; k <= 3; k++)
{
curdim++;
if (k > 1)
R1 = R2 = 0.;
A.AddConstraint(IndexOfConstraint, curel, curdim, myTfthet->Value(jt + k) * V2, R1);
A.AddConstraint(IndexOfConstraint + 1,
curel,
curdim,
myTfthet->Value(jt + 3 + k) * V2,
R2);
}
IndexOfConstraint += Ng3d;
j += 6;
jt += 6;
}
j--;
IndexOfConstraint = NBeg2d + NTang2d + 1;
for (pnt = 1; pnt <= myNbP2d; pnt++)
{
R1 = 0.;
for (k = 1; k <= 2; k++)
{
R1 += myTabConstraints->Value(j + k) * myTtheta->Value(jt + k);
}
R1 *= CBLONG * CBLONG;
for (k = 1; k <= 2; k++)
{
curdim++;
if (k > 1)
R1 = 0.;
A.AddConstraint(IndexOfConstraint, curel, curdim, myTfthet->Value(jt + k) * V2, R1);
}
IndexOfConstraint += Ng2d;
j += 4;
jt += 2;
}
NTang3d += 2;
NTang2d += 1;
}
}
}
Standard_Boolean AppDef_Variational::InitTthetaF(const Standard_Integer ndimen,
const AppParCurves_Constraint typcon,
const Standard_Integer begin,
const Standard_Integer jndex)
{
if ((ndimen < 2) || (ndimen > 3))
return Standard_False;
gp_Vec T, V;
gp_Vec theta1, theta2;
gp_Vec F;
Standard_Real XX, XY, YY, XZ, YZ, ZZ;
if ((typcon == AppParCurves_TangencyPoint) || (typcon == AppParCurves_CurvaturePoint))
{
T.SetX(myTabConstraints->Value(jndex));
T.SetY(myTabConstraints->Value(jndex + 1));
if (ndimen == 3)
T.SetZ(myTabConstraints->Value(jndex + 2));
else
T.SetZ(0.);
if (ndimen == 2)
{
V.SetX(0.);
V.SetY(0.);
V.SetZ(1.);
}
if (ndimen == 3)
if (!NotParallel(T, V))
return Standard_False;
theta1 = V ^ T;
theta1.Normalize();
myTtheta->SetValue(begin, theta1.X());
myTtheta->SetValue(begin + 1, theta1.Y());
if (ndimen == 3)
{
theta2 = T ^ theta1;
theta2.Normalize();
myTtheta->SetValue(begin + 2, theta1.Z());
myTtheta->SetValue(begin + 3, theta2.X());
myTtheta->SetValue(begin + 4, theta2.Y());
myTtheta->SetValue(begin + 5, theta2.Z());
}
// Calculation of myTfthet
if (typcon == AppParCurves_CurvaturePoint)
{
XX = Pow(T.X(), 2);
XY = T.X() * T.Y();
YY = Pow(T.Y(), 2);
if (ndimen == 2)
{
F.SetX(YY * theta1.X() - XY * theta1.Y());
F.SetY(XX * theta1.Y() - XY * theta1.X());
myTfthet->SetValue(begin, F.X());
myTfthet->SetValue(begin + 1, F.Y());
}
if (ndimen == 3)
{
XZ = T.X() * T.Z();
YZ = T.Y() * T.Z();
ZZ = Pow(T.Z(), 2);
F.SetX((ZZ + YY) * theta1.X() - XY * theta1.Y() - XZ * theta1.Z());
F.SetY((XX + ZZ) * theta1.Y() - XY * theta1.X() - YZ * theta1.Z());
F.SetZ((XX + YY) * theta1.Z() - XZ * theta1.X() - YZ * theta1.Y());
myTfthet->SetValue(begin, F.X());
myTfthet->SetValue(begin + 1, F.Y());
myTfthet->SetValue(begin + 2, F.Z());
F.SetX((ZZ + YY) * theta2.X() - XY * theta2.Y() - XZ * theta2.Z());
F.SetY((XX + ZZ) * theta2.Y() - XY * theta2.X() - YZ * theta2.Z());
F.SetZ((XX + YY) * theta2.Z() - XZ * theta2.X() - YZ * theta2.Y());
myTfthet->SetValue(begin + 3, F.X());
myTfthet->SetValue(begin + 4, F.Y());
myTfthet->SetValue(begin + 5, F.Z());
}
}
}
return Standard_True;
}