Warning, /include/opencascade/AppParCurves_BSpGradient.gxx is written in an unsupported language. File is not indexed.
0001 // Copyright (c) 1995-1999 Matra Datavision
0002 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014
0015 // lpa, le 11/09/91
0016
0017
0018 // Application de la methode du gradient corrige pour minimiser
0019 // F = somme(||C(ui, Poles(ui)) - ptli||2.
0020 // La methode de gradient conjugue est programmee dans la bibliotheque
0021 // mathematique: math_BFGS.
0022
0023
0024 #define No_Standard_RangeError
0025 #define No_Standard_OutOfRange
0026
0027 #include <AppParCurves_Constraint.hxx>
0028 #include <AppParCurves_ConstraintCouple.hxx>
0029 #include <math_BFGS.hxx>
0030 #include <StdFail_NotDone.hxx>
0031 #include <AppParCurves_MultiPoint.hxx>
0032 #include <gp_Pnt.hxx>
0033 #include <gp_Pnt2d.hxx>
0034 #include <gp_Vec.hxx>
0035 #include <gp_Vec2d.hxx>
0036 #include <TColgp_Array1OfPnt.hxx>
0037 #include <TColgp_Array1OfPnt2d.hxx>
0038 #include <TColgp_Array1OfVec.hxx>
0039 #include <TColgp_Array1OfVec2d.hxx>
0040
0041 static AppParCurves_Constraint FirstConstraint
0042 (const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
0043 const Standard_Integer FirstPoint)
0044 {
0045 Standard_Integer i, myindex;
0046 Standard_Integer low = TheConstraints->Lower(), upp= TheConstraints->Upper();
0047 AppParCurves_ConstraintCouple mycouple;
0048 AppParCurves_Constraint Cons = AppParCurves_NoConstraint;
0049
0050 for (i = low; i <= upp; i++) {
0051 mycouple = TheConstraints->Value(i);
0052 Cons = mycouple.Constraint();
0053 myindex = mycouple.Index();
0054 if (myindex == FirstPoint) {
0055 break;
0056 }
0057 }
0058 return Cons;
0059 }
0060
0061
0062 static AppParCurves_Constraint LastConstraint
0063 (const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
0064 const Standard_Integer LastPoint)
0065 {
0066 Standard_Integer i, myindex;
0067 Standard_Integer low = TheConstraints->Lower(), upp= TheConstraints->Upper();
0068 AppParCurves_ConstraintCouple mycouple;
0069 AppParCurves_Constraint Cons = AppParCurves_NoConstraint;
0070
0071 for (i = low; i <= upp; i++) {
0072 mycouple = TheConstraints->Value(i);
0073 Cons = mycouple.Constraint();
0074 myindex = mycouple.Index();
0075 if (myindex == LastPoint) {
0076 break;
0077 }
0078 }
0079 return Cons;
0080 }
0081
0082
0083
0084
0085
0086 AppParCurves_BSpGradient::
0087 AppParCurves_BSpGradient(const MultiLine& SSP,
0088 const Standard_Integer FirstPoint,
0089 const Standard_Integer LastPoint,
0090 const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
0091 math_Vector& Parameters,
0092 const TColStd_Array1OfReal& Knots,
0093 const TColStd_Array1OfInteger& Mults,
0094 const Standard_Integer Deg,
0095 const Standard_Real Tol3d,
0096 const Standard_Real Tol2d,
0097 const Standard_Integer NbIterations):
0098 ParError(FirstPoint, LastPoint,0.0),
0099 mylambda1(0.0),
0100 mylambda2(0.0),
0101 myIsLambdaDefined(Standard_False)
0102 {
0103 Perform(SSP, FirstPoint, LastPoint, TheConstraints, Parameters,
0104 Knots, Mults, Deg, Tol3d, Tol2d, NbIterations);
0105 }
0106
0107
0108 AppParCurves_BSpGradient::
0109 AppParCurves_BSpGradient(const MultiLine& SSP,
0110 const Standard_Integer FirstPoint,
0111 const Standard_Integer LastPoint,
0112 const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
0113 math_Vector& Parameters,
0114 const TColStd_Array1OfReal& Knots,
0115 const TColStd_Array1OfInteger& Mults,
0116 const Standard_Integer Deg,
0117 const Standard_Real Tol3d,
0118 const Standard_Real Tol2d,
0119 const Standard_Integer NbIterations,
0120 const Standard_Real lambda1,
0121 const Standard_Real lambda2):
0122 ParError(FirstPoint, LastPoint,0.0),
0123 mylambda1(lambda1),
0124 mylambda2(lambda2),
0125 myIsLambdaDefined(Standard_True)
0126 {
0127 Perform(SSP, FirstPoint, LastPoint, TheConstraints, Parameters,
0128 Knots, Mults, Deg, Tol3d, Tol2d, NbIterations);
0129 }
0130
0131
0132
0133
0134
0135
0136
0137 void AppParCurves_BSpGradient::
0138 Perform(const MultiLine& SSP,
0139 const Standard_Integer FirstPoint,
0140 const Standard_Integer LastPoint,
0141 const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
0142 math_Vector& Parameters,
0143 const TColStd_Array1OfReal& Knots,
0144 const TColStd_Array1OfInteger& Mults,
0145 const Standard_Integer Deg,
0146 const Standard_Real Tol3d,
0147 const Standard_Real Tol2d,
0148 const Standard_Integer NbIterations)
0149 {
0150
0151 // Standard_Boolean grad = Standard_True;
0152 Standard_Integer i, j, k, i2, l;
0153 Standard_Real UF, DU, Fval = 0.0, FU, DFU;
0154 Standard_Integer nbP3d = ToolLine::NbP3d(SSP);
0155 Standard_Integer nbP2d = ToolLine::NbP2d(SSP);
0156 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
0157 Standard_Integer nbP = nbP3d + nbP2d;
0158 // gp_Pnt Pt, P1, P2;
0159 gp_Pnt Pt;
0160 // gp_Pnt2d Pt2d, P12d, P22d;
0161 gp_Pnt2d Pt2d;
0162 // gp_Vec V1, V2, MyV;
0163 gp_Vec V1, MyV;
0164 // gp_Vec2d V12d, V22d, MyV2d;
0165 gp_Vec2d V12d, MyV2d;
0166 Done = Standard_False;
0167
0168 if (nbP3d == 0) mynbP3d = 1;
0169 if (nbP2d == 0) mynbP2d = 1;
0170 TColgp_Array1OfPnt TabP(1, mynbP3d);
0171 TColgp_Array1OfPnt2d TabP2d(1, mynbP2d);
0172 TColgp_Array1OfVec TabV(1, mynbP3d);
0173 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
0174
0175 // Calcul de la fonction F= somme(||C(ui)-Ptli||2):
0176 // Appel a une fonction heritant de MultipleVarFunctionWithGradient
0177 // pour calculer F et grad_F.
0178 // ================================================================
0179
0180 Standard_Integer nbpoles = -Deg -1;
0181 for (i = Mults.Lower() ;i <= Mults.Upper(); i++) {
0182 nbpoles += Mults(i);
0183 }
0184
0185 TColgp_Array1OfPnt TabPole(1, nbpoles);
0186 TColgp_Array1OfPnt2d TabPole2d(1, nbpoles);
0187 TColgp_Array1OfPnt ThePoles(1, (nbpoles)*mynbP3d);
0188 TColgp_Array1OfPnt2d ThePoles2d(1, (nbpoles)*mynbP2d);
0189
0190
0191 AppParCurves_Constraint
0192 FirstCons = FirstConstraint(TheConstraints, FirstPoint),
0193 LastCons = LastConstraint(TheConstraints, LastPoint);
0194
0195
0196 AppParCurves_BSpParFunction MyF(SSP, FirstPoint,LastPoint, TheConstraints,
0197 Parameters, Knots, Mults, nbpoles);
0198
0199
0200
0201 if (FirstCons >= AppParCurves_TangencyPoint ||
0202 LastCons >= AppParCurves_TangencyPoint) {
0203
0204 if (!myIsLambdaDefined) {
0205 AppParCurves_BSpParLeastSquare thefitt(SSP, Knots, Mults, FirstPoint,
0206 LastPoint, FirstCons, LastCons,
0207 Parameters, nbpoles);
0208 if (FirstCons >= AppParCurves_TangencyPoint) {
0209 mylambda1 = thefitt.FirstLambda();
0210 MyF.SetFirstLambda(mylambda1);
0211 }
0212 if (LastCons >= AppParCurves_TangencyPoint) {
0213 mylambda2 = thefitt.LastLambda();
0214 MyF.SetLastLambda(mylambda2);
0215 }
0216 }
0217 else {
0218 MyF.SetFirstLambda(mylambda1);
0219 MyF.SetLastLambda(mylambda2);
0220 }
0221 }
0222
0223
0224 MyF.Value(Parameters, Fval);
0225 MError3d = MyF.MaxError3d();
0226 MError2d = MyF.MaxError2d();
0227 SCU = MyF.CurveValue();
0228
0229 if (MError3d > Tol3d || MError2d > Tol2d) {
0230
0231 // Stockage des Poles des courbes pour projeter:
0232 // ============================================
0233 i2 = 0;
0234 for (k = 1; k <= nbP3d; k++) {
0235 SCU.Curve(k, TabPole);
0236 for (j=1; j<=nbpoles; j++) ThePoles(j+i2) = TabPole(j);
0237 i2 += nbpoles;
0238 }
0239 i2 = 0;
0240 for (k = 1; k <= nbP2d; k++) {
0241 SCU.Curve(nbP3d+k, TabPole2d);
0242 for (j=1; j<=nbpoles; j++) ThePoles2d(j+i2) = TabPole2d(j);
0243 i2 += nbpoles;
0244 }
0245
0246 // Une iteration rapide de projection est faite par la methode de
0247 // Rogers & Fog 89, methode equivalente a Hoschek 88 qui ne necessite pas
0248 // le calcul de D2.
0249
0250 const math_Matrix& A = MyF.FunctionMatrix();
0251 const math_Matrix& DA = MyF.DerivativeFunctionMatrix();
0252 const math_IntegerVector& Index = MyF.Index();
0253 Standard_Real aa, da, a, b, c, d , e , f, px, py, pz;
0254 Standard_Integer indexdeb, indexfin;
0255
0256 for (j = FirstPoint+1; j <= LastPoint-1; j++) {
0257
0258 UF = Parameters(j);
0259 if (nbP3d != 0 && nbP2d != 0) ToolLine::Value(SSP, j, TabP, TabP2d);
0260 else if (nbP2d != 0) ToolLine::Value(SSP, j, TabP2d);
0261 else ToolLine::Value(SSP, j, TabP);
0262
0263 FU = 0.0;
0264 DFU = 0.0;
0265 i2 = 0;
0266
0267 indexdeb = Index(j) + 1;
0268 indexfin = indexdeb + Deg;
0269
0270 for (k = 1; k <= nbP3d; k++) {
0271 a = b = c = d = e = f = 0.0;
0272 for (l = indexdeb; l <= indexfin; l++) {
0273 Pt = ThePoles(l+i2);
0274 px = Pt.X(); py = Pt.Y(); pz = Pt.Z();
0275 aa = A(j, l); da = DA(j, l);
0276 a += aa* px; d += da* px;
0277 b += aa* py; e += da* py;
0278 c += aa* pz; f += da* pz;
0279 }
0280 Pt.SetCoord(a, b, c);
0281 V1.SetCoord(d, e, f);
0282 i2 += nbpoles;
0283
0284 MyV = gp_Vec(Pt, TabP(k));
0285 FU += MyV*V1;
0286 DFU += V1.SquareMagnitude();
0287 }
0288 i2 = 0;
0289 for (k = 1; k <= nbP2d; k++) {
0290 a = b = d = e = 0.0;
0291 for (l = indexdeb; l <= indexfin; l++) {
0292 Pt2d = ThePoles2d(l+i2);
0293 px = Pt2d.X(); py = Pt2d.Y();
0294 aa = A(j, l); da = DA(j, l);
0295 a += aa* px; d += da* px;
0296 b += aa* py; e += da* py;
0297 }
0298 Pt2d.SetCoord(a, b);
0299 V12d.SetCoord(d, e);
0300 i2 += nbpoles;
0301
0302 MyV2d = gp_Vec2d(Pt2d, TabP2d(k));
0303 FU += MyV2d*V12d;
0304 DFU += V12d.SquareMagnitude();
0305 }
0306
0307 if (DFU >= RealEpsilon()) {
0308 DU = FU/DFU;
0309 DU = Sign(Min(5.e-02, Abs(DU)), DU);
0310 UF += DU;
0311 Parameters(j) = UF;
0312 }
0313 }
0314
0315 MyF.Value(Parameters, Fval);
0316 MError3d = MyF.MaxError3d();
0317 MError2d = MyF.MaxError2d();
0318 }
0319
0320
0321 if (MError3d<= Tol3d && MError2d <= Tol2d) {
0322 Done = Standard_True;
0323 }
0324 else if (NbIterations != 0) {
0325 // NbIterations de gradient conjugue:
0326 // =================================
0327 Standard_Real Eps = 1.e-07;
0328 AppParCurves_BSpGradient_BFGS FResol(MyF, Parameters, Tol3d,
0329 Tol2d, Eps, NbIterations);
0330 }
0331
0332 SCU = MyF.CurveValue();
0333
0334
0335 AvError = 0.;
0336 for (j = FirstPoint; j <= LastPoint; j++) {
0337 Parameters(j) = MyF.NewParameters()(j);
0338 // Recherche des erreurs maxi et moyenne a un index donne:
0339 for (k = 1; k <= nbP; k++) {
0340 ParError(j) = Max(ParError(j), MyF.Error(j, k));
0341 }
0342 AvError += ParError(j);
0343 }
0344 AvError = AvError/(LastPoint-FirstPoint+1);
0345
0346
0347 MError3d = MyF.MaxError3d();
0348 MError2d = MyF.MaxError2d();
0349 if (MError3d <= Tol3d && MError2d <= Tol2d) {
0350 Done = Standard_True;
0351 }
0352
0353 }
0354
0355
0356
0357 AppParCurves_MultiBSpCurve AppParCurves_BSpGradient::Value() const {
0358 return SCU;
0359 }
0360
0361
0362 Standard_Boolean AppParCurves_BSpGradient::IsDone() const {
0363 return Done;
0364 }
0365
0366
0367 Standard_Real AppParCurves_BSpGradient::Error(const Standard_Integer Index) const {
0368 return ParError(Index);
0369 }
0370
0371 Standard_Real AppParCurves_BSpGradient::AverageError() const {
0372 return AvError;
0373 }
0374
0375 Standard_Real AppParCurves_BSpGradient::MaxError3d() const {
0376 return MError3d;
0377 }
0378
0379 Standard_Real AppParCurves_BSpGradient::MaxError2d() const {
0380 return MError2d;
0381 }
0382
0383