0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[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 static void 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   gp_Pnt P1, P2;
103   gp_Pnt2d P12d, P22d;
104
105   if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
106     nbP3d = ApproxInt_TheMultiLineTool::NbP3d(Line);
107     nbP2d = ApproxInt_TheMultiLineTool::NbP2d(Line);
108     Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
109     if (nbP3d == 0) mynbP3d = 1;
110     if (nbP2d == 0) mynbP2d = 1;
111
112     TheParameters(firstP) = 0.0;
113     dist = 0.0;
114     TColgp_Array1OfPnt tabP(1, mynbP3d);
115     TColgp_Array1OfPnt tabPP(1, mynbP3d);
116     TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
117     TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
118
119     for (i = firstP+1; i <= lastP; i++) {
120       if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP, tabP2d);
121       else if (nbP2d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP2d);
122       else if (nbP3d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP);
123
124       if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP, tabPP2d);
125       else if (nbP2d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i, tabPP2d);
126       else if (nbP3d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i, tabPP);
127       dist = 0;
128       for (j = 1; j <= nbP3d; j++) {
129         P1 = tabP(j);
130         P2 = tabPP(j);
131         dist += P2.Distance(P1);
132       }
133       for (j = 1; j <= nbP2d; j++) {
134         P12d = tabP2d(j);
135         P22d = tabPP2d(j);
136         dist += P22d.Distance(P12d);
137       }
138       if(Par == Approx_ChordLength)
139         TheParameters(i) = TheParameters(i-1) + dist;
140       else {// Par == Approx_Centripetal
141         TheParameters(i) = TheParameters(i-1) + Sqrt(dist);
142       }
143     }
144     for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
145   }
146   else {
147     for (i = firstP; i <= lastP; i++) {
148       TheParameters(i) = (Standard_Real(i)-firstP)/
149         (Standard_Real(lastP)-Standard_Real(firstP));
150     }
151   }
152 }
153
154 //=======================================================================
155 //function : Default constructor
156 //purpose  : 
157 //=======================================================================
158 ApproxInt_Approx::ApproxInt_Approx():
159                       myComputeLine(4, 8, 0.001, 0.001, 5),
160                       myComputeLineBezier(4, 8, 0.001, 0.001, 5),
161                       myWithTangency(Standard_True),
162                       myTol3d(0.001),
163                       myTol2d(0.001),
164                       myDegMin(4),
165                       myDegMax(8),
166                       myNbIterMax(5),
167                       myTolReached3d(0.0),
168                       myTolReached2d(0.0)
169 {
170   myComputeLine.SetContinuity(2);
171   //myComputeLineBezier.SetContinuity(2);
172 }
173
174 //=======================================================================
175 //function : Perform
176 //purpose  : Build without surfaces information.
177 //=======================================================================
178 void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline,
179                                const Standard_Boolean ApproxXYZ,
180                                const Standard_Boolean ApproxU1V1,
181                                const Standard_Boolean ApproxU2V2,
182                                const Standard_Integer indicemin,
183                                const Standard_Integer indicemax)
184 {
185   // Prepare DS.
186   prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
187
188   const Standard_Integer nbpntbez = myData.indicemax - myData.indicemin;
189   if(nbpntbez < aMinNbPointsForApprox) 
190     myData.myBezierApprox = Standard_False;
191   else 
192     myData.myBezierApprox = Standard_True;
193
194   // Fill data structure.
195   fillData(theline);
196
197   // Build knots.
198   buildKnots(theline, NULL);
199   if (myKnots.Length() == 2 &&
200       indicemax - indicemin > 2 * myData.myNbPntMax)
201   {
202     // At least 3 knots for BrepApprox.
203     myKnots.ChangeLast() = (indicemax - indicemin) / 2;
204     myKnots.Append(indicemax);
205   }
206
207   myComputeLine.Init      (myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, Standard_True, myData.parametrization);
208   myComputeLineBezier.Init(myDegMin, myDegMax, myTol3d, myTol2d, myNbIterMax, Standard_True, myData.parametrization);
209
210   buildCurve(theline, NULL);
211 }
212
213 //=======================================================================
214 //function : Perform
215 //purpose  : Definition of next steps according to surface types
216 //            (i.e. coordination algorithm).
217 //=======================================================================
218 void ApproxInt_Approx::Perform(const ThePSurface& Surf1,
219                                const ThePSurface& Surf2,
220                                const Handle(TheWLine)& theline,
221                                const Standard_Boolean ApproxXYZ,
222                                const Standard_Boolean ApproxU1V1,
223                                const Standard_Boolean ApproxU2V2,
224                                const Standard_Integer indicemin,
225                                const Standard_Integer indicemax) 
226 {
227
228   myTolReached3d = myTolReached2d = 0.;
229
230   const GeomAbs_SurfaceType typeS1 = ThePSurfaceTool::GetType(Surf1);
231   const GeomAbs_SurfaceType typeS2 = ThePSurfaceTool::GetType(Surf2);
232
233   const Standard_Boolean isQuadric = ((typeS1 == GeomAbs_Plane) ||
234                                       (typeS1 == GeomAbs_Cylinder) ||
235                                       (typeS1 == GeomAbs_Sphere) ||
236                                       (typeS1 == GeomAbs_Cone) ||
237                                       (typeS2 == GeomAbs_Plane) ||
238                                       (typeS2 == GeomAbs_Cylinder) ||
239                                       (typeS2 == GeomAbs_Sphere) ||
240                                       (typeS2 == GeomAbs_Cone));
241
242   if(isQuadric)
243   {
244     IntSurf_Quadric Quad;
245     Standard_Boolean SecondIsImplicit=Standard_False;
246     switch (typeS1)
247     {
248     case GeomAbs_Plane:
249       Quad.SetValue(ThePSurfaceTool::Plane(Surf1));
250       break;
251
252     case GeomAbs_Cylinder:
253       Quad.SetValue(ThePSurfaceTool::Cylinder(Surf1));
254       break;
255
256     case GeomAbs_Sphere:
257       Quad.SetValue(ThePSurfaceTool::Sphere(Surf1));
258       break;
259
260     case GeomAbs_Cone:
261       Quad.SetValue(ThePSurfaceTool::Cone(Surf1));
262       break;
263
264     default:
265       {
266         SecondIsImplicit = Standard_True;
267         switch (typeS2)
268         {
269         case GeomAbs_Plane:
270           Quad.SetValue(ThePSurfaceTool::Plane(Surf2));
271           break;
272
273         case GeomAbs_Cylinder:
274           Quad.SetValue(ThePSurfaceTool::Cylinder(Surf2));
275           break;
276
277         case GeomAbs_Sphere:
278           Quad.SetValue(ThePSurfaceTool::Sphere(Surf2));
279           break;
280
281         case GeomAbs_Cone:
282           Quad.SetValue(ThePSurfaceTool::Cone(Surf2));
283           break;
284
285         default:
286           break;
287         }//switch (typeS2)
288       }
289
290       break;
291     }//switch (typeS1)
292
293     Perform(Quad, (SecondIsImplicit? Surf1: Surf2), theline,
294             ApproxXYZ, ApproxU1V1, ApproxU2V2,
295             indicemin, indicemax, !SecondIsImplicit);
296
297     return;
298   }
299
300   // Here, isQuadric == FALSE.
301
302   // Prepare DS.
303   prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
304
305   // Non-analytical case: Param-Param perform.
306   ApproxInt_ThePrmPrmSvSurfaces myPrmPrmSvSurfaces(Surf1,Surf2);
307
308   Standard_Integer nbpntbez = indicemax-indicemin;
309
310   if(nbpntbez < aMinNbPointsForApprox)
311   {
312     myData.myBezierApprox = Standard_False;
313   }
314   else 
315   {
316     myData.myBezierApprox = Standard_True;
317   }
318
319   // Fill data structure.
320   fillData(theline);
321
322   const Standard_Boolean cut = myData.myBezierApprox;
323   const Standard_Address ptrsvsurf = &myPrmPrmSvSurfaces;
324
325   // Build knots.
326   buildKnots(theline, ptrsvsurf);
327
328   myComputeLine.Init      ( myDegMin, myDegMax, myTol3d, myTol2d,
329                             myNbIterMax, cut, myData.parametrization);
330   myComputeLineBezier.Init( myDegMin, myDegMax, myTol3d, myTol2d,
331                             myNbIterMax, cut, myData.parametrization);
332
333   buildCurve(theline, ptrsvsurf);
334 }
335
336 //=======================================================================
337 //function : Perform
338 //purpose  : Analytic-Param perform.
339 //=======================================================================
340 void ApproxInt_Approx::Perform(const TheISurface& ISurf,
341                                const ThePSurface& PSurf,
342                                const Handle(TheWLine)& theline,
343                                const Standard_Boolean ApproxXYZ,
344                                const Standard_Boolean ApproxU1V1,
345                                const Standard_Boolean ApproxU2V2,
346                                const Standard_Integer indicemin,
347                                const Standard_Integer indicemax,
348                                const Standard_Boolean isTheQuadFirst)
349 {
350   // Prepare DS.
351   prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
352
353   // Non-analytical case: Analytic-Param perform.
354   ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces = 
355                           isTheQuadFirst? ApproxInt_TheImpPrmSvSurfaces(ISurf, PSurf):
356                                           ApproxInt_TheImpPrmSvSurfaces(PSurf, ISurf);
357
358   const Standard_Integer nbpntbez = indicemax-indicemin;
359   if(nbpntbez < aMinNbPointsForApprox)
360   {
361     myData.myBezierApprox = Standard_False;
362   }
363   else 
364   {
365     myData.myBezierApprox = Standard_True;
366   }
367
368   const Standard_Boolean cut = myData.myBezierApprox;
369   const Standard_Address ptrsvsurf = &myImpPrmSvSurfaces;
370
371   // Fill data structure.
372   fillData(theline);
373
374   // Build knots.
375   buildKnots(theline, ptrsvsurf);
376
377   myComputeLine.Init      ( myDegMin, myDegMax, myTol3d, myTol2d,
378                             myNbIterMax, cut, myData.parametrization);
379   myComputeLineBezier.Init( myDegMin, myDegMax, myTol3d, myTol2d,
380                             myNbIterMax, cut, myData.parametrization);
381
382   buildCurve(theline, ptrsvsurf);
383 }
384
385 //=======================================================================
386 //function : SetParameters
387 //purpose  : 
388 //=======================================================================
389 void ApproxInt_Approx::SetParameters( const Standard_Real Tol3d,
390                                       const Standard_Real Tol2d,
391                                       const Standard_Integer DegMin,
392                                       const Standard_Integer DegMax,
393                                       const Standard_Integer NbIterMax,
394                                       const Standard_Integer NbPntMax,
395                                       const Standard_Boolean ApproxWithTangency,
396                                       const Approx_ParametrizationType Parametrization)
397 {
398   myData.myNbPntMax = NbPntMax;
399   myWithTangency = ApproxWithTangency;
400   myTol3d        = Tol3d/RatioTol;
401   myTol2d        = Tol2d/RatioTol;
402   myDegMin       = DegMin;
403   myDegMax       = DegMax;
404   myNbIterMax    = NbIterMax;
405
406   myComputeLine.Init      ( myDegMin, myDegMax, myTol3d, myTol2d,
407                             myNbIterMax, Standard_True, Parametrization);
408   myComputeLineBezier.Init( myDegMin, myDegMax, myTol3d, myTol2d,
409                             myNbIterMax, Standard_True, Parametrization);
410
411   if(!ApproxWithTangency)
412   { 
413     myComputeLine.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
414     myComputeLineBezier.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
415   }
416   
417   myData.myBezierApprox = Standard_True;
418 }
419
420 //=======================================================================
421 //function : NbMultiCurves
422 //purpose  :
423 //=======================================================================
424 Standard_Integer ApproxInt_Approx::NbMultiCurves() const
425 {
426   return 1;
427 }
428
429 //=======================================================================
430 //function : UpdateTolReached
431 //purpose  :
432 //=======================================================================
433 void ApproxInt_Approx::UpdateTolReached()
434 {
435   if (myData.myBezierApprox)
436   {
437     const Standard_Integer NbCurves = myComputeLineBezier.NbMultiCurves() ;
438     for (Standard_Integer ICur = 1 ; ICur <= NbCurves ; ICur++)
439     {
440       Standard_Real Tol3D, Tol2D ;
441       myComputeLineBezier.Error (ICur, Tol3D, Tol2D) ;
442       myTolReached3d = Max(myTolReached3d, Tol3D);
443       myTolReached2d = Max(myTolReached2d, Tol2D);
444     }
445   }
446   else
447   {
448     myComputeLine.Error (myTolReached3d, myTolReached2d);
449   }
450 }
451
452 //=======================================================================
453 //function : TolReached3d
454 //purpose  :
455 //=======================================================================
456 Standard_Real ApproxInt_Approx::TolReached3d() const
457 {
458   return myTolReached3d * RatioTol;
459 }
460
461 //=======================================================================
462 //function : TolReached2d
463 //purpose  :
464 //=======================================================================
465 Standard_Real ApproxInt_Approx::TolReached2d() const
466 {
467   return myTolReached2d * RatioTol;
468 }
469
470 //=======================================================================
471 //function : IsDone
472 //purpose  :
473 //=======================================================================
474 Standard_Boolean ApproxInt_Approx::IsDone() const
475 {
476   if(myData.myBezierApprox)
477   { 
478     return(myComputeLineBezier.NbMultiCurves() > 0);
479   }
480   else
481   {
482     return(myComputeLine.IsToleranceReached());
483   }
484 }
485
486 //=======================================================================
487 //function : Value
488 //purpose  :
489 //=======================================================================
490 const AppParCurves_MultiBSpCurve& ApproxInt_Approx::Value(const Standard_Integer ) const
491 {
492   if(myData.myBezierApprox)
493   { 
494     return(myBezToBSpl.Value());
495   }
496   else
497   { 
498     return(myComputeLine.Value());
499   }
500 }
501
502 //=======================================================================
503 //function : fillData
504 //purpose  : Fill ApproxInt data structure.
505 //=======================================================================
506 void ApproxInt_Approx::fillData(const Handle(TheWLine)& theline)
507 {
508   if(myData.ApproxXYZ)
509     ComputeTrsf3d(theline, myData.Xo, myData.Yo, myData.Zo);
510   else
511     myData.Xo = myData.Yo = myData.Zo = 0.0;
512
513   if(myData.ApproxU1V1)
514     ComputeTrsf2d(theline, Standard_True, myData.U1o, myData.V1o);
515   else
516     myData.U1o = myData.V1o = 0.0;
517
518   if(myData.ApproxU2V2)
519     ComputeTrsf2d(theline, Standard_False, myData.U2o, myData.V2o);
520   else
521     myData.U2o = myData.V2o = 0.0;
522 }
523
524 //=======================================================================
525 //function : prepareDS
526 //purpose  :
527 //=======================================================================
528 void ApproxInt_Approx::prepareDS(const Standard_Boolean theApproxXYZ,
529                                  const Standard_Boolean theApproxU1V1,
530                                  const Standard_Boolean theApproxU2V2,
531                                  const Standard_Integer theIndicemin,
532                                  const Standard_Integer theIndicemax)
533 {
534   myTolReached3d = myTolReached2d = 0.0;
535   myData.ApproxU1V1 = theApproxU1V1;
536   myData.ApproxU2V2 = theApproxU2V2;
537   myData.ApproxXYZ = theApproxXYZ;
538   myData.indicemin = theIndicemin;
539   myData.indicemax = theIndicemax;
540   myData.parametrization = myComputeLineBezier.Parametrization();
541 }
542
543 //=======================================================================
544 //function : buildKnots
545 //purpose  :
546 //=======================================================================
547 void ApproxInt_Approx::buildKnots(const Handle(TheWLine)& theline,
548                                   const Standard_Address thePtrSVSurf)
549 {
550   myKnots.Clear();
551   if(!myData.myBezierApprox)
552   {
553     myKnots.Append(myData.indicemin);
554     myKnots.Append(myData.indicemax);
555     return;
556   }
557
558   const ApproxInt_TheMultiLine aTestLine( theline, thePtrSVSurf,
559                                           ((myData.ApproxXYZ)? 1 : 0),
560                                           ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
561                                           myData.ApproxU1V1, myData.ApproxU2V2,
562                                           myData.Xo, myData.Yo, myData.Zo,
563                                           myData.U1o, myData.V1o, myData.U2o, myData.V2o,
564                                           myData.ApproxU1V1,
565                                           myData.indicemin, myData.indicemax);
566
567   const Standard_Integer  nbp3d = aTestLine.NbP3d(),
568                           nbp2d = aTestLine.NbP2d();
569   TColgp_Array1OfPnt aTabPnt3d(1, Max(1, nbp3d));
570   TColgp_Array1OfPnt2d aTabPnt2d(1, Max(1, nbp2d));
571   TColgp_Array1OfPnt aPntXYZ(myData.indicemin, myData.indicemax);
572   TColgp_Array1OfPnt2d aPntU1V1(myData.indicemin, myData.indicemax);
573   TColgp_Array1OfPnt2d aPntU2V2(myData.indicemin, myData.indicemax);
574
575   for(Standard_Integer i = myData.indicemin; i <= myData.indicemax; ++i)
576   {
577     if (nbp3d != 0 && nbp2d != 0) aTestLine.Value(i, aTabPnt3d, aTabPnt2d);
578     else if (nbp2d != 0)          aTestLine.Value(i, aTabPnt2d);
579     else if (nbp3d != 0)          aTestLine.Value(i, aTabPnt3d);
580     //
581     if(nbp3d > 0)
582     {
583       aPntXYZ(i) = aTabPnt3d(1);
584     }
585     if(nbp2d > 1)
586     {
587       aPntU1V1(i) = aTabPnt2d(1);
588       aPntU2V2(i) = aTabPnt2d(2);
589     }
590     else if(nbp2d > 0)
591     {
592       if(myData.ApproxU1V1)
593       {
594         aPntU1V1(i) = aTabPnt2d(1);
595       }
596       else
597       {
598         aPntU2V2(i) = aTabPnt2d(1);
599       }
600     }
601   }
602
603   Standard_Integer aMinNbPnts = myData.myNbPntMax;
604
605   // Expected parametrization.
606   math_Vector aPars(myData.indicemin, myData.indicemax);
607   Parameters(aTestLine, myData.indicemin, myData.indicemax, myData.parametrization, aPars);
608
609   ApproxInt_KnotTools::BuildKnots(aPntXYZ, aPntU1V1, aPntU2V2, aPars,
610     myData.ApproxXYZ, myData.ApproxU1V1, myData.ApproxU2V2, aMinNbPnts, myKnots);
611 }
612
613 //=======================================================================
614 //function : buildCurve
615 //purpose  :
616 //=======================================================================
617 void ApproxInt_Approx::buildCurve(const Handle(TheWLine)& theline,
618                                   const Standard_Address thePtrSVSurf)
619 {
620   if(myData.myBezierApprox)
621   {
622     myBezToBSpl.Reset();
623   }
624
625   Standard_Integer kind = myKnots.Lower();
626   Standard_Integer imin = 0, imax = 0;
627   Standard_Boolean OtherInter = Standard_False;
628   do
629   {
630     // Base cycle: iterate over knots.
631     imin = myKnots(kind);
632     imax = myKnots(kind+1);
633     ApproxInt_TheMultiLine myMultiLine(theline, thePtrSVSurf,
634                                        ((myData.ApproxXYZ)? 1 : 0),
635                                        ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
636                                        myData.ApproxU1V1, myData.ApproxU2V2,
637                                        myData.Xo, myData.Yo, myData.Zo, myData.U1o, myData.V1o,
638                                        myData.U2o, myData.V2o, myData.ApproxU1V1, imin, imax);
639
640     if(myData.myBezierApprox)
641     {
642       myComputeLineBezier.Perform(myMultiLine);
643       if (myComputeLineBezier.NbMultiCurves() == 0)
644         return;
645     }
646     else
647     {
648       myComputeLine.Perform(myMultiLine);
649     }
650
651     UpdateTolReached();
652
653     Standard_Integer indice3d = 1, indice2d1 = 2, indice2d2 = 3;
654     if(!myData.ApproxXYZ)  { indice2d1--; indice2d2--; } 
655     if(!myData.ApproxU1V1) { indice2d2--; } 
656     if(myData.ApproxXYZ)
657     { 
658       if(myData.myBezierApprox)
659       {
660         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
661         {
662           myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d, -myData.Xo, 1.0, -myData.Yo, 1.0, -myData.Zo, 1.0);
663         }
664       }
665       else
666       {
667         myComputeLine.ChangeValue().Transform(indice3d, -myData.Xo, 1.0, -myData.Yo, 1.0, -myData.Zo, 1.0);
668       }
669     }
670     if(myData.ApproxU1V1)
671     {
672       if(myData.myBezierApprox) {
673         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
674         {
675           myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1, -myData.U1o, 1.0, -myData.V1o, 1.0);
676         }
677       }
678       else
679       {
680         myComputeLine.ChangeValue().Transform2d(indice2d1, -myData.U1o, 1.0, -myData.V1o, 1.0);
681       }
682     }
683     if(myData.ApproxU2V2)
684     {
685       if(myData.myBezierApprox)
686       {
687         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
688         {
689           myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2, -myData.U2o, 1.0, -myData.V2o, 1.0);
690         }
691       }
692       else
693       {
694         myComputeLine.ChangeValue().Transform2d(indice2d2, -myData.U2o, 1.0, -myData.V2o, 1.0);
695       }
696     }
697
698     OtherInter = Standard_False;
699     if(myData.myBezierApprox)
700     {
701       for(Standard_Integer nbmc = 1; 
702         nbmc <= myComputeLineBezier.NbMultiCurves();
703         nbmc++)
704       {
705           myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
706       }
707       kind++;
708       if(kind < myKnots.Upper())
709       {
710         OtherInter = Standard_True;
711       }
712     }
713   }
714   while(OtherInter);
715
716   if(myData.myBezierApprox)
717   {
718     myBezToBSpl.Perform();
719   }
720 }