b311480e |
1 | // Created on: 1995-03-14 |
2 | // Created by: Modelistation |
3 | // Copyright (c) 1995-1999 Matra Datavision |
4 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
5 | // |
6 | // The content of this file is subject to the Open CASCADE Technology Public |
7 | // License Version 6.5 (the "License"). You may not use the content of this file |
8 | // except in compliance with the License. Please obtain a copy of the License |
9 | // at http://www.opencascade.org and read it completely before using this file. |
10 | // |
11 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
12 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
13 | // |
14 | // The Original Code and all software distributed under the License is |
15 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
16 | // Initial Developer hereby disclaims all such warranties, including without |
17 | // limitation, any warranties of merchantability, fitness for a particular |
18 | // purpose or non-infringement. Please see the License for the specific terms |
19 | // and conditions governing the rights and limitations under the License. |
20 | |
7fd59977 |
21 | |
22 | |
23 | #ifndef DEB |
24 | #define No_Standard_OutOfRange |
25 | #define No_Standard_RangeError |
26 | #endif |
27 | |
28 | |
29 | |
30 | #include <math.hxx> |
31 | #include <math_Vector.hxx> |
32 | #include <math_Matrix.hxx> |
33 | #include <TColgp_Array1OfPnt.hxx> |
34 | #include <TColgp_Array1OfPnt2d.hxx> |
35 | #include <gp_Pnt2d.hxx> |
36 | #include <gp_Pnt.hxx> |
37 | #include <gp_Vec.hxx> |
38 | #include <gp_Vec2d.hxx> |
39 | #include <TColgp_Array1OfVec.hxx> |
40 | #include <TColgp_Array1OfVec2d.hxx> |
41 | #include <AppParCurves_MultiPoint.hxx> |
42 | #include <AppCont_ContMatrices.hxx> |
43 | #include <PLib.hxx> |
44 | |
45 | |
46 | |
47 | |
48 | //======================================================================= |
49 | //function : AppCont_LeastSquare |
50 | //purpose : |
51 | //======================================================================= |
52 | |
53 | AppCont_LeastSquare::AppCont_LeastSquare |
54 | (const MultiLine& SSP, |
55 | const Standard_Real U0, |
56 | const Standard_Real U1, |
57 | const AppParCurves_Constraint FirstCons, |
58 | const AppParCurves_Constraint LastCons, |
59 | const Standard_Integer Deg, |
60 | const Standard_Integer NbPoints): |
61 | SCU(Deg+1), |
62 | Points(1, NbPoints, 1, NbBColumns(SSP)), |
63 | Poles(1, Deg+1, 1, NbBColumns(SSP), 0.0), |
64 | myParam(1, NbPoints), |
65 | VB(1, Deg+1, 1, NbPoints) |
66 | |
67 | { |
68 | Done = Standard_False; |
69 | Degre = Deg; |
70 | math_Matrix InvM(1, Deg+1, 1, Deg+1); |
71 | Standard_Integer i, j, k, c, i2; |
72 | Standard_Integer classe = Deg+1, cl1 = Deg; |
73 | Standard_Real U, dU, Coeff, Coeff2; |
74 | Standard_Real IBij, IBPij; |
75 | |
76 | Standard_Integer FirstP = 1, LastP = NbPoints; |
77 | Standard_Integer nbcol = NbBColumns(SSP); |
78 | math_Matrix B(1, classe, 1, nbcol, 0.0); |
79 | Standard_Integer bdeb = 1, bfin = classe; |
80 | AppParCurves_Constraint myFirstC = FirstCons, myLastC = LastCons; |
81 | nbP = LineTool::NbP3d(SSP); |
82 | nbP2d = LineTool::NbP2d(SSP); |
83 | Standard_Integer mynbP = nbP, mynbP2d = nbP2d; |
84 | if (nbP == 0) mynbP = 1; |
85 | if (nbP2d == 0) mynbP2d = 1; |
86 | |
87 | Standard_Integer i2plus1, i2plus2; |
88 | Nbdiscret = NbPoints; |
89 | TColgp_Array1OfPnt TabP(1, mynbP); |
90 | TColgp_Array1OfVec TabV(1, mynbP); |
91 | TColgp_Array1OfPnt2d TabP2d(1, mynbP2d); |
92 | TColgp_Array1OfVec2d TabV2d(1, mynbP2d); |
93 | |
94 | Standard_Boolean Ok; |
95 | if (myFirstC == AppParCurves_TangencyPoint) { |
96 | if (nbP != 0 && nbP2d != 0) Ok=LineTool::D1(SSP, U0, TabV, TabV2d); |
97 | else if (nbP != 0) Ok=LineTool::D1(SSP, U0, TabV); |
98 | else Ok=LineTool::D1(SSP, U0, TabV2d); |
99 | if (!Ok) myFirstC = AppParCurves_PassPoint; |
100 | } |
101 | |
102 | if (myLastC == AppParCurves_TangencyPoint) { |
103 | if (nbP != 0 && nbP2d != 0) Ok=LineTool::D1(SSP, U1, TabV, TabV2d); |
104 | else if (nbP != 0) Ok=LineTool::D1(SSP, U1, TabV); |
105 | else Ok=LineTool::D1(SSP, U1, TabV2d); |
106 | if (!Ok) myLastC = AppParCurves_PassPoint; |
107 | } |
108 | |
109 | math_Vector GaussP(1, NbPoints), GaussW(1, NbPoints); |
110 | math::GaussPoints(NbPoints, GaussP); |
111 | math::GaussWeights(NbPoints, GaussW); |
112 | |
113 | math_Vector TheWeights(1, NbPoints), VBParam(1, NbPoints); |
114 | |
115 | dU = 0.5*(U1-U0); |
116 | |
117 | // calcul et mise en ordre des parametres et des poids: |
118 | for (i = FirstP; i <= LastP; i++) { |
119 | U = 0.5*(U1+U0) + dU*GaussP(i); |
120 | if (i <= (NbPoints+1)/2) { |
121 | myParam(LastP-i+1) = U; |
122 | VBParam(LastP-i+1) = 0.5*(1 + GaussP(i)); |
123 | TheWeights(LastP-i+1) = 0.5*GaussW(i); |
124 | } |
125 | else { |
126 | VBParam(i-(NbPoints+1)/2) = 0.5*(1 + GaussP(i)); |
127 | myParam(i-(NbPoints+1)/2) = U; |
128 | TheWeights(i-(NbPoints+1)/2) = 0.5*GaussW(i); |
129 | } |
130 | } |
131 | |
132 | |
133 | for (i = FirstP; i <= LastP; i++) { |
134 | U = myParam(i); |
135 | if (nbP != 0 && nbP2d != 0) LineTool::Value(SSP, U, TabP, TabP2d); |
136 | else if (nbP != 0) LineTool::Value(SSP, U, TabP); |
137 | else LineTool::Value(SSP, U, TabP2d); |
138 | |
139 | i2 = 1; |
140 | for (j = 1; j <= nbP; j++) { |
141 | (TabP(j)).Coord(Points(i, i2), Points(i, i2+1), Points(i, i2+2)); |
142 | i2 += 3; |
143 | } |
144 | for (j = 1; j <= nbP2d; j++) { |
145 | (TabP2d(j)).Coord(Points(i, i2), Points(i, i2+1)); |
146 | i2 += 2; |
147 | } |
148 | } |
149 | |
150 | // Calcul du VB ( Valeur des fonctions de Bernstein): |
151 | |
152 | // for (i = 1; i <= classe; i++) { |
153 | // for (j = 1; j <= NbPoints; j++) { |
154 | // VB(i,j)=PLib::Binomial(cl1,i-1)*Pow((1-VBParam(j)),classe-i)* |
155 | // Pow(VBParam(j),i-1); |
156 | // } |
157 | // } |
158 | |
159 | VBernstein(classe, NbPoints, VB); |
160 | |
161 | // Traitement du second membre: |
162 | |
163 | Standard_Real *tmppoints, *tmpbis; |
164 | tmppoints = new Standard_Real[nbcol]; |
165 | |
166 | for (c = 1; c <= classe; c++) { |
167 | tmpbis = tmppoints; |
168 | for (k = 1; k <= nbcol; k++, tmpbis++) { |
169 | *tmpbis = 0.0; |
170 | } |
171 | for (i = 1; i <= NbPoints; i++) { |
172 | Coeff = TheWeights(i)*VB(c, i); |
173 | tmpbis = tmppoints; |
174 | for (j = 1; j <= nbcol; j++, tmpbis++) { |
175 | *tmpbis += Points(i, j)*Coeff; |
176 | //B(c, j) += Points(i, j)*Coeff; |
177 | } |
178 | } |
179 | tmpbis = tmppoints; |
180 | for (k = 1; k <= nbcol; k++, tmpbis++) { |
181 | B(c, k) += *tmpbis; |
182 | } |
183 | } |
184 | |
185 | delete [] tmppoints; |
186 | |
187 | if (myFirstC == AppParCurves_NoConstraint && |
188 | myLastC == AppParCurves_NoConstraint) { |
189 | |
190 | math_Matrix InvM(1, classe, 1, classe); |
191 | InvMMatrix(classe, InvM); |
192 | // Calcul direct des poles: |
193 | |
194 | for (i = 1; i <= classe; i++) { |
195 | for (j = 1; j <= classe; j++) { |
196 | IBij = InvM(i, j); |
197 | for (k = 1; k <= nbcol; k++) { |
198 | Poles(i, k) += IBij * B(j, k); |
199 | } |
200 | } |
201 | } |
202 | } |
203 | |
204 | |
205 | else { |
206 | math_Matrix M(1, classe, 1, classe); |
207 | MMatrix(classe, M); |
208 | |
209 | if (myFirstC == AppParCurves_PassPoint || |
210 | myFirstC == AppParCurves_TangencyPoint) { |
211 | |
212 | if (nbP != 0 && nbP2d != 0) LineTool::Value(SSP, U0, TabP, TabP2d); |
213 | else if (nbP != 0) LineTool::Value(SSP, U0, TabP); |
214 | else LineTool::Value(SSP, U0, TabP2d); |
215 | i2 =1; |
216 | for (k = 1; k<= nbP; k++) { |
217 | (TabP(k)).Coord(Poles(1, i2), Poles(1, i2+1), Poles(1, i2+2)); |
218 | i2 += 3; |
219 | } |
220 | for (k = 1; k<= nbP2d; k++) { |
221 | (TabP2d(k)).Coord(Poles(1, i2), Poles(1, i2+1)); |
222 | i2 += 2; |
223 | } |
224 | |
225 | } |
226 | |
227 | if (myLastC == AppParCurves_PassPoint || |
228 | myLastC == AppParCurves_TangencyPoint) { |
229 | |
230 | i2 = 1; |
231 | if (nbP != 0 && nbP2d != 0) LineTool::Value(SSP, U1, TabP, TabP2d); |
232 | else if (nbP != 0) LineTool::Value(SSP, U1, TabP); |
233 | else LineTool::Value(SSP, U1, TabP2d); |
234 | for (k = 1; k<= nbP; k++) { |
235 | (TabP(k)).Coord(Poles(classe,i2), |
236 | Poles(classe,i2+1), |
237 | Poles(classe,i2+2)); |
238 | i2 += 3; |
239 | } |
240 | for (k = 1; k<= nbP2d; k++) { |
241 | (TabP2d(k)).Coord(Poles(classe, i2), Poles(classe, i2+1)); |
242 | i2 += 2; |
243 | } |
244 | } |
245 | |
246 | |
247 | |
248 | if (myFirstC == AppParCurves_PassPoint) { |
249 | bdeb = 2; |
250 | // mise a jour du second membre: |
251 | for (i = 1; i <= classe; i++) { |
252 | Coeff = M(i, 1); |
253 | for (k = 1; k <= nbcol; k++) { |
254 | B(i, k) -= Poles(1, k)*Coeff; |
255 | } |
256 | } |
257 | } |
258 | |
259 | |
260 | if (myLastC == AppParCurves_PassPoint) { |
261 | bfin = cl1; |
262 | for (i = 1; i <= classe; i++) { |
263 | Coeff = M(i, classe); |
264 | for (k = 1; k <= nbcol; k++) { |
265 | B(i, k) -= Poles(classe, k)*Coeff; |
266 | } |
267 | } |
268 | } |
269 | |
270 | |
271 | if (myFirstC == AppParCurves_TangencyPoint) { |
272 | // On fixe le second pole:: |
273 | bdeb = 3; |
274 | if (nbP != 0 && nbP2d != 0) LineTool::D1(SSP, U0, TabV, TabV2d); |
275 | else if (nbP != 0) LineTool::D1(SSP, U0, TabV); |
276 | else LineTool::D1(SSP, U0, TabV2d); |
277 | i2 = 1; |
278 | Coeff = (U1-U0)/Degre; |
279 | for (k = 1; k<= nbP; k++) { |
280 | i2plus1 = i2+1; i2plus2 = i2+2; |
281 | Poles(2, i2) = Poles(1, i2) + TabV(k).X()*Coeff; |
282 | Poles(2, i2plus1) = Poles(1, i2plus1) + TabV(k).Y()*Coeff; |
283 | Poles(2, i2plus2) = Poles(1, i2plus2) + TabV(k).Z()*Coeff; |
284 | i2 += 3; |
285 | } |
286 | for (k = 1; k<= nbP2d; k++) { |
287 | i2plus1 = i2+1; |
288 | Poles(2, i2) = Poles(1, i2) + TabV2d(k).X()*Coeff; |
289 | Poles(2, i2plus1) = Poles(1, i2plus1) + TabV2d(k).Y()*Coeff; |
290 | i2 += 2; |
291 | } |
292 | |
293 | |
294 | for (i = 1; i <= classe; i++) { |
295 | Coeff = M(i, 1); Coeff2 = M(i, 2); |
296 | for (k = 1; k <= nbcol; k++) { |
297 | B(i, k) -= Poles(1, k)*Coeff+Poles(2, k)*Coeff2; |
298 | } |
299 | } |
300 | } |
301 | |
302 | if (myLastC == AppParCurves_TangencyPoint) { |
303 | bfin = classe-2; |
304 | |
305 | if (nbP != 0 && nbP2d != 0) LineTool::D1(SSP, U1, TabV, TabV2d); |
306 | else if (nbP != 0) LineTool::D1(SSP, U1, TabV); |
307 | else LineTool::D1(SSP, U1, TabV2d); |
308 | i2 = 1; |
309 | Coeff = (U1-U0)/Degre; |
310 | for (k = 1; k<= nbP; k++) { |
311 | i2plus1 = i2+1; i2plus2 = i2+2; |
312 | Poles(cl1,i2) = Poles(classe, i2) - TabV(k).X()*Coeff; |
313 | Poles(cl1,i2plus1) = Poles(classe, i2plus1) - TabV(k).Y()*Coeff; |
314 | Poles(cl1,i2plus2) = Poles(classe, i2plus2) - TabV(k).Z()*Coeff; |
315 | i2 += 3; |
316 | } |
317 | for (k = 1; k<= nbP2d; k++) { |
318 | i2plus1 = i2+1; |
319 | Poles(cl1,i2) = Poles(classe, i2) - TabV2d(k).X()*Coeff; |
320 | Poles(cl1,i2plus1) = Poles(classe, i2plus1) - TabV2d(k).Y()*Coeff; |
321 | i2 += 2; |
322 | } |
323 | |
324 | for (i = 1; i <= classe; i++) { |
325 | Coeff = M(i, classe); Coeff2 = M(i, cl1); |
326 | for (k = 1; k <= nbcol; k++) { |
327 | B(i, k) -= Poles(classe, k)*Coeff + Poles(cl1, k)*Coeff2; |
328 | } |
329 | } |
330 | } |
331 | |
332 | if (bdeb <= bfin) { |
333 | math_Matrix B2(bdeb, bfin, 1, B.UpperCol(), 0.0); |
334 | |
335 | for (i = bdeb; i <= bfin; i++) { |
336 | for (j = 1; j <= classe; j++) { |
337 | Coeff = M(i, j); |
338 | for (k = 1; k <= nbcol; k++) { |
339 | B2(i, k) += B(j, k)*Coeff; |
340 | } |
341 | } |
342 | } |
343 | |
344 | |
345 | // Resolution: |
346 | // =========== |
347 | math_Matrix IBP(bdeb, bfin, bdeb, bfin); |
348 | |
349 | // dans IBPMatrix at IBTMatrix ne sont stockees que les resultats pour |
350 | // une classe inferieure ou egale a 26 (pour l instant du moins.) |
351 | |
352 | if (bdeb == 2 && bfin == classe-1 && classe <= 26) { |
353 | IBPMatrix(classe, IBP); |
354 | } |
355 | else if (bdeb == 3 && bfin == classe-2 && classe <= 26) { |
356 | IBTMatrix(classe, IBP); |
357 | } |
358 | else { |
359 | math_Matrix MP(1, classe, bdeb, bfin); |
360 | |
361 | for (i = 1; i <= classe; i++) { |
362 | for (j = bdeb; j <= bfin; j++) { |
363 | MP(i, j) = M(i, j); |
364 | } |
365 | } |
366 | math_Matrix IBP1(bdeb, bfin, bdeb, bfin); |
367 | IBP1 = MP.Transposed()*MP; |
368 | IBP = IBP1.Inverse(); |
369 | } |
370 | |
371 | |
372 | Done = Standard_True; |
373 | for (i = bdeb; i <= bfin; i++) { |
374 | for (j = bdeb; j <= bfin; j++) { |
375 | IBPij = IBP(i, j);; |
376 | for (k = 1; k<= nbcol; k++) { |
377 | Poles(i, k) += IBPij * B2(j, k); |
378 | } |
379 | } |
380 | } |
381 | } |
382 | } |
383 | } |
384 | |
385 | |
386 | |
387 | |
388 | //======================================================================= |
389 | //function : NbBColumns |
390 | //purpose : |
391 | //======================================================================= |
392 | |
393 | Standard_Integer AppCont_LeastSquare::NbBColumns( |
394 | const MultiLine& SSP) const |
395 | { |
396 | Standard_Integer BCol; |
397 | BCol = (LineTool::NbP3d(SSP))*3 + |
398 | (LineTool::NbP2d(SSP))*2; |
399 | return BCol; |
400 | } |
401 | |
402 | |
403 | //======================================================================= |
404 | //function : Value |
405 | //purpose : |
406 | //======================================================================= |
407 | |
408 | const AppParCurves_MultiCurve& AppCont_LeastSquare::Value() |
409 | { |
410 | |
411 | Standard_Integer i, j, j2; |
412 | gp_Pnt Pt; |
413 | gp_Pnt2d Pt2d; |
414 | Standard_Integer ideb = 1, ifin = Degre+1; |
415 | |
416 | // On met le resultat dans les curves correspondantes |
417 | for (i = ideb; i <= ifin; i++) { |
418 | j2 = 1; |
419 | AppParCurves_MultiPoint MPole(nbP, nbP2d); |
420 | for (j = 1; j <= nbP; j++) { |
421 | Pt.SetCoord(Poles(i, j2), Poles(i, j2+1), Poles(i,j2+2)); |
422 | MPole.SetPoint(j, Pt); |
423 | j2 += 3; |
424 | } |
425 | for (j = nbP+1;j <= nbP+nbP2d; j++) { |
426 | Pt2d.SetCoord(Poles(i, j2), Poles(i, j2+1)); |
427 | MPole.SetPoint2d(j, Pt2d); |
428 | j2 += 2; |
429 | } |
430 | SCU.SetValue(i, MPole); |
431 | } |
432 | return SCU; |
433 | } |
434 | |
435 | |
436 | |
437 | //======================================================================= |
438 | //function : Error |
439 | //purpose : |
440 | //======================================================================= |
441 | |
442 | void AppCont_LeastSquare::Error(Standard_Real& F, |
443 | Standard_Real& MaxE3d, |
444 | Standard_Real& MaxE2d) const |
445 | { |
446 | Standard_Integer i, j, k, c, i2, classe = Degre+1; |
447 | // Standard_Real Coeff, val = 0.0, err3d = 0.0, err2d =0.0; |
448 | Standard_Real Coeff, err3d = 0.0, err2d =0.0; |
449 | Standard_Integer ncol = Points.UpperCol()-Points.LowerCol()+1; |
450 | |
451 | math_Matrix MyPoints(1, Nbdiscret, 1, ncol); |
452 | MyPoints = Points; |
453 | |
454 | MaxE3d = MaxE2d = F = 0.0; |
455 | |
456 | Standard_Real *tmppoles, *tmpbis; |
457 | tmppoles = new Standard_Real[ncol]; |
458 | |
459 | for (c = 1; c <= classe; c++) { |
460 | tmpbis = tmppoles; |
461 | for (k = 1; k <= ncol; k++, tmpbis++) { |
462 | *tmpbis = Poles(c, k); |
463 | } |
464 | for (i = 1; i <= Nbdiscret; i++) { |
465 | Coeff = VB(c, i); |
466 | tmpbis = tmppoles; |
467 | for (j = 1; j <= ncol; j++, tmpbis++) { |
468 | MyPoints(i, j) -= (*tmpbis)*Coeff; // Poles(c, j)*Coeff; |
469 | } |
470 | } |
471 | } |
472 | delete [] tmppoles; |
473 | |
474 | Standard_Real e1, e2, e3; |
475 | for (i = 1; i <= Nbdiscret; i++) { |
476 | i2 = 1; |
477 | for (j = 1; j<= nbP; j++) { |
478 | e1 = MyPoints(i, i2); |
479 | e2 = MyPoints(i, i2+1); |
480 | e3 = MyPoints(i, i2+2); |
481 | err3d = e1*e1+e2*e2+e3*e3; |
482 | MaxE3d = Max(MaxE3d, err3d); |
483 | F += err3d; |
484 | i2 += 3; |
485 | } |
486 | for (j = 1; j<= nbP2d; j++) { |
487 | e1 = MyPoints(i, i2); |
488 | e2 = MyPoints(i, i2+1); |
489 | err2d = e1*e1+e2*e2; |
490 | MaxE2d = Max(MaxE2d, err2d); |
491 | F += err2d; |
492 | i2 += 2; |
493 | } |
494 | } |
495 | |
496 | MaxE3d = Sqrt(MaxE3d); |
497 | MaxE2d = Sqrt(MaxE2d); |
498 | |
499 | } |
500 | |
501 | |
502 | //======================================================================= |
503 | //function : IsDone |
504 | //purpose : |
505 | //======================================================================= |
506 | |
507 | Standard_Boolean AppCont_LeastSquare::IsDone() const |
508 | { |
509 | return Done; |
510 | } |