0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / Approx / Approx_ComputeLine.gxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
7fd59977 14
15#include <Approx_ParametrizationType.hxx>
16#include Approx_ParLeastSquareOfMyGradient_hxx
17#include <TColStd_Array1OfReal.hxx>
18#include <TColgp_Array1OfPnt.hxx>
19#include <TColgp_Array1OfPnt2d.hxx>
20#include <gp_Pnt.hxx>
21#include <gp_Pnt2d.hxx>
22#include <gp_Vec.hxx>
23#include <gp_Vec2d.hxx>
24#include <TColgp_Array1OfVec.hxx>
25#include <TColgp_Array1OfVec2d.hxx>
26#include <AppParCurves_Constraint.hxx>
27#include <AppParCurves_HArray1OfConstraintCouple.hxx>
28#include <AppParCurves_MultiPoint.hxx>
29#include <Precision.hxx>
30#include <math_IntegerVector.hxx>
31#include <math_Gauss.hxx>
32#include <math_Uzawa.hxx>
33#include <Approx_MCurvesToBSpCurve.hxx>
34#include <AppParCurves_ConstraintCouple.hxx>
35
36#include <stdio.h>
37
0797d9d3 38#ifdef OCCT_DEBUG
7fd59977 39static Standard_Boolean mydebug = Standard_False;
40
41#include <Geom_BezierCurve.hxx>
42#include <Geom2d_BezierCurve.hxx>
43#ifdef DRAW
44#include <DrawTrSurf.hxx>
45#include <Draw.hxx>
46#include <Draw_Appli.hxx>
47#endif
2c26a53d 48
7fd59977 49static void DUMP(const MultiLine& Line)
50{
51 Standard_Integer i, j, nbP2d, nbP3d, firstP, lastP;
52 gp_Pnt P1;
53 gp_Pnt2d P12d;
54
55 firstP = LineTool::FirstPoint(Line);
56 lastP = LineTool::LastPoint(Line);
57
58 nbP3d = LineTool::NbP3d(Line);
59 nbP2d = LineTool::NbP2d(Line);
60 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
61 if (nbP3d == 0) mynbP3d = 1;
62 if (nbP2d == 0) mynbP2d = 1;
63
64 TColgp_Array1OfPnt tabP(1, mynbP3d);
65 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
66
67 cout <<"DUMP de la MultiLine entre "<<firstP <<" et "<<lastP<<": "<<endl;
68 for (i = firstP; i <= lastP; i++) {
69 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabP, tabP2d);
70 else if (nbP2d != 0) LineTool::Value(Line, i, tabP2d);
71 else if (nbP3d != 0) LineTool::Value(Line, i, tabP);
72
73 cout << "point "<<i<<":"<< endl;
74 for (j = 1; j <= nbP3d; j++) {
75 P1 = tabP(j);
76 cout <<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<endl;
77 }
78 for (j = 1; j <= nbP2d; j++) {
79 P12d = tabP2d(j);
80 cout <<P12d.X()<<" "<<P12d.Y()<<endl;
81 }
82 }
83
84}
85
7fd59977 86static void DUMP(const AppParCurves_MultiCurve& C) {
87 static Standard_Integer nbappel = 0;
88 Standard_Integer i;
89 Standard_Integer nbpoles = C.NbPoles();
7fd59977 90
91 Handle(Geom_BezierCurve) BSp;
92 Handle(Geom2d_BezierCurve) BSp2d;
93
94 TColgp_Array1OfPnt tabPoles(1, nbpoles);
95 TColgp_Array1OfPnt2d tabPoles2d(1, nbpoles);
96 char solname[100];
97
98 nbappel++;
99 for (i = 1; i <= C.NbCurves(); i++) {
100 if (C.Dimension(i) == 3) {
101 C.Curve(i, tabPoles);
102 BSp = new Geom_BezierCurve(tabPoles);
103 sprintf(solname, "%s%i%s_%i", "c", i, "3d", nbappel);
104#ifdef DRAW
105 char* Temp = solname;
106 DrawTrSurf::Set(Temp, BSp);
107// DrawTrSurf::Set(solname, BSp);
108#endif
109 }
110 else {
111 C.Curve(i, tabPoles2d);
112 BSp2d = new Geom2d_BezierCurve(tabPoles2d);
113 sprintf(solname, "%s%i%s_%i", "c", i, "2d", nbappel);
114#ifdef DRAW
115 char* Temp = solname;
116 DrawTrSurf::Set(Temp, BSp2d);
117// DrawTrSurf::Set(solname, BSp2d);
118#endif
119 }
120 }
121#ifdef DRAW
122 dout.Flush();
123#endif
124}
125
2c26a53d 126#endif
127
128static Standard_Boolean CheckMultiCurve(const AppParCurves_MultiCurve& theMultiCurve,
129 const MultiLine& theLine,
130 const Standard_Integer theIndfirst,
131 const Standard_Integer theIndlast,
132 Standard_Integer& theIndbad)
133{
134 const Standard_Integer nbp3d = LineTool::NbP3d(theLine);
135 const Standard_Integer nbp2d = LineTool::NbP2d(theLine);
136
137 if (nbp3d > 1) //only simple cases are analysed
138 return Standard_True;
139
140 const Standard_Real MinScalProd = -0.9;
141 const Standard_Real SqTol3d = Precision::SquareConfusion();
7fd59977 142
2c26a53d 143 theIndbad = 0;
144 Standard_Integer indbads [4];
145 indbads[1] = indbads[2] = indbads[3] = 0;
146
147 Standard_Integer NbCur = theMultiCurve.NbCurves();
148 Standard_Boolean LoopFound = Standard_False;
149
150 Standard_Integer aNbP3d = Max(nbp3d, 1);
151 Standard_Integer aNbP2d = Max(nbp2d, 1);
152
153 TColgp_Array1OfPnt tabP(1, aNbP3d);
154 TColgp_Array1OfPnt2d tabP2d(1, aNbP2d);
155
156#ifdef DRAW
157 char* name = new char[100];
158 Standard_Integer nbbc = 1;
159 Standard_Integer indc = 1;
160#endif
161 if (theMultiCurve.Dimension(1) == 3 /*myNbP3d == 1*/)
162 {
163 TColgp_Array1OfPnt aPoles(1, theMultiCurve.NbPoles());
164 theMultiCurve.Curve(1, aPoles);
165#ifdef DRAW
166 Handle(Geom_Curve) theBezier = new Geom_BezierCurve(aPoles);
167 sprintf(name, "bc3d_%d_%d", indc, nbbc);
168 DrawTrSurf::Set(name, theBezier);
7fd59977 169#endif
2c26a53d 170 gp_Vec FirstVec, SecondVec;
171 Standard_Integer indp = 2;
172 while (indp <= aPoles.Upper())
173 {
174 FirstVec = gp_Vec(aPoles(1), aPoles(indp++));
175 Standard_Real aLength = FirstVec.Magnitude();
176 if (aLength > gp::Resolution())
177 {
178 FirstVec /= aLength;
179 break;
180 }
181 }
182 gp_Pnt MidPnt = aPoles(indp-1);
183 //for (Standard_Integer k = 3; k <= aPoles.Upper(); k++)
184 while (indp <= aPoles.Upper())
185 {
186 SecondVec = gp_Vec(MidPnt, aPoles(indp));
187 Standard_Real aLength = SecondVec.Magnitude();
188 if (aLength <= gp::Resolution())
189 {
190 indp++;
191 continue;
192 }
193 SecondVec /= aLength;
194 Standard_Real ScalProd = FirstVec * SecondVec;
195 if (ScalProd < MinScalProd)
196 {
197#ifdef DRAW
198 cout<<"ScalProd("<<indp-2<<","<<indp-1<<")-("<<indp-1<<","<<indp<<") = "<<ScalProd<<endl;
199#endif
200 LoopFound = Standard_True;
201 break;
202 }
203 FirstVec = SecondVec;
204 MidPnt = aPoles(indp);
205 indp++;
206 }
207 //Check: may be it is a real loop
208 if (LoopFound)
209 {
210 for (Standard_Integer FirstInd = theIndfirst;
211 FirstInd <= theIndlast - 2; FirstInd++)
212 {
213 LineTool::Value(theLine, FirstInd, tabP);
214 gp_Pnt FirstPnt = tabP(1);
215 for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
216 {
217 LineTool::Value(theLine, k, tabP);
218 gp_Pnt Pnt1 = tabP(1);
219 LineTool::Value(theLine, k+1, tabP);
220 gp_Pnt Pnt2 = tabP(1);
221 if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
222 FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
223 {
224 LoopFound = Standard_False;
225 break;
226 }
227 gp_Vec Vec1(FirstPnt, Pnt1);
228 Vec1.Normalize();
229 gp_Vec Vec2(FirstPnt, Pnt2);
230 Vec2.Normalize();
231 Standard_Real ScalProd = Vec1 * Vec2;
232 if (ScalProd < MinScalProd)
233 {
234 LoopFound = Standard_False;
235 break;
236 }
237 }
238 if (LoopFound == Standard_False)
239 break;
240 }
241 }
242 if (LoopFound)
243 {
244 //search <indbad>
245 Standard_Real MaxSqDist = 0.;
246 for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
247 {
248 LineTool::Value(theLine, k-1, tabP);
249 gp_Pnt PrevPnt = tabP(1);
250 LineTool::Value(theLine, k, tabP);
251 gp_Pnt CurPnt = tabP(1);
252 Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
253 if (aSqDist > MaxSqDist)
254 {
255 MaxSqDist = aSqDist;
256 indbads[1] = k;
257 }
258 }
259 for (Standard_Integer indcur = 2; indcur <= NbCur; indcur++)
260 {
261 MaxSqDist = 0.;
262 for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
263 {
264 LineTool::Value(theLine, k-1, tabP2d);
265 gp_Pnt2d PrevPnt = tabP2d(indcur-1);
266 LineTool::Value(theLine, k, tabP2d);
267 gp_Pnt2d CurPnt = tabP2d(indcur-1);
268 Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
269 if (aSqDist > MaxSqDist)
270 {
271 MaxSqDist = aSqDist;
272 indbads[indcur] = k;
273 }
274 }
275 }
276 }
277 } //if (myNbP3d == 1)
278 else //2d case
279 {
280 TColgp_Array1OfPnt2d aPoles2d(1, theMultiCurve.NbPoles());
281 theMultiCurve.Curve(1, aPoles2d);
282#ifdef DRAW
283 Handle(Geom2d_Curve) theBezier2d = new Geom2d_BezierCurve(aPoles2d);
284 sprintf(name, "bc2d_%d_%d", indc, nbbc);
285 DrawTrSurf::Set(name, theBezier2d);
286#endif
287 gp_Vec2d FirstVec, SecondVec;
288 FirstVec = gp_Vec2d(aPoles2d(1), aPoles2d(2));
289 FirstVec.Normalize();
290 gp_Pnt2d MidPnt = aPoles2d(2);
291 for (Standard_Integer k = 3; k <= aPoles2d.Upper(); k++)
292 {
293 SecondVec = gp_Vec2d(MidPnt, aPoles2d(k));
294 SecondVec.Normalize();
295 Standard_Real ScalProd = FirstVec * SecondVec;
296 if (ScalProd < MinScalProd)
297 {
298#ifdef DRAW
299 cout<<"ScalProd("<<k-2<<","<<k-1<<")-("<<k-1<<","<<k<<") = "<<ScalProd<<endl;
300#endif
301 LoopFound = Standard_True;
302 break;
303 }
304 FirstVec = SecondVec;
305 MidPnt = aPoles2d(k);
306 }
307 //Check: may be it is a real loop
308 if (LoopFound)
309 {
310 for (Standard_Integer FirstInd = theIndfirst;
311 FirstInd <= theIndlast - 2; FirstInd++)
312 {
313 LineTool::Value(theLine, FirstInd, tabP2d);
314 gp_Pnt2d FirstPnt = tabP2d(1);
315 for (Standard_Integer k = FirstInd+1; k < theIndlast; k++)
316 {
317 LineTool::Value(theLine, k, tabP2d);
318 gp_Pnt2d Pnt1 = tabP2d(1);
319 LineTool::Value(theLine, k+1, tabP2d);
320 gp_Pnt2d Pnt2 = tabP2d(1);
321 if (FirstPnt.SquareDistance(Pnt1) <= SqTol3d ||
322 FirstPnt.SquareDistance(Pnt2) <= SqTol3d)
323 {
324 LoopFound = Standard_False;
325 break;
326 }
327 gp_Vec2d Vec1(FirstPnt, Pnt1);
328 Vec1.Normalize();
329 gp_Vec2d Vec2(FirstPnt, Pnt2);
330 Vec2.Normalize();
331 Standard_Real ScalProd = Vec1 * Vec2;
332 if (ScalProd < MinScalProd)
333 {
334 LoopFound = Standard_False;
335 break;
336 }
337 }
338 if (LoopFound == Standard_False)
339 break;
340 }
341 }
342 if (LoopFound)
343 {
344 //search <indbad>
345 for (Standard_Integer indcur = 1; indcur <= NbCur; indcur++)
346 {
347 Standard_Real MaxSqDist = 0.;
348 for (Standard_Integer k = theIndfirst+1; k <= theIndlast; k++)
349 {
350 LineTool::Value(theLine, k-1, tabP2d);
351 gp_Pnt2d PrevPnt = tabP2d(indcur);
352 LineTool::Value(theLine, k, tabP2d);
353 gp_Pnt2d CurPnt = tabP2d(indcur);
354 Standard_Real aSqDist = PrevPnt.SquareDistance(CurPnt);
355 if (aSqDist > MaxSqDist)
356 {
357 MaxSqDist = aSqDist;
358 indbads[indcur] = k;
359 }
360 }
361 }
362 }
363 }
364
365 //Define <indbad>
366 if (indbads[1] != 0 && indbads[2] != 0)
367 {
368 if (indbads[1] != indbads[2])
369 LoopFound = Standard_False;
370 else if (indbads[3] != 0 && indbads[1] != indbads[3])
371 LoopFound = Standard_False;
372 }
373 if (LoopFound)
374 theIndbad = indbads[1];
375
376 return (!LoopFound);
377}
7fd59977 378
379void Approx_ComputeLine::FirstTangencyVector(const MultiLine& Line,
380 const Standard_Integer index,
381 math_Vector& V) const
382{
383
384 Standard_Integer i, j, nbP2d, nbP3d;
385 nbP3d = LineTool::NbP3d(Line);
386 nbP2d = LineTool::NbP2d(Line);
387 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
388 if (nbP3d == 0) mynbP3d = 1;
389 if (nbP2d == 0) mynbP2d = 1;
390 Standard_Boolean Ok=Standard_False;
391 TColgp_Array1OfVec TabV(1, mynbP3d);
392 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
393
394 if (nbP3d != 0 && nbP2d != 0)
395 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
396 else if (nbP2d != 0)
397 Ok = LineTool::Tangency(Line, index, TabV2d);
398 else if (nbP3d != 0)
399 Ok = LineTool::Tangency(Line, index, TabV);
400
401 if (Ok) {
402 if (nbP3d != 0) {
403 j = 1;
404 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
405 V(j) = TabV(i).X();
406 V(j+1) = TabV(i).Y();
407 V(j+2) = TabV(i).Z();
408 j += 3;
409 }
410 }
411 if (nbP2d != 0) {
412 j = nbP3d*3+1;
413 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
414 V(j) = TabV2d(i).X();
415 V(j+1) = TabV2d(i).Y();
416 j += 2;
417 }
418 }
419 }
420 else {
421
422 // recherche d un vecteur tangent par construction d une parabole:
423 AppParCurves_Constraint firstC, lastC;
424 firstC = lastC = AppParCurves_PassPoint;
425 Standard_Integer nbpoles = 3;
426 math_Vector mypar(index, index+2);
427 Parameters(Line, index, index+2, mypar);
428 Approx_ParLeastSquareOfMyGradient
429 LSQ(Line, index, index+2, firstC, lastC, mypar, nbpoles);
430 AppParCurves_MultiCurve C = LSQ.BezierValue();
431
432 gp_Pnt myP;
433 gp_Vec myV;
434 gp_Pnt2d myP2d;
435 gp_Vec2d myV2d;
436 j = 1;
437 for (i = 1; i <= nbP3d; i++) {
438 C.D1(i, 0.0, myP, myV);
439 V(j) = myV.X();
440 V(j+1) = myV.Y();
441 V(j+2) = myV.Z();
442 j += 3;
443 }
444 j = nbP3d*3+1;
445 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
446 C.D1(i, 0.0, myP2d, myV2d);
447 V(j) = myV2d.X();
448 V(j+1) = myV2d.Y();
449 j += 2;
450 }
451 }
452}
453
454
455void Approx_ComputeLine::LastTangencyVector(const MultiLine& Line,
456 const Standard_Integer index,
457 math_Vector& V) const
458{
459 Standard_Integer i, j, nbP2d, nbP3d;
460 nbP3d = LineTool::NbP3d(Line);
461 nbP2d = LineTool::NbP2d(Line);
462 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
463 if (nbP3d == 0) mynbP3d = 1;
464 if (nbP2d == 0) mynbP2d = 1;
465 Standard_Boolean Ok=Standard_False;
466 TColgp_Array1OfVec TabV(1, mynbP3d);
467 TColgp_Array1OfVec2d TabV2d(1, mynbP2d);
468
469
470 if (nbP3d != 0 && nbP2d != 0)
471 Ok = LineTool::Tangency(Line, index, TabV, TabV2d);
472 else if (nbP2d != 0)
473 Ok = LineTool::Tangency(Line, index, TabV2d);
474 else if (nbP3d != 0)
475 Ok = LineTool::Tangency(Line, index, TabV);
476
477 if (Ok) {
478 if (nbP3d != 0) {
479 j = 1;
480 for (i = TabV.Lower(); i <= TabV.Upper(); i++) {
481 V(j) = TabV(i).X();
482 V(j+1) = TabV(i).Y();
483 V(j+2) = TabV(i).Z();
484 j += 3;
485 }
486 }
487 if (nbP2d != 0) {
488 j = nbP3d*3+1;
489 for (i = TabV2d.Lower(); i <= TabV2d.Upper(); i++) {
490 V(j) = TabV2d(i).X();
491 V(j+1) = TabV2d(i).Y();
492 j += 2;
493 }
494 }
495 }
496 else {
497
498 // recherche d un vecteur tangent par construction d une parabole:
499 AppParCurves_Constraint firstC, lastC;
500 firstC = lastC = AppParCurves_PassPoint;
501 Standard_Integer nbpoles = 3;
502 math_Vector mypar(index-2, index);
503 Parameters(Line, index-2, index, mypar);
504 Approx_ParLeastSquareOfMyGradient
505 LSQ(Line, index-2, index, firstC, lastC, mypar, nbpoles);
506 AppParCurves_MultiCurve C = LSQ.BezierValue();
507
508 gp_Pnt myP;
509 gp_Vec myV;
510 gp_Pnt2d myP2d;
511 gp_Vec2d myV2d;
512 j = 1;
513 for (i = 1; i <= nbP3d; i++) {
514 C.D1(i, 1.0, myP, myV);
515 V(j) = myV.X();
516 V(j+1) = myV.Y();
517 V(j+2) = myV.Z();
518 j += 3;
519 }
520 j = nbP3d*3+1;
521 for (i = nbP3d+1; i <= nbP3d+nbP2d; i++) {
522 C.D1(i, 1.0, myP2d, myV2d);
523 V(j) = myV2d.X();
524 V(j+1) = myV2d.Y();
525 j += 2;
526 }
527 }
528
529}
530
531
532
533Standard_Real Approx_ComputeLine::
534 SearchFirstLambda(const MultiLine& Line,
535 const math_Vector& TheParam,
536 const math_Vector& V,
537 const Standard_Integer index) const
538{
539
540 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
541
542 Standard_Integer nbP2d, nbP3d;
543 gp_Pnt P1, P2;
544 gp_Pnt2d P12d, P22d;
545 nbP3d = LineTool::NbP3d(Line);
546 nbP2d = LineTool::NbP2d(Line);
547 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
548 if (nbP3d == 0) mynbP3d = 1;
549 if (nbP2d == 0) mynbP2d = 1;
550 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d);
551 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d);
552
553
554 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP1, tabP12d);
555 else if (nbP2d != 0) LineTool::Value(Line, index, tabP12d);
556 else if (nbP3d != 0) LineTool::Value(Line, index, tabP1);
557
558 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index+1, tabP2, tabP22d);
559 else if (nbP2d != 0) LineTool::Value(Line, index+1, tabP22d);
560 else if (nbP3d != 0) LineTool::Value(Line, index+1, tabP2);
561
562
563 Standard_Real U1 = TheParam(index), U2 = TheParam(index+1);
564 Standard_Real lambda, S;
565 Standard_Integer low = V.Lower();
566
567 if (nbP3d != 0) {
568 P1 = tabP1(1);
569 P2 = tabP2(1);
570 gp_Vec P1P2(P1, P2), myV;
571 myV.SetCoord(V(low), V(low+1), V(low+2));
572 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
573 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
574 }
575 else {
576 P12d = tabP12d(1);
577 P22d = tabP22d(1);
578 gp_Vec2d P1P2(P12d, P22d), myV;
579 myV.SetCoord(V(low), V(low+1));
580 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
581 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
582 }
583 return (S*lambda);
584
585}
586
587
588Standard_Real Approx_ComputeLine::
589 SearchLastLambda(const MultiLine& Line,
590 const math_Vector& TheParam,
591 const math_Vector& V,
592 const Standard_Integer index) const
593{
594 // dq/dw = lambda* V = (p2-p1)/(u2-u1)
595
596 Standard_Integer nbP2d, nbP3d;
597 gp_Pnt P1, P2;
598 gp_Pnt2d P12d, P22d;
599 nbP3d = LineTool::NbP3d(Line);
600 nbP2d = LineTool::NbP2d(Line);
601 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
602 if (nbP3d == 0) mynbP3d = 1;
603 if (nbP2d == 0) mynbP2d = 1;
604 TColgp_Array1OfPnt tabP(1, mynbP3d), tabP2(1, mynbP3d);
605 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d), tabP22d(1, mynbP2d);
606
607 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index-1, tabP, tabP2d);
608 else if (nbP2d != 0) LineTool::Value(Line, index-1, tabP2d);
609 else if (nbP3d != 0) LineTool::Value(Line, index-1, tabP);
610
611 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, index, tabP2, tabP22d);
612 else if (nbP2d != 0) LineTool::Value(Line, index, tabP22d);
613 else if (nbP3d != 0) LineTool::Value(Line, index, tabP2);
614
615
616 Standard_Real U1 = TheParam(index-1), U2 = TheParam(index);
617 Standard_Real lambda, S;
618 Standard_Integer low = V.Lower();
619
620 if (nbP3d != 0) {
621 P1 = tabP(1);
622 P2 = tabP2(1);
623 gp_Vec P1P2(P1, P2), myV;
624 myV.SetCoord(V(low), V(low+1), V(low+2));
625 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
626 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
627 }
628 else {
629 P12d = tabP2d(1);
630 P22d = tabP22d(1);
631 gp_Vec2d P1P2(P12d, P22d), myV;
632 myV.SetCoord(V(low), V(low+1));
633 lambda = (P1P2.Magnitude())/(myV.Magnitude()*(U2-U1));
634 S = (P1P2.Dot(myV)> 0.0) ? 1.0 : -1.0;
635 }
636
637 return (S*lambda);
638}
639
640
641
642Approx_ComputeLine::Approx_ComputeLine
643 (const MultiLine& Line,
644 const math_Vector& Parameters,
645 const Standard_Integer degreemin,
646 const Standard_Integer degreemax,
647 const Standard_Real Tolerance3d,
648 const Standard_Real Tolerance2d,
649 const Standard_Integer NbIterations,
650 const Standard_Boolean cutting,
651 const Standard_Boolean Squares)
41194117 652: myMultiLineNb (0),
2c26a53d 653 myNbPlusOnePoint (0),
41194117 654 myIsClear (Standard_False)
7fd59977 655{
656 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
657 Parameters.Upper());
658 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
659 myfirstParam->SetValue(i, Parameters(i));
660 }
661 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
662 Par = Approx_IsoParametric;
663 mydegremin = degreemin;
664 mydegremax = degreemax;
665 mytol3d = Tolerance3d;
666 mytol2d = Tolerance2d;
667 mysquares = Squares;
668 mycut = cutting;
669 myitermax = NbIterations;
670 alldone = Standard_False;
671 myfirstC = AppParCurves_TangencyPoint;
672 mylastC = AppParCurves_TangencyPoint;
673 Perform(Line);
674}
675
676
677Approx_ComputeLine::Approx_ComputeLine
678 (const math_Vector& Parameters,
679 const Standard_Integer degreemin,
680 const Standard_Integer degreemax,
681 const Standard_Real Tolerance3d,
682 const Standard_Real Tolerance2d,
683 const Standard_Integer NbIterations,
684 const Standard_Boolean cutting,
685 const Standard_Boolean Squares)
41194117 686: myMultiLineNb (0),
2c26a53d 687 myNbPlusOnePoint (0),
41194117 688 myIsClear (Standard_False)
7fd59977 689{
690 myfirstParam = new TColStd_HArray1OfReal(Parameters.Lower(),
691 Parameters.Upper());
692 for (Standard_Integer i = Parameters.Lower(); i <= Parameters.Upper(); i++) {
693 myfirstParam->SetValue(i, Parameters(i));
694 }
695 myfirstC = AppParCurves_TangencyPoint;
696 mylastC = AppParCurves_TangencyPoint;
697 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
698 Par = Approx_IsoParametric;
699 mydegremin = degreemin;
700 mydegremax = degreemax;
701 mytol3d = Tolerance3d;
702 mytol2d = Tolerance2d;
703 mysquares = Squares;
704 mycut = cutting;
705 myitermax = NbIterations;
706 alldone = Standard_False;
707}
708
709Approx_ComputeLine::Approx_ComputeLine
710 (const Standard_Integer degreemin,
711 const Standard_Integer degreemax,
712 const Standard_Real Tolerance3d,
713 const Standard_Real Tolerance2d,
714 const Standard_Integer NbIterations,
715 const Standard_Boolean cutting,
716 const Approx_ParametrizationType parametrization,
717 const Standard_Boolean Squares)
41194117 718: myMultiLineNb (0),
2c26a53d 719 myNbPlusOnePoint (0),
41194117 720 myIsClear (Standard_False)
7fd59977 721{
722 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
723 Par = parametrization;
724 mydegremin = degreemin;
725 mydegremax = degreemax;
726 mytol3d = Tolerance3d;
727 mytol2d = Tolerance2d;
728 mysquares = Squares;
729 mycut = cutting;
730 myitermax = NbIterations;
731 myfirstC = AppParCurves_TangencyPoint;
732 mylastC = AppParCurves_TangencyPoint;
733 alldone = Standard_False;
734}
735
736
737Approx_ComputeLine::Approx_ComputeLine
738 (const MultiLine& Line,
739 const Standard_Integer degreemin,
740 const Standard_Integer degreemax,
741 const Standard_Real Tolerance3d,
742 const Standard_Real Tolerance2d,
743 const Standard_Integer NbIterations,
744 const Standard_Boolean cutting,
745 const Approx_ParametrizationType parametrization,
746 const Standard_Boolean Squares)
41194117 747: myMultiLineNb (0),
2c26a53d 748 myNbPlusOnePoint (0),
41194117 749 myIsClear (Standard_False)
7fd59977 750{
751 myConstraints = new AppParCurves_HArray1OfConstraintCouple(1, 2);
752 alldone = Standard_False;
753 mydegremin = degreemin;
754 mydegremax = degreemax;
755 mytol3d = Tolerance3d;
756 mytol2d = Tolerance2d;
757 mysquares = Squares;
758 mycut = cutting;
759 myitermax = NbIterations;
760 Par = parametrization;
761 myfirstC = AppParCurves_TangencyPoint;
762 mylastC = AppParCurves_TangencyPoint;
763
764 Perform(Line);
765}
766
767
768
769void Approx_ComputeLine::Perform(const MultiLine& Line)
770{
0797d9d3 771#ifdef OCCT_DEBUG
7fd59977 772 if (mydebug) DUMP(Line);
773#endif
41194117
K
774 if (!myIsClear)
775 {
7fd59977 776 myMultiCurves.Clear();
777 myPar.Clear();
778 Tolers3d.Clear();
779 Tolers2d.Clear();
41194117 780 myMultiLineNb = 0;
2c26a53d 781 //myNbPlusOnePoint = 0;
7fd59977 782 }
41194117 783 else myIsClear = Standard_False;
7fd59977 784
785 Standard_Integer i, nbp, Thefirstpt, Thelastpt, oldlastpt;
786 Standard_Boolean Finish = Standard_False,
787 begin = Standard_True, Ok = Standard_False,
788 GoUp = Standard_False, Interpol;
789 Standard_Real thetol3d, thetol2d;
790 Approx_Status MyStatus;
791// gp_Vec V13d, V23d;
792// gp_Vec2d V2d;
793 Thefirstpt = LineTool::FirstPoint(Line);
794 Thelastpt = LineTool::LastPoint(Line);
795 Standard_Integer myfirstpt = Thefirstpt;
796 Standard_Integer mylastpt = Thelastpt;
797
798 AppParCurves_ConstraintCouple myCouple1(myfirstpt, myfirstC);
799 AppParCurves_ConstraintCouple myCouple2(mylastpt, mylastC);
800 myConstraints->SetValue(1, myCouple1);
801 myConstraints->SetValue(2, myCouple2);
802
803 math_Vector TheParam(Thefirstpt, Thelastpt);
804
805
806 if (!mycut) {
807 if(myfirstParam.IsNull()) {
808 Parameters(Line, Thefirstpt, Thelastpt, TheParam);
809 }
810 else {
811 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
812 TheParam(i+Thefirstpt-1) = myfirstParam->Value(i);
813 }
814 }
815 TheMultiCurve = AppParCurves_MultiCurve();
2c26a53d 816 MultiLine anOtherLine0;
817 Standard_Boolean isOtherLine0Made = Standard_False;
818 Standard_Integer indbad = 0;
819 alldone = Compute(Line, myfirstpt, mylastpt, TheParam, thetol3d, thetol2d, indbad);
820 if (indbad != 0)
821 {
822 isOtherLine0Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine0);
823 }
824 if (isOtherLine0Made)
825 {
826 myIsClear = Standard_True;
827 //++myMultiLineNb;
828 myNbPlusOnePoint++;
829 Perform(anOtherLine0);
830 alldone = Standard_True;
831 }
7fd59977 832 if(!alldone && TheMultiCurve.NbCurves() > 0) {
0797d9d3 833#ifdef OCCT_DEBUG
7fd59977 834 if (mydebug) DUMP(TheMultiCurve);
835#endif
836 myMultiCurves.Append(TheMultiCurve);
837 Tolers3d.Append(currenttol3d);
838 Tolers2d.Append(currenttol2d);
2c26a53d 839 Standard_Integer mylen = mylastpt-myfirstpt+1;
840 Standard_Integer myParLen = myParameters->Length();
841 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
842 Handle(TColStd_HArray1OfReal) ThePar =
843 new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
844 for (i = 0; i < aLen; i++)
845 ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
7fd59977 846 myPar.Append(ThePar);
847 }
848 }
849 else {
850 while (!Finish) {
851 oldlastpt = mylastpt;
852 // Gestion du decoupage de la multiline pour approximer:
853 if(!begin) {
854 if (!GoUp) {
855 if (Ok) {
856 // Calcul de la partie a approximer.
857 myfirstpt = mylastpt;
858 mylastpt = Thelastpt;
859 if (myfirstpt == Thelastpt) {
860 Finish = Standard_True;
861 alldone = Standard_True;
862 return;
863 }
864 }
865 else {
866 nbp = mylastpt - myfirstpt + 1;
867 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
868 if (MyStatus == Approx_NoPointsAdded && nbp <= mydegremax+1) {
869 Interpol = ComputeCurve(Line, myfirstpt, mylastpt);
870 if (Interpol) {
871 if (mylastpt == Thelastpt) {
872 Finish = Standard_True;
873 alldone = Standard_True;
874 return;
875 }
876 }
877 }
878 mylastpt = Standard_Integer((myfirstpt + mylastpt)/2);
879 }
880 }
881 GoUp = Standard_False;
882 }
883
884 // Verification du nombre de points restants par rapport au degre
885 // demande.
886 // ==============================================================
887 nbp = mylastpt - myfirstpt + 1;
888 MyStatus = LineTool::WhatStatus(Line, myfirstpt, mylastpt);
889 if (nbp <= mydegremax+5 ) {
890 // Rajout necessaire de points si possible.
891 // ========================================
892 GoUp = Standard_False;
893 Ok = Standard_True;
7fd59977 894 if (MyStatus == Approx_PointsAdded) {
895 // Appel recursif du decoupage:
896 GoUp = Standard_True;
897
2c26a53d 898 MultiLine anOtherLine1 = LineTool::MakeMLBetween(Line, myfirstpt, mylastpt, nbp-1);
7fd59977 899
2c26a53d 900 Standard_Integer nbpdsotherligne = LineTool::FirstPoint (anOtherLine1) - LineTool::LastPoint (anOtherLine1);
7fd59977 901
902 //-- Si MakeML a echoue on retourne une ligne vide
41194117
K
903 if ((nbpdsotherligne == 0) || myMultiLineNb >= 3)
904 {
7fd59977 905 //-- cout<<" ** ApproxComputeLine MakeML Echec ** LBR lbr "<<endl;
906 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
907 // planter la station !!
908 myCouple1.SetIndex(myfirstpt);
909 myCouple2.SetIndex(mylastpt);
910 myConstraints->SetValue(1, myCouple1);
911 myConstraints->SetValue(2, myCouple2);
912
913 math_Vector Param(myfirstpt, mylastpt);
914 Approx_ParametrizationType SavePar = Par;
915 Par = Approx_IsoParametric;
916 Parameters(Line, myfirstpt, mylastpt, Param);
917 TheMultiCurve = AppParCurves_MultiCurve();
2c26a53d 918 MultiLine anOtherLine2;
919 Standard_Boolean isOtherLine2Made = Standard_False;
920 Standard_Integer indbad = 0;
921 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
922 if (indbad != 0)
923 {
924 isOtherLine2Made = LineTool::MakeMLOneMorePoint(Line, myfirstpt, mylastpt, indbad, anOtherLine2);
925 }
926 if (isOtherLine2Made)
927 {
928 myIsClear = Standard_True;
929 //++myMultiLineNb;
930 myNbPlusOnePoint++;
931 Par = SavePar;
932 Perform(anOtherLine2);
933 Ok = Standard_True;
934 }
7fd59977 935
936 if (!Ok) {
937 Standard_Real tt3d = currenttol3d, tt2d = currenttol2d;
938 Handle(TColStd_HArray1OfReal) saveParameters = myParameters;
939 AppParCurves_MultiCurve saveMultiCurve = TheMultiCurve;
940
941 if(SavePar != Approx_IsoParametric)
942 Par = SavePar;
943 else
944 Par = Approx_ChordLength;
945
946 Parameters(Line, myfirstpt, mylastpt, Param);
2c26a53d 947 isOtherLine2Made = Standard_False;
948 indbad = 0;
949 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
950 if (indbad != 0)
951 {
952 isOtherLine2Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad, anOtherLine2);
953 }
954 if (isOtherLine2Made)
955 {
956 myIsClear = Standard_True;
957 //++myMultiLineNb;
958 myNbPlusOnePoint++;
959 Perform (anOtherLine2);
960 Ok = Standard_True;
961 }
7fd59977 962
963 if (!Ok && tt3d <= currenttol3d && tt2d <= currenttol2d) {
964 currenttol3d = tt3d; currenttol2d = tt2d;
965 myParameters = saveParameters;
966 TheMultiCurve = saveMultiCurve;
967 }
968 }
969 Par = SavePar;
2c26a53d 970 if (myfirstpt == Thelastpt)
971 {
972 Finish = Standard_True;
973 alldone = Standard_True;
974 return;
975 }
7fd59977 976
977 oldlastpt = mylastpt;
978 if (!Ok) {
979 tolreached = Standard_False;
980 if (TheMultiCurve.NbCurves() == 0) {
981 myMultiCurves.Clear();
982 return;
983 }
0797d9d3 984#ifdef OCCT_DEBUG
2c26a53d 985 if (mydebug) DUMP(TheMultiCurve);
7fd59977 986#endif
2c26a53d 987 MultiLine anOtherLine3;
988 Standard_Boolean isOtherLine3Made = Standard_False;
989 Standard_Integer indbad2 = 0;
990 if (!CheckMultiCurve(TheMultiCurve, Line,
991 myfirstpt, mylastpt,
992 indbad2))
993 {
994 isOtherLine3Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad2, anOtherLine3);
995 }
996 if (isOtherLine3Made)
997 {
998 myIsClear = Standard_True;
999 //++myMultiLineNb;
1000 myNbPlusOnePoint++;
1001 Perform(anOtherLine3);
1002 myfirstpt = mylastpt;
1003 mylastpt = Thelastpt;
1004 }
1005 else
1006 {
1007 myMultiCurves.Append(TheMultiCurve);
1008 Tolers3d.Append(currenttol3d);
1009 Tolers2d.Append(currenttol2d);
1010 Standard_Integer mylen = oldlastpt-myfirstpt+1;
1011 Standard_Integer myParLen = myParameters->Length();
1012 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
1013 Handle(TColStd_HArray1OfReal) ThePar =
1014 new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
1015 for (i = 0; i < aLen; i++)
1016 ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
1017 myPar.Append(ThePar);
1018 }
7fd59977 1019 }
1020 myfirstpt = oldlastpt;
1021 mylastpt = Thelastpt;
1022
1023 }
41194117
K
1024 else
1025 {
1026 myIsClear = Standard_True;
1027 ++myMultiLineNb;
2c26a53d 1028 Perform(anOtherLine1);
7fd59977 1029 myfirstpt = mylastpt;
41194117 1030 mylastpt = Thelastpt;
7fd59977 1031 }
1032 }
1033
1034 if (MyStatus == Approx_NoPointsAdded && !begin) {
1035 // On rend la meilleure approximation obtenue precedemment.
1036 // ========================================================
1037 GoUp = Standard_True;
1038 tolreached = Standard_False;
1039 if (TheMultiCurve.NbCurves() == 0) {
1040 myMultiCurves.Clear();
1041 return;
1042 }
0797d9d3 1043#ifdef OCCT_DEBUG
7fd59977 1044 if (mydebug) DUMP(TheMultiCurve);
1045#endif
1046 myMultiCurves.Append(TheMultiCurve);
1047 Tolers3d.Append(currenttol3d);
1048 Tolers2d.Append(currenttol2d);
2c26a53d 1049 Standard_Integer mylen = oldlastpt-myfirstpt+1;
1050 Standard_Integer myParLen = myParameters->Length();
1051 Standard_Integer aLen = (myParLen > mylen)? myParLen : mylen;
1052 Handle(TColStd_HArray1OfReal) ThePar =
1053 new TColStd_HArray1OfReal(myfirstpt, myfirstpt+aLen-1);
1054 for (i = 0; i < aLen; i++)
1055 ThePar->SetValue(myfirstpt+i, myParameters->Value(myParameters->Lower()+i));
7fd59977 1056 myPar.Append(ThePar);
1057
1058 myfirstpt = oldlastpt;
1059 mylastpt = Thelastpt;
1060 }
1061
1062 else if (MyStatus == Approx_NoApproximation) {
1063 // On ne fait pas d approximation entre myfirstpt et mylastpt.
1064 // ===========================================================
1065 // On stocke pour pouvoir en informer l utilisateur.
1066 GoUp = Standard_True;
1067 myfirstpt = mylastpt;
1068 mylastpt = Thelastpt;
1069 }
1070 }
1071
1072 if (myfirstpt == Thelastpt) {
1073 Finish = Standard_True;
1074 alldone = Standard_True;
1075 return;
1076 }
1077 if (!GoUp) {
1078 if (myfirstpt == mylastpt) break; // Pour etre sur de ne pas
1079 // planter la station !!
1080 myCouple1.SetIndex(myfirstpt);
1081 myCouple2.SetIndex(mylastpt);
1082 myConstraints->SetValue(1, myCouple1);
1083 myConstraints->SetValue(2, myCouple2);
1084
1085 // Calcul des parametres sur ce nouvel intervalle.
1086 // On recupere les parametres initiaux lors du decoupage.
1087
1088 math_Vector Param(myfirstpt, mylastpt);
1089 if (begin) {
1090 if(myfirstParam.IsNull()) {
1091 Parameters(Line, myfirstpt, mylastpt, Param);
1092 }
1093 else {
1094 for (i = myfirstParam->Lower(); i <= myfirstParam->Upper(); i++) {
1095 Param(i) = myfirstParam->Value(i);
1096 }
1097 myfirstParam.Nullify();
1098 }
1099 TheParam = Param;
1100 begin = Standard_False;
1101 }
1102 else {
1103 Standard_Real pfirst = TheParam.Value(myfirstpt);
1104 Standard_Real plast = TheParam.Value(mylastpt);
1105 for (i = myfirstpt; i <= mylastpt; i++) {
1106 Param(i) = (TheParam.Value(i)-pfirst)/(plast-pfirst);
1107 }
1108 }
1109
1110 TheMultiCurve = AppParCurves_MultiCurve();
2c26a53d 1111 MultiLine anOtherLine4;
1112 Standard_Boolean isOtherLine4Made = Standard_False;
1113 Standard_Integer indbad = 0;
1114 Ok = Compute(Line, myfirstpt, mylastpt, Param, thetol3d, thetol2d, indbad);
1115 if (indbad != 0)
1116 {
1117 isOtherLine4Made = LineTool::MakeMLOneMorePoint (Line, myfirstpt, mylastpt, indbad, anOtherLine4);
1118 }
1119 if (isOtherLine4Made)
1120 {
1121 myIsClear = Standard_True;
1122 //++myMultiLineNb;
1123 myNbPlusOnePoint++;
1124 Perform (anOtherLine4);
1125 Ok = Standard_True;
1126 }
1127 if (myfirstpt == Thelastpt)
1128 {
1129 Finish = Standard_True;
1130 alldone = Standard_True;
1131 return;
1132 }
7fd59977 1133 }
1134 }
1135 }
1136}
1137
1138
1139
1140const TColStd_Array1OfReal& Approx_ComputeLine::Parameters(const Standard_Integer Index) const
1141{
1142 return (myPar.Value(Index))->Array1();
1143}
1144
1145
1146Standard_Integer Approx_ComputeLine::NbMultiCurves()const
1147{
1148 return myMultiCurves.Length();
1149}
1150
1151AppParCurves_MultiCurve& Approx_ComputeLine::ChangeValue(const Standard_Integer Index)
1152{
1153 return myMultiCurves.ChangeValue(Index);
1154}
1155
1156
1157const AppParCurves_MultiCurve& Approx_ComputeLine::Value(const Standard_Integer Index)
1158const
1159{
1160 return myMultiCurves.Value(Index);
1161}
1162
1163
1164const AppParCurves_MultiBSpCurve& Approx_ComputeLine::SplineValue()
1165{
1166 Approx_MCurvesToBSpCurve Trans;
1167 Trans.Perform(myMultiCurves);
1168 myspline = Trans.Value();
1169 return myspline;
1170}
1171
1172
1173
1174
1175
1176void Approx_ComputeLine::Parameters(const MultiLine& Line,
1177 const Standard_Integer firstP,
1178 const Standard_Integer lastP,
1179 math_Vector& TheParameters) const
1180{
96a95605 1181 Standard_Integer i, j, nbP2d, nbP3d;
7fd59977 1182 Standard_Real dist;
1183 gp_Pnt P1, P2;
1184 gp_Pnt2d P12d, P22d;
7fd59977 1185
1186 if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
1187 nbP3d = LineTool::NbP3d(Line);
1188 nbP2d = LineTool::NbP2d(Line);
1189 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
1190 if (nbP3d == 0) mynbP3d = 1;
1191 if (nbP2d == 0) mynbP2d = 1;
1192
1193 TheParameters(firstP) = 0.0;
1194 dist = 0.0;
1195 TColgp_Array1OfPnt tabP(1, mynbP3d);
1196 TColgp_Array1OfPnt tabPP(1, mynbP3d);
1197 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
1198 TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
1199
1200 for (i = firstP+1; i <= lastP; i++) {
1201 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i-1, tabP, tabP2d);
1202 else if (nbP2d != 0) LineTool::Value(Line, i-1, tabP2d);
1203 else if (nbP3d != 0) LineTool::Value(Line, i-1, tabP);
1204
1205 if (nbP3d != 0 && nbP2d != 0) LineTool::Value(Line, i, tabPP, tabPP2d);
1206 else if (nbP2d != 0) LineTool::Value(Line, i, tabPP2d);
1207 else if (nbP3d != 0) LineTool::Value(Line, i, tabPP);
1208 dist = 0;
1209 for (j = 1; j <= nbP3d; j++) {
1210 P1 = tabP(j);
1211 P2 = tabPP(j);
1212 dist += P2.Distance(P1);
1213 }
1214 for (j = 1; j <= nbP2d; j++) {
1215 P12d = tabP2d(j);
1216 P22d = tabPP2d(j);
1217 dist += P22d.Distance(P12d);
1218 }
1219 if(Par == Approx_ChordLength)
1220 TheParameters(i) = TheParameters(i-1) + dist;
1221 else {// Par == Approx_Centripetal
1222 TheParameters(i) = TheParameters(i-1) + Sqrt(dist);
1223 }
1224 }
1225 for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
1226 }
1227 else {
1228 for (i = firstP; i <= lastP; i++) {
1229 TheParameters(i) = (Standard_Real(i)-firstP)/
1230 (Standard_Real(lastP)-Standard_Real(firstP));
1231 }
1232 }
1233}
1234
1235
1236Standard_Boolean Approx_ComputeLine::Compute(const MultiLine& Line,
1237 const Standard_Integer fpt,
1238 const Standard_Integer lpt,
1239 math_Vector& Para,
1240 Standard_Real& TheTol3d,
2c26a53d 1241 Standard_Real& TheTol2d,
1242 Standard_Integer& indbad)
7fd59977 1243{
2c26a53d 1244 indbad = 0;
7fd59977 1245 Standard_Integer deg, i;
1246 Standard_Boolean mydone;
1247 Standard_Real Fv;
1248 Standard_Integer nbp = lpt-fpt+1;
1249
1250 math_Vector ParSav(Para.Lower(), Para.Upper());
1251 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1252 ParSav(i) = Para(i);
1253 }
1254 Standard_Integer Mdegmax = mydegremax;
1255 if(nbp < Mdegmax+5 && mycut) {
1256 Mdegmax = nbp - 5;
1257 }
1258 if(Mdegmax < mydegremin) {
1259 Mdegmax = mydegremin;
1260 }
1261
1262 currenttol3d = currenttol2d = RealLast();
1263 for (deg = Min(nbp-1,mydegremin); deg <= Mdegmax; deg++) {
1264 AppParCurves_MultiCurve mySCU(deg+1);
1265 if (mysquares) {
1266 Approx_ParLeastSquareOfMyGradient SQ(Line, fpt, lpt,
1267 myfirstC, mylastC, Para, deg+1);
1268 mydone = SQ.IsDone();
1269 mySCU = SQ.BezierValue();
1270 SQ.Error(Fv, TheTol3d, TheTol2d);
1271 }
1272 else {
1273 Approx_MyGradient GRAD(Line, fpt, lpt, myConstraints,
1274 Para, deg, mytol3d, mytol2d, myitermax);
1275 mydone = GRAD.IsDone();
1276 mySCU = GRAD.Value();
1277 if (mySCU.NbCurves() == 0)
1278 continue;
1279 TheTol3d = GRAD.MaxError3d();
1280 TheTol2d = GRAD.MaxError2d();
1281 }
1282 Standard_Real uu1 = Para(Para.Lower()), uu2;
1283 Standard_Boolean restau = Standard_False;
1284 for ( i = Para.Lower()+1; i <= Para.Upper(); i++) {
1285 uu2 = Para(i);
1286 if (uu2 <= uu1) {
1287 restau = Standard_True;
1288// cout << "restau = Standard_True" << endl;
1289 break;
1290 }
1291 uu1 = uu2;
1292 }
1293 if (restau) {
1294 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1295 Para(i) = ParSav(i);
1296 }
1297 }
1298 if (mydone) {
1299 if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) {
1300 // Stockage de la multicurve approximee.
1301 tolreached = Standard_True;
0797d9d3 1302#ifdef OCCT_DEBUG
2c26a53d 1303 if (mydebug) DUMP(mySCU);
7fd59977 1304#endif
2c26a53d 1305 if (myNbPlusOnePoint != 0 &&
1306 !CheckMultiCurve(mySCU, Line,
1307 fpt, lpt,
1308 indbad))
1309 {
1310 return Standard_False;
1311 }
1312 else
1313 {
1314 myMultiCurves.Append(mySCU);
1315 // Stockage des parametres de la partie de MultiLine approximee:
1316 // A ameliorer !! (bq trop de recopies)
1317 Handle(TColStd_HArray1OfReal) ThePar =
1318 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1319 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1320 ThePar->SetValue(i, Para(i));
1321 }
1322 myPar.Append(ThePar);
1323 Tolers3d.Append(TheTol3d);
1324 Tolers2d.Append(TheTol2d);
1325 return Standard_True;
1326 }
7fd59977 1327 }
1328 }
1329
1330 if (TheTol3d <= currenttol3d && TheTol2d <= currenttol2d) {
1331 TheMultiCurve = mySCU;
1332 currenttol3d = TheTol3d;
1333 currenttol2d = TheTol2d;
1334 myParameters = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1335 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1336 myParameters->SetValue(i, Para(i));
1337 }
1338 }
1339
1340 }
1341
1342 return Standard_False;
1343}
1344
1345
1346
1347
1348Standard_Boolean Approx_ComputeLine::ComputeCurve(const MultiLine& Line,
1349 const Standard_Integer firstpt,
1350 const Standard_Integer lastpt)
1351{
1352 Standard_Integer i, j, nbP3d, nbP2d, deg;
1353 gp_Vec V13d, V23d;
1354 gp_Vec2d V12d, V22d;
1355 gp_Pnt P1, P2;
1356 gp_Pnt2d P12d, P22d;
96a95605 1357 Standard_Boolean Tangent1, Tangent2, mydone= Standard_False;
0797d9d3 1358#ifdef OCCT_DEBUG
96a95605
DB
1359 Standard_Boolean Parallel;
1360#endif
7fd59977 1361 Standard_Integer myfirstpt = firstpt, mylastpt = lastpt;
1362 Standard_Integer nbp = lastpt-firstpt+1, Kopt = 0;
7fd59977 1363 math_Vector Para(firstpt, lastpt);
1364
1365 Parameters(Line, firstpt, lastpt, Para);
1366
1367 nbP3d = LineTool::NbP3d(Line);
1368 nbP2d = LineTool::NbP2d(Line);
1369 Standard_Integer mynbP3d = nbP3d, mynbP2d = nbP2d;
1370 if (nbP3d == 0) mynbP3d = 1 ;
1371 if (nbP2d == 0) mynbP2d = 1 ;
1372
1373
1374 TColgp_Array1OfVec tabV1(1, mynbP3d), tabV2(1, mynbP3d);
1375 TColgp_Array1OfPnt tabP1(1, mynbP3d), tabP2(1, mynbP3d), tabP(1, mynbP3d);
1376 TColgp_Array1OfVec2d tabV12d(1, mynbP2d), tabV22d(1, mynbP2d);
1377 TColgp_Array1OfPnt2d tabP12d(1, mynbP2d), tabP22d(1, mynbP2d), tabP2d(1, mynbP2d);
1378
1379 if (nbP3d != 0 && nbP2d != 0) {
1380 LineTool::Value(Line, myfirstpt,tabP1,tabP12d);
1381 LineTool::Value(Line, mylastpt,tabP2,tabP22d);
1382 Tangent1 = LineTool::Tangency(Line, myfirstpt,tabV1,tabV12d);
1383 Tangent2 = LineTool::Tangency(Line, mylastpt,tabV2,tabV22d);
1384 }
1385 else if (nbP2d != 0) {
1386 LineTool::Value(Line, myfirstpt,tabP12d);
1387 LineTool::Value(Line, mylastpt,tabP22d);
1388 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV12d);
1389 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV22d);
1390 }
1391 else {
1392 LineTool::Value(Line, myfirstpt,tabP1);
1393 LineTool::Value(Line, mylastpt,tabP2);
1394 Tangent1 = LineTool::Tangency(Line, myfirstpt, tabV1);
1395 Tangent2 = LineTool::Tangency(Line, mylastpt, tabV2);
1396 }
1397
1398 if (Tangent1) Kopt++;
1399 if (Tangent2) Kopt++;
1400
1401
1402 if (nbp == 2) {
1403 // S il n y a que 2 points, on verifie quand meme que les tangentes sont
1404 // alignees.
0797d9d3 1405#ifdef OCCT_DEBUG
7fd59977 1406 Parallel = Standard_True;
96a95605 1407#endif
7fd59977 1408 if (Tangent1) {
1409 for (i = 1; i <= nbP3d; i++) {
1410 gp_Vec PVec(tabP1(i), tabP2(i));
1411 V13d = tabV1(i);
1412 if (!PVec.IsParallel(V13d, Precision::Angular())) {
0797d9d3 1413#ifdef OCCT_DEBUG
7fd59977 1414 Parallel = Standard_False;
96a95605 1415#endif
7fd59977 1416 break;
1417 }
1418 }
1419 for (i = 1; i <= nbP2d; i++) {
1420 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1421 V12d = tabV12d(i);
1422 if (!PVec2d.IsParallel(V12d, Precision::Angular())) {
0797d9d3 1423#ifdef OCCT_DEBUG
7fd59977 1424 Parallel = Standard_False;
96a95605 1425#endif
7fd59977 1426 break;
1427 }
1428 }
1429 }
1430
1431 if (Tangent2) {
1432 for (i = 1; i <= nbP3d; i++) {
1433 gp_Vec PVec(tabP1(i), tabP2(i));
1434 V23d = tabV2(i);
1435 if (!PVec.IsParallel(V23d, Precision::Angular())) {
0797d9d3 1436#ifdef OCCT_DEBUG
7fd59977 1437 Parallel = Standard_False;
96a95605 1438#endif
7fd59977 1439 break;
1440 }
1441 }
1442 for (i = 1; i <= nbP2d; i++) {
1443 gp_Vec2d PVec2d(tabP12d(i), tabP22d(i));
1444 V22d = tabV22d(i);
1445 if (!PVec2d.IsParallel(V22d, Precision::Angular())) {
0797d9d3 1446#ifdef OCCT_DEBUG
7fd59977 1447 Parallel = Standard_False;
96a95605 1448#endif
7fd59977 1449 break;
1450 }
1451 }
1452 }
1453
0797d9d3 1454#ifdef OCCT_DEBUG
7fd59977 1455 if (!Parallel) {
1456 if (mydebug) cout <<"droite mais tangentes pas vraiment paralleles!!"<< endl;
1457 }
1458#endif
1459 AppParCurves_MultiCurve mySCU(mydegremin+1);
1460 if (nbP3d != 0 && nbP2d != 0) {
1461 AppParCurves_MultiPoint MPole1(tabP1, tabP12d);
1462 AppParCurves_MultiPoint MPole2(tabP2, tabP22d);
1463 mySCU.SetValue(1, MPole1);
1464 mySCU.SetValue(mydegremin+1, MPole2);
1465 for (i = 2; i <= mydegremin; i++) {
1466 for (j = 1; j<= nbP3d; j++) {
1467 P1 = tabP1(j);
1468 P2 = tabP2(j);
1469 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1470 }
1471 for (j = 1; j<= nbP2d; j++) {
1472 P12d = tabP12d(j);
1473 P22d = tabP22d(j);
1474 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1475 }
1476 AppParCurves_MultiPoint MPole(tabP, tabP2d);
1477 mySCU.SetValue(i, MPole);
1478 }
1479
1480 }
1481 else if (nbP3d != 0) {
1482 AppParCurves_MultiPoint MPole1(tabP1);
1483 AppParCurves_MultiPoint MPole2(tabP2);
1484 mySCU.SetValue(1, MPole1);
1485 mySCU.SetValue(mydegremin+1, MPole2);
1486 for (i = 2; i <= mydegremin; i++) {
1487 for (j = 1; j<= nbP3d; j++) {
1488 P1 = tabP1(j);
1489 P2 = tabP2(j);
1490 tabP(j).SetXYZ(P1.XYZ()+(i-1)*(P2.XYZ()-P1.XYZ())/mydegremin);
1491 }
1492 AppParCurves_MultiPoint MPole(tabP);
1493 mySCU.SetValue(i, MPole);
1494 }
1495 }
1496 else if (nbP2d != 0) {
1497 AppParCurves_MultiPoint MPole1(tabP12d);
1498 AppParCurves_MultiPoint MPole2(tabP22d);
1499 mySCU.SetValue(1, MPole1);
1500 mySCU.SetValue(mydegremin+1, MPole2);
1501 for (i = 2; i <= mydegremin; i++) {
1502 for (j = 1; j<= nbP2d; j++) {
1503 P12d = tabP12d(j);
1504 P22d = tabP22d(j);
1505 tabP2d(j).SetXY(P12d.XY()+(i-1)*(P22d.XY()-P12d.XY())/mydegremin);
1506 }
1507 AppParCurves_MultiPoint MPole(tabP2d);
1508 mySCU.SetValue(i, MPole);
1509 }
1510 }
1511 mydone = Standard_True;
1512 // Stockage de la multicurve approximee.
1513 tolreached = Standard_True;
0797d9d3 1514#ifdef OCCT_DEBUG
7fd59977 1515 if (mydebug) DUMP(mySCU);
1516#endif
1517 myMultiCurves.Append(mySCU);
1518 Handle(TColStd_HArray1OfReal) ThePar = new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1519 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1520 ThePar->SetValue(i, Para(i));
1521 }
1522 myPar.Append(ThePar);
1523 Tolers3d.Append(Precision::Confusion());
1524 Tolers2d.Append(Precision::PConfusion());
1525 return mydone;
1526 }
1527
1528 // avec les tangentes.
1529 deg = nbp+1;
1530 AppParCurves_MultiCurve mySCU(deg+1);
1531 AppParCurves_Constraint Cons = AppParCurves_TangencyPoint;
1532 Standard_Real lambda1, lambda2;
1533 math_Vector V1(1, nbP3d*3+nbP2d*2);
1534 math_Vector V2(1, nbP3d*3+nbP2d*2);
1535 FirstTangencyVector(Line, myfirstpt, V1);
1536 lambda1 = SearchFirstLambda(Line, Para, V1, myfirstpt);
1537
1538 LastTangencyVector(Line, mylastpt, V2);
1539 lambda2 = SearchLastLambda(Line, Para, V2, mylastpt);
1540
1541 Approx_ParLeastSquareOfMyGradient
1542 LSQ(Line, myfirstpt, mylastpt,
1543 Cons, Cons, Para, deg+1);
1544
1545 lambda1 = lambda1/deg;
1546 lambda2 = lambda2/deg;
1547 LSQ.Perform(Para, V1, V2, lambda1, lambda2);
1548 mydone = LSQ.IsDone();
1549 mySCU = LSQ.BezierValue();
1550
1551 if (mydone) {
1552 Standard_Real Fv, TheTol3d, TheTol2d;
1553 LSQ.Error(Fv, TheTol3d, TheTol2d);
1554
1555 // Stockage de la multicurve approximee.
1556 tolreached = Standard_True;
0797d9d3 1557#ifdef OCCT_DEBUG
7fd59977 1558 if (mydebug) DUMP(mySCU);
1559#endif
1560 myMultiCurves.Append(mySCU);
1561 Handle(TColStd_HArray1OfReal) ThePar =
1562 new TColStd_HArray1OfReal(Para.Lower(), Para.Upper());
1563 for (i = Para.Lower(); i <= Para.Upper(); i++) {
1564 ThePar->SetValue(i, Para(i));
1565 }
1566 myPar.Append(ThePar);
1567 Tolers3d.Append(TheTol3d);
1568 Tolers2d.Append(TheTol2d);
1569 return Standard_True;
1570 }
1571 return mydone;
1572}
1573
1574
1575
1576void Approx_ComputeLine::Init(const Standard_Integer degreemin,
1577 const Standard_Integer degreemax,
1578 const Standard_Real Tolerance3d,
1579 const Standard_Real Tolerance2d,
1580 const Standard_Integer NbIterations,
1581 const Standard_Boolean cutting,
1582 const Approx_ParametrizationType parametrization,
1583 const Standard_Boolean Squares)
1584{
1585 mydegremin = degreemin;
1586 mydegremax = degreemax;
1587 mytol3d = Tolerance3d;
1588 mytol2d = Tolerance2d;
1589 Par = parametrization;
1590 mysquares = Squares;
1591 mycut = cutting;
1592 myitermax = NbIterations;
1593}
1594
1595
1596
1597void Approx_ComputeLine::SetDegrees(const Standard_Integer degreemin,
1598 const Standard_Integer degreemax)
1599{
1600 mydegremin = degreemin;
1601 mydegremax = degreemax;
1602}
1603
1604
1605void Approx_ComputeLine::SetTolerances(const Standard_Real Tolerance3d,
1606 const Standard_Real Tolerance2d)
1607{
1608 mytol3d = Tolerance3d;
1609 mytol2d = Tolerance2d;
1610}
1611
1612
1613void Approx_ComputeLine::SetConstraints(const AppParCurves_Constraint FirstC,
1614 const AppParCurves_Constraint LastC)
1615{
1616 myfirstC = FirstC;
1617 mylastC = LastC;
1618}
1619
1620
1621
1622Standard_Boolean Approx_ComputeLine::IsAllApproximated()
1623const {
1624 return alldone;
1625}
1626
1627Standard_Boolean Approx_ComputeLine::IsToleranceReached()
1628const {
1629 return tolreached;
1630}
1631
1632void Approx_ComputeLine::Error(const Standard_Integer Index,
1633 Standard_Real& tol3d,
1634 Standard_Real& tol2d) const
1635{
1636 tol3d = Tolers3d.Value(Index);
1637 tol2d = Tolers2d.Value(Index);
1638}
1639
4e14c88f 1640Approx_ParametrizationType Approx_ComputeLine::Parametrization() const
7fd59977 1641{
4e14c88f 1642 return Par;
7fd59977 1643}