0032701: Modeling Algorithms - 2d curve has bending near the degenerated edge of...
[occt.git] / src / ApproxInt / ApproxInt_Approx.gxx
1 // Created on: 1993-03-30
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <AppParCurves_Constraint.hxx>
18 #include <GeomAbs_SurfaceType.hxx>
19 #include <IntSurf_Quadric.hxx>
20 #include <gp_Trsf.hxx>
21 #include <gp_Trsf2d.hxx>
22 #include <IntSurf_PntOn2S.hxx>
23 #include <Precision.hxx>
24 #include <ApproxInt_KnotTools.hxx>
25
26 // If quantity of points is less than aMinNbPointsForApprox
27 // then interpolation is used.
28 const Standard_Integer aMinNbPointsForApprox = 5;
29
30 // This constant should be removed in the future.
31 const Standard_Real RatioTol = 1.5 ;
32
33 //=======================================================================
34 //function : ComputeTrsf3d
35 //purpose  : 
36 //=======================================================================
37 static void ComputeTrsf3d(const Handle(TheWLine)& theline,
38                           Standard_Real& theXo,
39                           Standard_Real& theYo,
40                           Standard_Real& theZo)
41 {
42   const Standard_Integer aNbPnts = theline->NbPnts();
43   Standard_Real aXmin = RealLast(), aYmin = RealLast(), aZmin = RealLast();
44   for(Standard_Integer i=1;i<=aNbPnts;i++)
45   {
46     const gp_Pnt P = theline->Point(i).Value();
47     aXmin = Min(P.X(), aXmin);
48     aYmin = Min(P.Y(), aYmin);
49     aZmin = Min(P.Z(), aZmin);
50   }
51
52   theXo = -aXmin;
53   theYo = -aYmin;
54   theZo = -aZmin;
55 }
56
57 //=======================================================================
58 //function : ComputeTrsf2d
59 //purpose  : 
60 //=======================================================================
61 static void ComputeTrsf2d(const Handle(TheWLine)& theline,
62                           const Standard_Boolean onFirst,
63                           Standard_Real& theUo,
64                           Standard_Real& theVo)
65
66   const Standard_Integer aNbPnts = theline->NbPnts();
67   Standard_Real aUmin = RealLast(), aVmin = RealLast();
68
69   // pointer to a member-function
70   void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const;
71
72   if (onFirst)
73     pfunc = &IntSurf_PntOn2S::ParametersOnS1;
74   else
75     pfunc = &IntSurf_PntOn2S::ParametersOnS2;
76   
77   for(Standard_Integer i=1; i<=aNbPnts; i++)
78   {
79     const IntSurf_PntOn2S POn2S = theline->Point(i);
80     Standard_Real  U,V;
81     (POn2S.*pfunc)(U,V);
82     aUmin = Min(U, aUmin);
83     aVmin = Min(V, aVmin);
84   }
85
86   theUo = -aUmin;
87   theVo = -aVmin;
88 }
89
90 //=======================================================================
91 //function : Parameters
92 //purpose  :
93 //=======================================================================
94 void ApproxInt_Approx::Parameters(const ApproxInt_TheMultiLine& Line,
95                        const Standard_Integer firstP,
96                        const Standard_Integer lastP,
97                        const Approx_ParametrizationType Par,
98                        math_Vector& TheParameters)
99 {
100   Standard_Integer i, j, nbP2d, nbP3d;
101   Standard_Real dist;
102
103   if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
104     nbP3d = ApproxInt_TheMultiLineTool::NbP3d(Line);
105     nbP2d = ApproxInt_TheMultiLineTool::NbP2d(Line);
106     Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
107     if (nbP3d == 0) mynbP3d = 1;
108     if (nbP2d == 0) mynbP2d = 1;
109
110     TheParameters(firstP) = 0.0;
111     dist = 0.0;
112     TColgp_Array1OfPnt tabP(1, mynbP3d);
113     TColgp_Array1OfPnt tabPP(1, mynbP3d);
114     TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
115     TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
116
117     for (i = firstP+1; i <= lastP; i++) {
118       if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP, tabP2d);
119       else if (nbP2d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP2d);
120       else if (nbP3d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP);
121
122       if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP, tabPP2d);
123       else if (nbP2d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i, tabPP2d);
124       else if (nbP3d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i, tabPP);
125       dist = 0;
126       for (j = 1; j <= nbP3d; j++) {
127         const gp_Pnt &aP1 = tabP(j),
128                      &aP2 = tabPP(j);
129         dist += aP2.SquareDistance(aP1);
130       }
131       for (j = 1; j <= nbP2d; j++) {
132         const gp_Pnt2d &aP12d = tabP2d(j),
133                        &aP22d = tabPP2d(j);
134
135         dist += aP22d.SquareDistance(aP12d);
136       }
137
138       dist = Sqrt(dist);
139       if(Par == Approx_ChordLength)
140       {
141         TheParameters(i) = TheParameters(i - 1) + dist;
142       }
143       else
144       {// Par == Approx_Centripetal
145         TheParameters(i) = TheParameters(i - 1) + Sqrt(dist);
146       }
147     }
148     for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
149   }
150   else {
151     for (i = firstP; i <= lastP; i++) {
152       TheParameters(i) = (Standard_Real(i)-firstP)/
153         (Standard_Real(lastP)-Standard_Real(firstP));
154     }
155   }
156 }
157
158 //=======================================================================
159 //function : Default constructor
160 //purpose  : 
161 //=======================================================================
162 ApproxInt_Approx::ApproxInt_Approx():
163                       myComputeLine(4, 8, 0.001, 0.001, 5),
164                       myComputeLineBezier(4, 8, 0.001, 0.001, 5),
165                       myWithTangency(Standard_True),
166                       myTol3d(0.001),
167                       myTol2d(0.001),
168                       myDegMin(4),
169                       myDegMax(8),
170                       myNbIterMax(5),
171                       myTolReached3d(0.0),
172                       myTolReached2d(0.0)
173 {
174   myComputeLine.SetContinuity(2);
175   //myComputeLineBezier.SetContinuity(2);
176 }
177
178 //=======================================================================
179 //function : Perform
180 //purpose  : Build without surfaces information.
181 //=======================================================================
182 void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline,
183                                const Standard_Boolean ApproxXYZ,
184                                const Standard_Boolean ApproxU1V1,
185                                const Standard_Boolean ApproxU2V2,
186                                const Standard_Integer indicemin,
187                                const Standard_Integer indicemax)
188 {
189   // Prepare DS.
190   prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
191
192   const Standard_Integer nbpntbez = myData.indicemax - myData.indicemin;
193   if(nbpntbez < aMinNbPointsForApprox) 
194     myData.myBezierApprox = Standard_False;
195   else 
196     myData.myBezierApprox = Standard_True;
197
198   // Fill data structure.
199   fillData(theline);
200
201   // Build knots.
202   buildKnots(theline, NULL);
203   if (myKnots.Length() == 2 &&
204       indicemax - indicemin > 2 * myData.myNbPntMax)
205   {
206     // At least 3 knots for BrepApprox.
207     myKnots.ChangeLast() = (indicemax - indicemin) / 2;
208     myKnots.Append(indicemax);
209   }
210
211   myComputeLine.Init      (myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, Standard_True, myData.parametrization);
212   myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, Standard_True, myData.parametrization);
213
214   buildCurve(theline, NULL);
215 }
216
217 //=======================================================================
218 //function : Perform
219 //purpose  : Definition of next steps according to surface types
220 //            (i.e. coordination algorithm).
221 //=======================================================================
222 void ApproxInt_Approx::Perform(const ThePSurface& Surf1,
223                                const ThePSurface& Surf2,
224                                const Handle(TheWLine)& theline,
225                                const Standard_Boolean ApproxXYZ,
226                                const Standard_Boolean ApproxU1V1,
227                                const Standard_Boolean ApproxU2V2,
228                                const Standard_Integer indicemin,
229                                const Standard_Integer indicemax) 
230 {
231
232   myTolReached3d = myTolReached2d = 0.;
233
234   const GeomAbs_SurfaceType typeS1 = ThePSurfaceTool::GetType(Surf1);
235   const GeomAbs_SurfaceType typeS2 = ThePSurfaceTool::GetType(Surf2);
236
237   const Standard_Boolean isQuadric = ((typeS1 == GeomAbs_Plane) ||
238                                       (typeS1 == GeomAbs_Cylinder) ||
239                                       (typeS1 == GeomAbs_Sphere) ||
240                                       (typeS1 == GeomAbs_Cone) ||
241                                       (typeS2 == GeomAbs_Plane) ||
242                                       (typeS2 == GeomAbs_Cylinder) ||
243                                       (typeS2 == GeomAbs_Sphere) ||
244                                       (typeS2 == GeomAbs_Cone));
245
246   if(isQuadric)
247   {
248     IntSurf_Quadric Quad;
249     Standard_Boolean SecondIsImplicit=Standard_False;
250     switch (typeS1)
251     {
252     case GeomAbs_Plane:
253       Quad.SetValue(ThePSurfaceTool::Plane(Surf1));
254       break;
255
256     case GeomAbs_Cylinder:
257       Quad.SetValue(ThePSurfaceTool::Cylinder(Surf1));
258       break;
259
260     case GeomAbs_Sphere:
261       Quad.SetValue(ThePSurfaceTool::Sphere(Surf1));
262       break;
263
264     case GeomAbs_Cone:
265       Quad.SetValue(ThePSurfaceTool::Cone(Surf1));
266       break;
267
268     default:
269       {
270         SecondIsImplicit = Standard_True;
271         switch (typeS2)
272         {
273         case GeomAbs_Plane:
274           Quad.SetValue(ThePSurfaceTool::Plane(Surf2));
275           break;
276
277         case GeomAbs_Cylinder:
278           Quad.SetValue(ThePSurfaceTool::Cylinder(Surf2));
279           break;
280
281         case GeomAbs_Sphere:
282           Quad.SetValue(ThePSurfaceTool::Sphere(Surf2));
283           break;
284
285         case GeomAbs_Cone:
286           Quad.SetValue(ThePSurfaceTool::Cone(Surf2));
287           break;
288
289         default:
290           break;
291         }//switch (typeS2)
292       }
293
294       break;
295     }//switch (typeS1)
296
297     Perform(Quad, (SecondIsImplicit? Surf1: Surf2), theline,
298             ApproxXYZ, ApproxU1V1, ApproxU2V2,
299             indicemin, indicemax, !SecondIsImplicit);
300
301     return;
302   }
303
304   // Here, isQuadric == FALSE.
305
306   // Prepare DS.
307   prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
308
309   // Non-analytical case: Param-Param perform.
310   ApproxInt_ThePrmPrmSvSurfaces myPrmPrmSvSurfaces(Surf1,Surf2);
311
312   Standard_Integer nbpntbez = indicemax-indicemin;
313
314   if(nbpntbez < aMinNbPointsForApprox)
315   {
316     myData.myBezierApprox = Standard_False;
317   }
318   else 
319   {
320     myData.myBezierApprox = Standard_True;
321   }
322
323   // Fill data structure.
324   fillData(theline);
325
326   const Standard_Boolean cut = myData.myBezierApprox;
327   const Standard_Address ptrsvsurf = &myPrmPrmSvSurfaces;
328
329   // Build knots.
330   buildKnots(theline, ptrsvsurf);
331
332   myComputeLine.Init      ( myDegMin, myDegMax, myTol3d, myTol2d,
333                             myNbIterMax, cut, myData.parametrization);
334   myComputeLineBezier.Init( myDegMin, myDegMax, myTol3d, myTol2d,
335                             myNbIterMax, cut, myData.parametrization);
336
337   buildCurve(theline, ptrsvsurf);
338 }
339
340 //=======================================================================
341 //function : Perform
342 //purpose  : Analytic-Param perform.
343 //=======================================================================
344 void ApproxInt_Approx::Perform(const TheISurface& ISurf,
345                                const ThePSurface& PSurf,
346                                const Handle(TheWLine)& theline,
347                                const Standard_Boolean ApproxXYZ,
348                                const Standard_Boolean ApproxU1V1,
349                                const Standard_Boolean ApproxU2V2,
350                                const Standard_Integer indicemin,
351                                const Standard_Integer indicemax,
352                                const Standard_Boolean isTheQuadFirst)
353 {
354   // Prepare DS.
355   prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
356
357   // Non-analytical case: Analytic-Param perform.
358   ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces = 
359                           isTheQuadFirst? ApproxInt_TheImpPrmSvSurfaces(ISurf, PSurf):
360                                           ApproxInt_TheImpPrmSvSurfaces(PSurf, ISurf);
361
362   myImpPrmSvSurfaces.SetUseSolver(Standard_False);
363
364   const Standard_Integer nbpntbez = indicemax-indicemin;
365   if(nbpntbez < aMinNbPointsForApprox)
366   {
367     myData.myBezierApprox = Standard_False;
368   }
369   else 
370   {
371     myData.myBezierApprox = Standard_True;
372   }
373
374   const Standard_Boolean cut = myData.myBezierApprox;
375   const Standard_Address ptrsvsurf = &myImpPrmSvSurfaces;
376
377   // Fill data structure.
378   fillData(theline);
379
380   // Build knots.
381   buildKnots(theline, ptrsvsurf);
382
383   myComputeLine.Init      ( myDegMin, myDegMax, myTol3d, myTol2d,
384                             myNbIterMax, cut, myData.parametrization);
385   myComputeLineBezier.Init( myDegMin, myDegMax, myTol3d, myTol2d,
386                             myNbIterMax, cut, myData.parametrization);
387
388   buildCurve(theline, ptrsvsurf);
389 }
390
391 //=======================================================================
392 //function : SetParameters
393 //purpose  : 
394 //=======================================================================
395 void ApproxInt_Approx::SetParameters( const Standard_Real Tol3d,
396                                       const Standard_Real Tol2d,
397                                       const Standard_Integer DegMin,
398                                       const Standard_Integer DegMax,
399                                       const Standard_Integer NbIterMax,
400                                       const Standard_Integer NbPntMax,
401                                       const Standard_Boolean ApproxWithTangency,
402                                       const Approx_ParametrizationType Parametrization)
403 {
404   myData.myNbPntMax = NbPntMax;
405   myWithTangency = ApproxWithTangency;
406   myTol3d        = Tol3d/RatioTol;
407   myTol2d        = Tol2d/RatioTol;
408   myDegMin       = DegMin;
409   myDegMax       = DegMax;
410   myNbIterMax    = NbIterMax;
411
412   myComputeLine.Init      ( myDegMin, myDegMax, myTol3d, myTol2d,
413                             myNbIterMax, Standard_True, Parametrization);
414   myComputeLineBezier.Init( myDegMin, myDegMax, myTol3d, myTol2d,
415                             myNbIterMax, Standard_True, Parametrization);
416
417   if(!ApproxWithTangency)
418   { 
419     myComputeLine.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
420     myComputeLineBezier.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
421   }
422   
423   myData.myBezierApprox = Standard_True;
424 }
425
426 //=======================================================================
427 //function : NbMultiCurves
428 //purpose  :
429 //=======================================================================
430 Standard_Integer ApproxInt_Approx::NbMultiCurves() const
431 {
432   return 1;
433 }
434
435 //=======================================================================
436 //function : UpdateTolReached
437 //purpose  :
438 //=======================================================================
439 void ApproxInt_Approx::UpdateTolReached()
440 {
441   if (myData.myBezierApprox)
442   {
443     const Standard_Integer NbCurves = myComputeLineBezier.NbMultiCurves() ;
444     for (Standard_Integer ICur = 1 ; ICur <= NbCurves ; ICur++)
445     {
446       Standard_Real Tol3D, Tol2D ;
447       myComputeLineBezier.Error (ICur, Tol3D, Tol2D) ;
448       myTolReached3d = Max(myTolReached3d, Tol3D);
449       myTolReached2d = Max(myTolReached2d, Tol2D);
450     }
451   }
452   else
453   {
454     myComputeLine.Error (myTolReached3d, myTolReached2d);
455   }
456 }
457
458 //=======================================================================
459 //function : TolReached3d
460 //purpose  :
461 //=======================================================================
462 Standard_Real ApproxInt_Approx::TolReached3d() const
463 {
464   return myTolReached3d * RatioTol;
465 }
466
467 //=======================================================================
468 //function : TolReached2d
469 //purpose  :
470 //=======================================================================
471 Standard_Real ApproxInt_Approx::TolReached2d() const
472 {
473   return myTolReached2d * RatioTol;
474 }
475
476 //=======================================================================
477 //function : IsDone
478 //purpose  :
479 //=======================================================================
480 Standard_Boolean ApproxInt_Approx::IsDone() const
481 {
482   if(myData.myBezierApprox)
483   { 
484     return(myComputeLineBezier.NbMultiCurves() > 0);
485   }
486   else
487   {
488     return(myComputeLine.IsToleranceReached());
489   }
490 }
491
492 //=======================================================================
493 //function : Value
494 //purpose  :
495 //=======================================================================
496 const AppParCurves_MultiBSpCurve& ApproxInt_Approx::Value(const Standard_Integer ) const
497 {
498   if(myData.myBezierApprox)
499   { 
500     return(myBezToBSpl.Value());
501   }
502   else
503   { 
504     return(myComputeLine.Value());
505   }
506 }
507
508 //=======================================================================
509 //function : fillData
510 //purpose  : Fill ApproxInt data structure.
511 //=======================================================================
512 void ApproxInt_Approx::fillData(const Handle(TheWLine)& theline)
513 {
514   if(myData.ApproxXYZ)
515     ComputeTrsf3d(theline, myData.Xo, myData.Yo, myData.Zo);
516   else
517     myData.Xo = myData.Yo = myData.Zo = 0.0;
518
519   if(myData.ApproxU1V1)
520     ComputeTrsf2d(theline, Standard_True, myData.U1o, myData.V1o);
521   else
522     myData.U1o = myData.V1o = 0.0;
523
524   if(myData.ApproxU2V2)
525     ComputeTrsf2d(theline, Standard_False, myData.U2o, myData.V2o);
526   else
527     myData.U2o = myData.V2o = 0.0;
528 }
529
530 //=======================================================================
531 //function : prepareDS
532 //purpose  :
533 //=======================================================================
534 void ApproxInt_Approx::prepareDS(const Standard_Boolean theApproxXYZ,
535                                  const Standard_Boolean theApproxU1V1,
536                                  const Standard_Boolean theApproxU2V2,
537                                  const Standard_Integer theIndicemin,
538                                  const Standard_Integer theIndicemax)
539 {
540   myTolReached3d = myTolReached2d = 0.0;
541   myData.ApproxU1V1 = theApproxU1V1;
542   myData.ApproxU2V2 = theApproxU2V2;
543   myData.ApproxXYZ = theApproxXYZ;
544   myData.indicemin = theIndicemin;
545   myData.indicemax = theIndicemax;
546   myData.parametrization = myComputeLineBezier.Parametrization();
547 }
548
549 //=======================================================================
550 //function : buildKnots
551 //purpose  :
552 //=======================================================================
553 void ApproxInt_Approx::buildKnots(const Handle(TheWLine)& theline,
554                                   const Standard_Address thePtrSVSurf)
555 {
556   myKnots.Clear();
557   if(!myData.myBezierApprox)
558   {
559     myKnots.Append(myData.indicemin);
560     myKnots.Append(myData.indicemax);
561     return;
562   }
563
564   const ApproxInt_TheMultiLine aTestLine( theline, thePtrSVSurf,
565                                           ((myData.ApproxXYZ)? 1 : 0),
566                                           ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
567                                           myData.ApproxU1V1, myData.ApproxU2V2,
568                                           myData.Xo, myData.Yo, myData.Zo,
569                                           myData.U1o, myData.V1o, myData.U2o, myData.V2o,
570                                           myData.ApproxU1V1,
571                                           myData.indicemin, myData.indicemax);
572
573   const Standard_Integer  nbp3d = aTestLine.NbP3d(),
574                           nbp2d = aTestLine.NbP2d();
575   TColgp_Array1OfPnt aTabPnt3d(1, Max(1, nbp3d));
576   TColgp_Array1OfPnt2d aTabPnt2d(1, Max(1, nbp2d));
577   TColgp_Array1OfPnt aPntXYZ(myData.indicemin, myData.indicemax);
578   TColgp_Array1OfPnt2d aPntU1V1(myData.indicemin, myData.indicemax);
579   TColgp_Array1OfPnt2d aPntU2V2(myData.indicemin, myData.indicemax);
580
581   for(Standard_Integer i = myData.indicemin; i <= myData.indicemax; ++i)
582   {
583     if (nbp3d != 0 && nbp2d != 0) aTestLine.Value(i, aTabPnt3d, aTabPnt2d);
584     else if (nbp2d != 0)          aTestLine.Value(i, aTabPnt2d);
585     else if (nbp3d != 0)          aTestLine.Value(i, aTabPnt3d);
586     //
587     if(nbp3d > 0)
588     {
589       aPntXYZ(i) = aTabPnt3d(1);
590     }
591     if(nbp2d > 1)
592     {
593       aPntU1V1(i) = aTabPnt2d(1);
594       aPntU2V2(i) = aTabPnt2d(2);
595     }
596     else if(nbp2d > 0)
597     {
598       if(myData.ApproxU1V1)
599       {
600         aPntU1V1(i) = aTabPnt2d(1);
601       }
602       else
603       {
604         aPntU2V2(i) = aTabPnt2d(1);
605       }
606     }
607   }
608
609   Standard_Integer aMinNbPnts = myData.myNbPntMax;
610
611   // Expected parametrization.
612   math_Vector aPars(myData.indicemin, myData.indicemax);
613   Parameters(aTestLine, myData.indicemin, myData.indicemax, myData.parametrization, aPars);
614
615   ApproxInt_KnotTools::BuildKnots(aPntXYZ, aPntU1V1, aPntU2V2, aPars,
616     myData.ApproxXYZ, myData.ApproxU1V1, myData.ApproxU2V2, aMinNbPnts, myKnots);
617 }
618
619 //=======================================================================
620 //function : buildCurve
621 //purpose  :
622 //=======================================================================
623 void ApproxInt_Approx::buildCurve(const Handle(TheWLine)& theline,
624                                   const Standard_Address thePtrSVSurf)
625 {
626   if(myData.myBezierApprox)
627   {
628     myBezToBSpl.Reset();
629   }
630
631   Standard_Integer kind = myKnots.Lower();
632   Standard_Integer imin = 0, imax = 0;
633   Standard_Boolean OtherInter = Standard_False;
634   do
635   {
636     // Base cycle: iterate over knots.
637     imin = myKnots(kind);
638     imax = myKnots(kind+1);
639     ApproxInt_TheMultiLine myMultiLine(theline, thePtrSVSurf,
640                                        ((myData.ApproxXYZ)? 1 : 0),
641                                        ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
642                                        myData.ApproxU1V1, myData.ApproxU2V2,
643                                        myData.Xo, myData.Yo, myData.Zo, myData.U1o, myData.V1o,
644                                        myData.U2o, myData.V2o, myData.ApproxU1V1, imin, imax);
645
646     if(myData.myBezierApprox)
647     {
648       myComputeLineBezier.Perform(myMultiLine);
649       if (myComputeLineBezier.NbMultiCurves() == 0)
650         return;
651     }
652     else
653     {
654       myComputeLine.Perform(myMultiLine);
655     }
656
657     UpdateTolReached();
658
659     Standard_Integer indice3d = 1, indice2d1 = 2, indice2d2 = 3;
660     if(!myData.ApproxXYZ)  { indice2d1--; indice2d2--; } 
661     if(!myData.ApproxU1V1) { indice2d2--; } 
662     if(myData.ApproxXYZ)
663     { 
664       if(myData.myBezierApprox)
665       {
666         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
667         {
668           myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d, -myData.Xo, 1.0, -myData.Yo, 1.0, -myData.Zo, 1.0);
669         }
670       }
671       else
672       {
673         myComputeLine.ChangeValue().Transform(indice3d, -myData.Xo, 1.0, -myData.Yo, 1.0, -myData.Zo, 1.0);
674       }
675     }
676     if(myData.ApproxU1V1)
677     {
678       if(myData.myBezierApprox) {
679         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
680         {
681           myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1, -myData.U1o, 1.0, -myData.V1o, 1.0);
682         }
683       }
684       else
685       {
686         myComputeLine.ChangeValue().Transform2d(indice2d1, -myData.U1o, 1.0, -myData.V1o, 1.0);
687       }
688     }
689     if(myData.ApproxU2V2)
690     {
691       if(myData.myBezierApprox)
692       {
693         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
694         {
695           myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2, -myData.U2o, 1.0, -myData.V2o, 1.0);
696         }
697       }
698       else
699       {
700         myComputeLine.ChangeValue().Transform2d(indice2d2, -myData.U2o, 1.0, -myData.V2o, 1.0);
701       }
702     }
703
704     OtherInter = Standard_False;
705     if(myData.myBezierApprox)
706     {
707       for(Standard_Integer nbmc = 1; 
708         nbmc <= myComputeLineBezier.NbMultiCurves();
709         nbmc++)
710       {
711           myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
712       }
713       kind++;
714       if(kind < myKnots.Upper())
715       {
716         OtherInter = Standard_True;
717       }
718     }
719   }
720   while(OtherInter);
721
722   if(myData.myBezierApprox)
723   {
724     myBezToBSpl.Perform();
725   }
726 }