3b8fcee88ba6e140ce3286b6650fa644113c5969
[occt.git] / src / AppParCurves / AppParCurves_Projection.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 // lpa, le 11/09/91
16
17
18
19 #define No_Standard_RangeError
20 #define No_Standard_OutOfRange
21
22 #include <AppParCurves_Constraint.hxx>
23 #include <StdFail_NotDone.hxx>
24 #include <AppParCurves_MultiPoint.hxx>
25 #include <gp_Pnt.hxx>
26 #include <gp_Pnt2d.hxx>
27 #include <gp_Vec.hxx>
28 #include <gp_Vec2d.hxx>
29 #include <TColgp_Array1OfPnt.hxx>
30 #include <TColgp_Array1OfPnt2d.hxx>
31 #include <TColgp_Array1OfVec.hxx>
32 #include <TColgp_Array1OfVec2d.hxx>
33 #include <PLib.hxx>
34 #include <BSplCLib.hxx>
35
36
37
38
39
40 AppParCurves_Projection::
41    AppParCurves_Projection(const MultiLine& SSP,
42          const Standard_Integer FirstPoint,
43          const Standard_Integer LastPoint,
44          const Handle(AppParCurves_HArray1OfConstraintCouple)& TheConstraints,
45          math_Vector& Parameters,
46          const Standard_Integer Deg,
47          const Standard_Real Tol3d,
48          const Standard_Real Tol2d,
49          const Standard_Integer NbIterations):
50          ParError(FirstPoint, LastPoint,0.0) {
51
52   Standard_Boolean grad = Standard_True;
53   Standard_Integer i, j, k, i2, l;
54   Standard_Real UF, DU, Fval = 0.0, FU, DFU;
55   Standard_Real MErr3d=0.0, MErr2d=0.0, 
56                 Gain3d = Tol3d, Gain2d=Tol2d;
57   Standard_Real EC, ECmax = 1.e10, Errsov3d, Errsov2d;
58   Standard_Integer nbP3d = ToolLine::NbP3d(SSP);
59   Standard_Integer nbP2d = ToolLine::NbP2d(SSP);
60   Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
61   Standard_Integer nbP = nbP3d + nbP2d;
62   gp_Pnt Pt, P1, P2;
63   gp_Pnt2d Pt2d, P12d, P22d;
64   gp_Vec V1, V2, MyV;
65   gp_Vec2d V12d, V22d, MyV2d;
66   
67   if (nbP3d == 0) mynbP3d = 1;
68   if (nbP2d == 0) mynbP2d = 1;
69   TColgp_Array1OfPnt TabP(1, mynbP3d);
70   TColgp_Array1OfPnt2d TabP2d(1, mynbP2d);
71   TColgp_Array1OfVec TabV(1, mynbP3d);
72   TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
73
74   // Calcul de la fonction F= somme(||C(ui)-Ptli||2):
75   // Appel a une fonction heritant de MultipleVarFunctionWithGradient
76   // pour calculer F et grad_F.
77   // ================================================================
78
79   AppParCurves_ProFunction MyF(SSP, FirstPoint,LastPoint, TheConstraints, Parameters, Deg);
80
81
82   ECmax = 0.0;
83   // Projection:
84   // ===========
85   MyF.Value(Parameters, Fval);
86   SCU = MyF.CurveValue();
87   Standard_Integer deg = SCU.Degree();
88   TColgp_Array1OfPnt   TabPole(1, deg+1),   TabCoef(1, deg+1);
89   TColgp_Array1OfPnt2d TabPole2d(1, deg+1), TabCoef2d(1, deg+1);
90   TColgp_Array1OfPnt    TheCoef(1, (deg+1)*mynbP3d);
91   TColgp_Array1OfPnt2d  TheCoef2d(1, (deg+1)*mynbP2d);
92
93   
94   for (i = 1; i <= NbIterations; i++) {
95
96     // Stockage des Poles des courbes:
97     // ===============================
98     i2 = 0;
99     for (k = 1; k <= nbP3d; k++) {
100       SCU.Curve(k, TabPole);
101       BSplCLib::PolesCoefficients(TabPole, PLib::NoWeights(),
102                                   TabCoef, PLib::NoWeights());
103       for (j=1; j<=deg+1; j++) TheCoef(j+i2) = TabCoef(j);
104       i2 += deg+1;
105     }
106     i2 = 0;
107     for (k = 1; k <= nbP2d; k++) {
108       SCU.Curve(nbP3d+k, TabPole2d);
109       BSplCLib::PolesCoefficients(TabPole2d, PLib::NoWeights(), 
110                                   TabCoef2d, PLib::NoWeights());
111       for (j=1; j<=deg+1; j++) TheCoef2d(j+i2) = TabCoef2d(j);
112       i2 += deg+1;
113     }
114     for (j = FirstPoint+1; j <= LastPoint-1; j++) {
115       UF = Parameters(j);
116       if (nbP != 0 && nbP2d != 0) ToolLine::Value(SSP, j, TabP, TabP2d);
117       else if (nbP2d != 0)        ToolLine::Value(SSP, j, TabP2d);
118       else                        ToolLine::Value(SSP, j, TabP);
119       
120       FU = 0.0;
121       DFU = 0.0;
122       i2 = 0;
123       for (k = 1; k <= nbP3d; k++) {
124         for (l=1; l<=deg+1; l++) TabCoef(l) = TheCoef(l+i2);
125         i2 += deg+1;
126         BSplCLib::CoefsD2(UF, TabCoef, PLib::NoWeights(), Pt, V1, V2);
127         MyV = gp_Vec(Pt, TabP(k));
128         FU += MyV*V1;
129         DFU += V1.SquareMagnitude() + MyV*V2;
130       }
131       i2 = 0;
132       for (k = 1; k <= nbP2d; k++) {
133         for (l=1; l<=deg+1; l++) TabCoef2d(l) = TheCoef2d(l+i2);
134         i2 += deg+1;
135         BSplCLib::CoefsD2(UF, TabCoef2d, PLib::NoWeights(), Pt2d, V12d, V22d);
136         MyV2d = gp_Vec2d(Pt2d, TabP2d(k));
137         FU += MyV2d*V12d;
138         DFU += V12d.SquareMagnitude() + MyV2d*V22d;
139       }
140
141       if (DFU <= RealEpsilon()) {
142         // Verification du parametrage:
143         EC = Abs(Parameters(j) - UF);
144         if (EC > ECmax) ECmax = EC;
145         break;
146       }
147
148       DU = -FU/DFU;
149       DU = Sign(Min(5.e-02, Abs(DU)), DU);
150       UF += DU;
151       Parameters(j) = UF;
152     }
153
154     // Test de progression:
155     // ====================
156     Errsov3d = MErr3d;
157     Errsov2d = MErr2d;
158
159     MyF.Value(Parameters, Fval);
160     SCU = MyF.CurveValue();
161     MErr3d = MyF.MaxError3d();
162     MErr2d = MyF.MaxError2d();
163
164     if (MErr3d< Tol3d && MErr2d < Tol2d) {
165       Done = Standard_True;
166       break;
167     }
168     if (MErr3d > 100.0*Tol3d || MErr2d > 100.0*Tol2d) {
169       Done = Standard_False;
170       grad = Standard_False;
171       break;
172     }
173     if (i >= 2) {
174       Gain3d = Abs(Errsov3d-MErr3d);
175       Gain2d = Abs(Errsov2d-MErr2d);
176       if ((MErr3d-Gain3d*(NbIterations-i)*0.5) > Tol3d ||
177           (MErr2d-Gain2d*(NbIterations-i)*0.5) > Tol2d) {
178         if (Gain3d < Tol3d/(2*NbIterations) &&
179             Gain2d < Tol2d/(2*NbIterations)) {
180           break;
181         }
182       }
183     }
184
185   }
186
187
188
189   AvError = 0.;
190   for (j = FirstPoint; j <= LastPoint; j++) {  
191     // Recherche des erreurs maxi et moyenne a un index donne:
192     for (k = 1; k <= nbP; k++) {
193       ParError(j) = Max(ParError(j), MyF.Error(j, k));
194     }
195     AvError += ParError(j);
196   }
197   AvError = AvError/(LastPoint-FirstPoint+1);
198
199
200   MError3d = MyF.MaxError3d();
201   MError2d = MyF.MaxError2d();
202   if (MError3d < Tol3d && MError2d < Tol2d) {
203     Done = Standard_True;
204   }
205
206 }
207
208
209
210 AppParCurves_MultiCurve AppParCurves_Projection::Value() const {
211   return SCU;
212 }
213
214
215 Standard_Boolean AppParCurves_Projection::IsDone() const {
216   return Done;
217 }
218
219
220 Standard_Real AppParCurves_Projection::Error(const Standard_Integer Index) const {
221   return ParError(Index);
222 }
223
224 Standard_Real AppParCurves_Projection::AverageError() const {
225   return AvError;
226 }
227
228 Standard_Real AppParCurves_Projection::MaxError3d() const {
229   return MError3d;
230 }
231
232 Standard_Real AppParCurves_Projection::MaxError2d() const {
233   return MError2d;
234 }
235
236