0024624: Lost word in license statement in source files
[occt.git] / src / Approx / Approx_SweepApproximation.cxx
1 // Created on: 1997-06-25
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1997-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 <Approx_SweepApproximation.ixx>
18 #include <gp_XYZ.hxx>
19 #include <BSplCLib.hxx>
20
21 #include <AdvApprox_ApproxAFunction.hxx>
22 #include <AdvApprox_DichoCutting.hxx>
23 #include <AdvApprox_PrefAndRec.hxx>
24
25 #include <TColgp_Array1OfPnt.hxx>
26 #include <TColgp_Array1OfPnt2d.hxx>
27 #include <TColgp_Array1OfVec.hxx>
28 #include <TColgp_Array1OfVec2d.hxx>
29
30 #include <TColStd_Array1OfReal.hxx>
31
32 #include <StdFail_NotDone.hxx>
33
34 //=======================================================================
35 //class : Approx_SweepApproximation_Eval
36 //purpose: evaluator class for approximation
37 //=======================================================================
38
39 class Approx_SweepApproximation_Eval : public AdvApprox_EvaluatorFunction
40 {
41  public:
42   Approx_SweepApproximation_Eval (Approx_SweepApproximation& theTool)
43     : Tool(theTool) {}
44   
45   virtual void Evaluate (Standard_Integer *Dimension,
46                          Standard_Real     StartEnd[2],
47                          Standard_Real    *Parameter,
48                          Standard_Integer *DerivativeRequest,
49                          Standard_Real    *Result, // [Dimension]
50                          Standard_Integer *ErrorCode);
51   
52  private:
53   Approx_SweepApproximation &Tool;
54 };
55
56 void Approx_SweepApproximation_Eval::Evaluate (Standard_Integer *,/*Dimension*/
57                                                Standard_Real     StartEnd[2],
58                                                Standard_Real    *Parameter,
59                                                Standard_Integer *DerivativeRequest,
60                                                Standard_Real    *Result,// [Dimension]
61                                                Standard_Integer *ErrorCode)
62 {
63   *ErrorCode = Tool.Eval (*Parameter, *DerivativeRequest, 
64                           StartEnd[0], StartEnd[1], Result[0]);
65 }
66
67 Approx_SweepApproximation::
68 Approx_SweepApproximation(const Handle(Approx_SweepFunction)& Func) 
69 {
70   myFunc  = Func;
71   //  Init of variables of control
72   myParam = 0;
73   myOrder = -1;
74   first = 1.e100; last = -1.e100;
75   done = Standard_False;
76 }
77
78 void Approx_SweepApproximation::Perform(const Standard_Real First,
79                                         const Standard_Real Last,
80                                         const Standard_Real Tol3d,
81                                         const Standard_Real BoundTol,
82                                         const Standard_Real Tol2d,
83                                         const Standard_Real TolAngular,
84                                         const GeomAbs_Shape Continuity,
85                                         const Standard_Integer Degmax,
86                                         const Standard_Integer Segmax)
87 {
88  Standard_Integer NbPolSect, NbKnotSect, ii;
89  Standard_Real Tol, Tol3dMin = Tol3d, The3D2DTol=0 ; 
90  GeomAbs_Shape   continuity = Continuity;
91
92 // (1) Characteristics of a section
93  myFunc->SectionShape(NbPolSect, NbKnotSect, udeg);
94  Num2DSS = myFunc->Nb2dCurves();
95  tabUKnots = new (TColStd_HArray1OfReal)    (1, NbKnotSect);
96  tabUMults = new (TColStd_HArray1OfInteger) (1, NbKnotSect);
97  myFunc->Knots(tabUKnots->ChangeArray1());
98  myFunc->Mults(tabUMults->ChangeArray1());
99
100 // (2) Decompositition into sub-spaces
101  Handle(TColStd_HArray1OfReal) OneDTol, TwoDTol, ThreeDTol;
102  Num3DSS = NbPolSect;
103
104 // (2.1) Tolerance 3d and 1d
105  OneDTol = new (TColStd_HArray1OfReal) (1, Num3DSS);
106  ThreeDTol = new (TColStd_HArray1OfReal) (1, Num3DSS);
107
108  myFunc->GetTolerance(BoundTol, Tol3d, TolAngular, 
109                       ThreeDTol->ChangeArray1());
110
111  for (ii=1; ii<=Num3DSS; ii++) 
112    if (ThreeDTol->Value(ii) < Tol3dMin) Tol3dMin = ThreeDTol->Value(ii);
113
114  if (myFunc->IsRational()) {
115    Standard_Real Size;
116    Num1DSS = NbPolSect;
117    TColStd_Array1OfReal Wmin(1, Num1DSS);
118    myFunc->GetMinimalWeight(Wmin);
119    Size =  myFunc->MaximalSection();
120    Translation.SetXYZ
121      (myFunc->BarycentreOfSurf().XYZ());
122    for (ii=1; ii<=Num3DSS; ii++) {
123      Tol =  ThreeDTol->Value(ii)/2; // To take accout of the error on the final result.
124      OneDTol->SetValue(ii, Tol * Wmin(ii) / Size);
125      Tol *= Wmin(ii); //Factor of projection
126      ThreeDTol->SetValue(ii, Max(Tol, 1.e-20) );
127    }
128  }
129  else { Num1DSS = 0; }
130
131  
132 // (2.2) Tolerance and Transformation 2d.
133  if (Num2DSS == 0) {TwoDTol.Nullify();}
134  else {
135    // for 2d define affinity using resolutions, to 
136    // avoid homogenuous tolerance of approximation (u/v and 2d/3d)
137    Standard_Real res, tolu, tolv; 
138    TwoDTol = new (TColStd_HArray1OfReal) (1, Num2DSS);
139    AAffin = new (Approx_HArray1OfGTrsf2d) (1, Num2DSS);
140    The3D2DTol= 0.9*BoundTol; // 10% of security
141    for (ii=1; ii<=Num2DSS; ii++) {
142      myFunc->Resolution(ii, The3D2DTol, tolu, tolv);   
143      if ( tolu> tolv ) {
144        res = tolv;
145        AAffin->ChangeValue(ii).SetValue(1,1, tolv/tolu); 
146      }
147      else {
148        res = tolu;
149        AAffin->ChangeValue(ii).SetValue(2,2, tolu/tolv);
150      }
151      TwoDTol->SetValue(ii, Min( Tol2d, res));
152    }
153  }
154
155 // (3) Approximation
156
157 // Init
158  myPoles = new (TColgp_HArray1OfPnt)(1, Num3DSS);
159  myDPoles = new (TColgp_HArray1OfVec)(1, Num3DSS);
160  myD2Poles = new (TColgp_HArray1OfVec)(1, Num3DSS);
161
162  myWeigths = new (TColStd_HArray1OfReal)(1, Num3DSS);
163  myDWeigths = new (TColStd_HArray1OfReal)(1, Num3DSS);
164  myD2Weigths = new (TColStd_HArray1OfReal)(1, Num3DSS);
165  
166  if (Num2DSS>0) {
167    myPoles2d   = new (TColgp_HArray1OfPnt2d)(1, Num2DSS);
168    myDPoles2d  = new (TColgp_HArray1OfVec2d)(1, Num2DSS);
169    myD2Poles2d = new (TColgp_HArray1OfVec2d)(1, Num2DSS);  
170    COnSurfErr  = new (TColStd_HArray1OfReal)(1, Num2DSS);
171  }
172 // Checks if myFunc->D2 is implemented
173  if (continuity >= GeomAbs_C2) {
174    Standard_Boolean B;
175    B = myFunc->D2(First, First, Last, 
176                   myPoles->ChangeArray1(), myDPoles->ChangeArray1(), 
177                   myD2Poles->ChangeArray1(),
178                   myPoles2d->ChangeArray1(), myDPoles2d->ChangeArray1(), 
179                   myD2Poles2d->ChangeArray1(),
180                   myWeigths->ChangeArray1(), myDWeigths->ChangeArray1(),
181                   myD2Weigths->ChangeArray1());
182    if (!B) continuity =  GeomAbs_C1;
183  }
184 // Checks if myFunc->D1 is implemented
185  if (continuity == GeomAbs_C1) {
186    Standard_Boolean B;
187    B = myFunc->D1(First, First, Last, 
188                   myPoles->ChangeArray1(), myDPoles->ChangeArray1(), 
189                   myPoles2d->ChangeArray1(), myDPoles2d->ChangeArray1(), 
190                   myWeigths->ChangeArray1(), myDWeigths->ChangeArray1());
191    if (!B) continuity =  GeomAbs_C0;
192  }
193
194 // So that F was at least 20 times more exact than its approx
195  myFunc->SetTolerance(Tol3dMin/20, Tol2d/20);
196  
197  Standard_Integer NbIntervalC2 = myFunc->NbIntervals(GeomAbs_C2);
198  Standard_Integer NbIntervalC3 = myFunc->NbIntervals(GeomAbs_C3);
199
200  if (NbIntervalC3 > 1) {
201 // (3.1) Approximation with preferential cut
202    TColStd_Array1OfReal Param_de_decoupeC2 (1, NbIntervalC2+1);
203    myFunc->Intervals(Param_de_decoupeC2, GeomAbs_C2);
204    TColStd_Array1OfReal Param_de_decoupeC3 (1, NbIntervalC3+1);
205    myFunc->Intervals(Param_de_decoupeC3, GeomAbs_C3);
206
207
208    AdvApprox_PrefAndRec Preferentiel(Param_de_decoupeC2,
209                                      Param_de_decoupeC3);
210    
211    Approx_SweepApproximation_Eval ev (*this);
212    Approximation(OneDTol,  TwoDTol, ThreeDTol,
213                  The3D2DTol,
214                  First,     Last, 
215                  continuity,
216                  Degmax,    Segmax, 
217                  ev,
218                  Preferentiel);
219  }
220  else {
221 // (3.2) Approximation without preferential cut
222    AdvApprox_DichoCutting Dichotomie;
223    Approx_SweepApproximation_Eval ev (*this);
224    Approximation(OneDTol,  TwoDTol, ThreeDTol,
225                  The3D2DTol,
226                  First,     Last, 
227                  continuity,
228                  Degmax,    Segmax, 
229                  ev,
230                  Dichotomie);
231  }
232 }
233
234 //========================================================================
235 //function : Approximation
236 //purpose  : Call F(t) and store the results
237 //========================================================================
238 void Approx_SweepApproximation::
239 Approximation(const Handle(TColStd_HArray1OfReal)& OneDTol,
240               const Handle(TColStd_HArray1OfReal)& TwoDTol,
241               const Handle(TColStd_HArray1OfReal)& ThreeDTol,
242               const Standard_Real BoundTol,
243               const Standard_Real First,const Standard_Real Last,
244               const GeomAbs_Shape Continuity,const Standard_Integer Degmax,
245               const Standard_Integer Segmax,
246               const AdvApprox_EvaluatorFunction& TheApproxFunction,
247               const AdvApprox_Cutting& TheCuttingTool) 
248 {
249  AdvApprox_ApproxAFunction Approx(Num1DSS, 
250                                   Num2DSS,
251                                   Num3DSS,
252                                   OneDTol,
253                                   TwoDTol,
254                                   ThreeDTol,
255                                   First,
256                                   Last, 
257                                   Continuity,
258                                   Degmax,
259                                   Segmax, 
260                                   TheApproxFunction,
261                                   TheCuttingTool);
262  done = Approx.HasResult();
263
264  if (done) {
265  // --> Fill Champs of the surface ----
266    Standard_Integer ii, jj;
267
268    vdeg = Approx.Degree();
269    // Unfortunately Adv_Approx stores the transposition of the required 
270    // so, writing tabPoles = Approx.Poles() will give an erroneous result
271    // It is only possible to allocate and recopy term by term...
272    tabPoles = new (TColgp_HArray2OfPnt)
273      (1, Num3DSS, 1, Approx.NbPoles());
274    tabWeights = new (TColStd_HArray2OfReal)
275      (1, Num3DSS, 1, Approx.NbPoles());
276
277    if (Num1DSS == Num3DSS) {
278      Standard_Real wpoid;
279      gp_Pnt P;
280      for (ii=1; ii <=Num3DSS; ii++) {
281        for (jj=1; jj <=Approx.NbPoles() ; jj++) {
282          P = Approx.Poles()->Value(jj,ii);
283          wpoid = Approx.Poles1d()->Value(jj,ii);
284          P.ChangeCoord() /= wpoid; // It is necessary to divide poles by weight
285          P.Translate(Translation); 
286          tabPoles->SetValue  (ii, jj, P);
287          tabWeights->SetValue(ii, jj, wpoid );
288        }
289      }
290    }
291    else {
292      tabWeights->Init(1);
293      for (ii=1; ii <=Num3DSS; ii++) {
294        for (jj=1; jj <=Approx.NbPoles() ; jj++) {
295          tabPoles->SetValue  (ii, jj, Approx.Poles  ()->Value(jj,ii) );
296        }
297      }
298    }
299    
300    // this is better
301    tabVKnots = Approx.Knots();
302    tabVMults = Approx.Multiplicities();
303
304    
305
306   // --> Filling of curves 2D  ----------
307    if (Num2DSS>0) {
308      gp_GTrsf2d TrsfInv;
309      deg2d = vdeg;
310      tab2dKnots = Approx.Knots();
311      tab2dMults = Approx.Multiplicities();
312
313      for (ii=1; ii<=Num2DSS; ii++) {
314        TrsfInv = AAffin->Value(ii).Inverted();
315        Handle(TColgp_HArray1OfPnt2d) P2d = 
316          new (TColgp_HArray1OfPnt2d) (1, Approx.NbPoles());
317        Approx.Poles2d( ii, P2d->ChangeArray1() );
318        // do not forget to apply inverted homothety.
319        for (jj=1; jj<=Approx.NbPoles(); jj++) {
320           TrsfInv.Transforms(P2d->ChangeValue(jj).ChangeCoord());
321         }
322        seqPoles2d.Append(P2d);
323      }
324    }
325   // ---> Filling of errors
326    MError3d = new (TColStd_HArray1OfReal) (1,Num3DSS);
327    AError3d = new (TColStd_HArray1OfReal) (1,Num3DSS);
328    for (ii=1; ii<=Num3DSS; ii++) {
329      MError3d->SetValue(ii, Approx.MaxError(3, ii));
330      AError3d->SetValue(ii, Approx.AverageError(3, ii));
331    }
332
333    if (myFunc->IsRational()) {
334      MError1d = new (TColStd_HArray1OfReal) (1,Num3DSS);
335      AError1d = new (TColStd_HArray1OfReal) (1,Num3DSS);
336      for (ii=1; ii<=Num1DSS; ii++) {
337        MError1d->SetValue(ii, Approx.MaxError(1, ii));
338        AError1d->SetValue(ii, Approx.AverageError(1, ii));
339      }
340    }
341
342    if (Num2DSS>0) {
343      tab2dError = new (TColStd_HArray1OfReal) (1,Num2DSS);
344      Ave2dError = new (TColStd_HArray1OfReal) (1,Num2DSS);
345      for (ii=1; ii<=Num2DSS; ii++) {
346        tab2dError->SetValue(ii, Approx.MaxError(2, ii));
347        Ave2dError->SetValue(ii, Approx.AverageError(2, ii));
348        COnSurfErr->SetValue(ii,
349           (tab2dError->Value(ii)/TwoDTol->Value(ii))*BoundTol);
350      }
351    }     
352  }
353 }
354
355 Standard_Integer Approx_SweepApproximation::Eval(const Standard_Real Parameter,
356                                                  const Standard_Integer DerivativeRequest,
357                                                  const Standard_Real First,
358                                                  const Standard_Real Last,
359                                                  Standard_Real& Result) 
360 {
361  Standard_Integer ier=0;
362  switch (DerivativeRequest) {
363  case 0 : 
364    ier = ( ! D0(Parameter, First, Last, Result));
365    break;
366  case 1 : 
367    ier = ( ! D1(Parameter, First, Last, Result));
368    break;
369  case 2 : 
370    ier = ( ! D2(Parameter, First, Last,Result));
371    break;
372  default :
373    ier = 2;
374  }
375  return ier;
376 }
377
378 Standard_Boolean Approx_SweepApproximation::D0(const Standard_Real Param,
379                                                const Standard_Real First,
380                                                const Standard_Real Last,
381                                                Standard_Real& Result) 
382 {
383   Standard_Integer index, ii;
384   Standard_Boolean Ok=Standard_True;
385   Standard_Real * LocalResult =  &Result;
386
387   // Management of limits
388   if ((first!=First) || (Last!=last)) {
389        myFunc->SetInterval(First, Last);
390      }
391
392   if (! ( (Param==myParam) && (myOrder>=0)
393          && (first==First) && (Last==last)) ) {
394     // Positioning in case when the last operation is not repeated.
395     Ok = myFunc->D0(Param, First, Last,
396                     myPoles->ChangeArray1(),
397                     myPoles2d->ChangeArray1(),
398                     myWeigths->ChangeArray1());
399
400     //  poles3d are multiplied by weight after tranlation.
401     for (ii=1; ii<=Num1DSS; ii++) {
402       myPoles->ChangeValue(ii).ChangeCoord()
403         -= Translation.XYZ();
404       myPoles->ChangeValue(ii).ChangeCoord() 
405         *= myWeigths->Value(ii);
406     }
407
408     //  The transformation is applied to poles 2d.
409     for (ii=1; ii<=Num2DSS; ii++) {
410       AAffin->Value(ii).Transforms(myPoles2d->ChangeValue(ii).ChangeCoord());
411     }
412
413     // Update variables of controle and return
414     first = First;
415     last  = Last;
416     myOrder = 0;
417     myParam = Param;
418   }
419
420   //  Extraction of results
421   index = 0;
422   for (ii=1; ii<=Num1DSS; ii++) {
423     LocalResult[index] = myWeigths->Value(ii);
424     index++;
425   }
426   for (ii=1; ii<=Num2DSS; ii++) {
427     LocalResult[index] =    myPoles2d->Value(ii).X();
428     LocalResult[index+1] =  myPoles2d->Value(ii).Y();
429     index += 2;
430   }
431   for (ii=1; ii<=Num3DSS; ii++, index+=3) {
432     LocalResult[index]   = myPoles->Value(ii).X();
433     LocalResult[index+1] = myPoles->Value(ii).Y();
434     LocalResult[index+2] = myPoles->Value(ii).Z();
435   }
436
437   return Ok;
438 }
439
440 Standard_Boolean Approx_SweepApproximation::D1(const Standard_Real Param,
441                                                const Standard_Real First,
442                                                const Standard_Real Last,
443                                                Standard_Real& Result) 
444 {
445   gp_XY Vcoord;
446   gp_Vec Vaux;
447   Standard_Integer index, ii;
448   Standard_Boolean Ok=Standard_True;
449   Standard_Real * LocalResult =  &Result;
450
451
452   if ((first!=First) || (Last!=last)) {
453     myFunc->SetInterval(First, Last);
454   }
455
456   if (! ( (Param==myParam) && (myOrder>=1)
457          && (first==First) && (Last==last)) ){
458
459     // Positioning 
460     Ok = myFunc->D1(Param, First, Last,
461                     myPoles->ChangeArray1(),
462                     myDPoles->ChangeArray1(),
463                     myPoles2d->ChangeArray1(),
464                     myDPoles2d->ChangeArray1(),
465                     myWeigths->ChangeArray1(),
466                     myDWeigths->ChangeArray1());
467
468     //  Take into account the multiplication of poles3d by weights.
469     //  and the translation.
470     for ( ii=1; ii<=Num1DSS; ii++) {
471       //Translation on the section
472       myPoles->ChangeValue(ii).ChangeCoord()
473         -= Translation.XYZ();
474       // Homothety on all. 
475       const Standard_Real aWeight = myWeigths->Value(ii);
476       myDPoles->ChangeValue(ii) *= aWeight;
477       Vaux.SetXYZ( myPoles->Value(ii).Coord());
478       myDPoles->ChangeValue(ii) += myDWeigths->Value(ii)*Vaux;
479       myPoles->ChangeValue(ii).ChangeCoord() *= aWeight; // for the cash
480     }
481       
482
483     //  Apply transformation 2d to suitable vectors
484     for (ii=1; ii<=Num2DSS; ii++) {
485       Vcoord =  myDPoles2d->Value(ii).XY();
486       AAffin->Value(ii).Transforms(Vcoord);
487       myDPoles2d->ChangeValue(ii).SetXY(Vcoord);
488       AAffin->Value(ii).Transforms(myPoles2d->ChangeValue(ii).ChangeCoord());
489     }
490
491     // Update control variables and return
492     first = First;
493     last  = Last;
494     myOrder = 1;
495     myParam = Param;
496   }
497   
498   //  Extraction of results
499   index = 0;
500   for (ii=1; ii<=Num1DSS; ii++) {
501     LocalResult[index] = myDWeigths->Value(ii);
502     index++;
503   }
504   for (ii=1; ii<=Num2DSS; ii++) {
505     LocalResult[index] =    myDPoles2d->Value(ii).X();
506     LocalResult[index+1] =  myDPoles2d->Value(ii).Y();
507     index += 2;
508   }
509   for (ii=1; ii<=Num3DSS; ii++, index+=3) {
510     LocalResult[index]   = myDPoles->Value(ii).X();
511     LocalResult[index+1] = myDPoles->Value(ii).Y();
512     LocalResult[index+2] = myDPoles->Value(ii).Z();
513   }
514   return Ok;
515 }
516
517 Standard_Boolean Approx_SweepApproximation::D2(const Standard_Real Param,
518                                                const Standard_Real First,
519                                                const Standard_Real Last,
520                                                Standard_Real& Result) 
521 {
522   gp_XY Vcoord;  
523   gp_Vec Vaux;
524   Standard_Integer index, ii;
525   Standard_Boolean Ok=Standard_True;
526   Standard_Real * LocalResult =  &Result;
527
528   // management of limits
529   if ((first!=First) || (Last!=last)) {
530        myFunc->SetInterval(First, Last);
531      }
532
533   if (! ( (Param==myParam) && (myOrder>=2)
534          && (first==First) && (Last==last)) ) {
535     // Positioning in case when the last operation is not repeated
536     Ok = myFunc->D2(Param, First, Last,
537                     myPoles->ChangeArray1(),
538                     myDPoles->ChangeArray1(),
539                     myD2Poles->ChangeArray1(),
540                     myPoles2d->ChangeArray1(),
541                     myDPoles2d->ChangeArray1(),
542                     myD2Poles2d->ChangeArray1(),
543                     myWeigths->ChangeArray1(),
544                     myDWeigths->ChangeArray1(),
545                     myD2Weigths->ChangeArray1());
546
547     //  Multiply poles3d by the weight after tranlations.
548     for (ii=1; ii<=Num1DSS; ii++) {
549       // First translate
550       myPoles->ChangeValue(ii).ChangeCoord()
551         -= Translation.XYZ();
552         
553       //Calculate the second derivative
554       myD2Poles->ChangeValue(ii) *= myWeigths->Value(ii);
555       Vaux.SetXYZ( myDPoles->Value(ii).XYZ());
556       myD2Poles->ChangeValue(ii) += (2*myDWeigths->Value(ii))*Vaux;
557       Vaux.SetXYZ( myPoles->Value(ii).Coord());
558       myD2Poles->ChangeValue(ii) += myD2Weigths->Value(ii)*Vaux;
559
560       //Then the remainder for the cash
561       myDPoles->ChangeValue(ii) *= myWeigths->Value(ii);
562       Vaux.SetXYZ( myPoles->Value(ii).Coord());
563       myDPoles->ChangeValue(ii) += myDWeigths->Value(ii)*Vaux;
564       myPoles->ChangeValue(ii).ChangeCoord() 
565         *= myWeigths->Value(ii); 
566     }
567
568     //  Apply transformation to poles 2d.
569     for (ii=1; ii<=Num2DSS; ii++) {
570       Vcoord =  myD2Poles2d->Value(ii).XY();
571       AAffin->Value(ii).Transforms(Vcoord);
572       myD2Poles2d->ChangeValue(ii).SetXY(Vcoord);
573       Vcoord =  myDPoles2d->Value(ii).XY();
574       AAffin->Value(ii).Transforms(Vcoord);
575       myDPoles2d->ChangeValue(ii).SetXY(Vcoord);
576       AAffin->Value(ii).Transforms(myPoles2d->ChangeValue(ii).ChangeCoord());
577     }
578
579     // Update variables of control and return
580     first = First;
581     last  = Last;
582     myOrder = 2;
583     myParam = Param;
584   }
585
586   //  Extraction of results
587   index = 0;
588   for (ii=1; ii<=Num1DSS; ii++) {
589     LocalResult[index] = myD2Weigths->Value(ii);
590     index++;
591   }
592   for (ii=1; ii<=Num2DSS; ii++) {
593     LocalResult[index] =    myD2Poles2d->Value(ii).X();
594     LocalResult[index+1] =  myD2Poles2d->Value(ii).Y();
595     index += 2;
596   }
597   for (ii=1; ii<=Num3DSS; ii++, index+=3) {
598     LocalResult[index]   = myD2Poles->Value(ii).X();
599     LocalResult[index+1] = myD2Poles->Value(ii).Y();
600     LocalResult[index+2] = myD2Poles->Value(ii).Z();
601   }
602
603   return Ok;
604 }
605
606 void Approx_SweepApproximation::
607 SurfShape(Standard_Integer& UDegree,
608           Standard_Integer& VDegree,Standard_Integer& NbUPoles,
609           Standard_Integer& NbVPoles,
610           Standard_Integer& NbUKnots,
611           Standard_Integer& NbVKnots) const
612 {
613   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
614   UDegree  = udeg;
615   VDegree  = vdeg;
616   NbUPoles = tabPoles->ColLength();
617   NbVPoles = tabPoles->RowLength();
618   NbUKnots = tabUKnots->Length();
619   NbVKnots = tabVKnots->Length();
620 }
621
622 void Approx_SweepApproximation::
623 Surface(TColgp_Array2OfPnt& TPoles,
624         TColStd_Array2OfReal& TWeights,
625         TColStd_Array1OfReal& TUKnots,
626         TColStd_Array1OfReal& TVKnots,
627         TColStd_Array1OfInteger& TUMults,
628         TColStd_Array1OfInteger& TVMults) const
629 {
630   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
631   TPoles   = tabPoles->Array2();
632   TWeights = tabWeights->Array2();
633   TUKnots  = tabUKnots->Array1();
634   TUMults  = tabUMults->Array1();
635   TVKnots  = tabVKnots->Array1();
636   TVMults  = tabVMults->Array1();
637 }
638
639 Standard_Real Approx_SweepApproximation::MaxErrorOnSurf() const
640 {
641  Standard_Integer ii;
642  Standard_Real MaxError = 0, err;
643  if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
644
645  if (myFunc->IsRational()) {
646    TColStd_Array1OfReal Wmin(1, Num1DSS);
647    myFunc->GetMinimalWeight(Wmin);
648    Standard_Real Size = myFunc->MaximalSection();
649    for (ii=1; ii<=Num3DSS; ii++) {
650      err = (Size*MError1d->Value(ii) + MError3d->Value(ii)) / Wmin(ii);
651      if (err>MaxError) MaxError = err;
652    }
653  }
654  else {
655   for (ii=1; ii<=Num3DSS; ii++) {
656      err = MError3d->Value(ii);
657      if (err>MaxError) MaxError = err;
658    } 
659  } 
660  return MaxError;
661 }
662
663  Standard_Real Approx_SweepApproximation::AverageErrorOnSurf() const
664 {
665  Standard_Integer ii;
666  Standard_Real MoyError = 0, err;
667  if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
668
669  if (myFunc->IsRational()) {
670    TColStd_Array1OfReal Wmin(1, Num1DSS);
671    myFunc->GetMinimalWeight(Wmin);
672    Standard_Real Size = myFunc->MaximalSection();
673    for (ii=1; ii<=Num3DSS; ii++) {
674      err = (Size*AError1d->Value(ii) + AError3d->Value(ii)) / Wmin(ii);
675      MoyError += err;
676    }
677  }
678  else {
679   for (ii=1; ii<=Num3DSS; ii++) {
680      err = AError3d->Value(ii);
681      MoyError += err;
682    } 
683  } 
684  return MoyError/Num3DSS;
685 }
686
687
688 void Approx_SweepApproximation::Curves2dShape(Standard_Integer& Degree,
689                                               Standard_Integer& NbPoles,
690                                               Standard_Integer& NbKnots) const
691 {
692   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
693   if (seqPoles2d.Length() == 0) {Standard_DomainError::Raise("Approx_SweepApproximation");}
694   Degree = deg2d;
695   NbPoles = seqPoles2d(1)->Length();
696   NbKnots = tab2dKnots->Length();
697 }
698
699 void Approx_SweepApproximation::Curve2d(const Standard_Integer Index,
700                                         TColgp_Array1OfPnt2d& TPoles,
701                                         TColStd_Array1OfReal& TKnots,
702                                         TColStd_Array1OfInteger& TMults) const
703 {
704   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
705   if (seqPoles2d.Length() == 0) {Standard_DomainError::Raise("Approx_SweepApproximation");}
706   TPoles = seqPoles2d(Index)->Array1();
707   TKnots  = tab2dKnots->Array1();
708   TMults  = tab2dMults->Array1(); 
709 }
710
711  Standard_Real Approx_SweepApproximation::Max2dError(const Standard_Integer Index) const
712 {
713   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
714   return tab2dError->Value(Index);
715 }
716
717  Standard_Real Approx_SweepApproximation::Average2dError(const Standard_Integer Index) const
718 {
719   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
720   return Ave2dError->Value(Index); 
721 }
722
723 Standard_Real Approx_SweepApproximation::TolCurveOnSurf(const Standard_Integer Index) const
724 {
725   if (!done) {StdFail_NotDone::Raise("Approx_SweepApproximation");}
726   return  COnSurfErr->Value(Index);
727 }
728
729  void Approx_SweepApproximation::Dump(Standard_OStream& o) const
730 {
731   o << "Dump of SweepApproximation" << endl;
732   if (done) { 
733     o << "Error 3d = " << MaxErrorOnSurf() << endl;
734
735     if (Num2DSS>0) {
736       o << "Error 2d = ";
737       for (Standard_Integer ii=1; ii<=Num2DSS; ii++) 
738         {  o << Max2dError(ii);
739            if (ii < Num2DSS) o << " , " << endl;
740          }
741       cout << endl;
742     }
743     o <<  tabVKnots->Length()-1 <<" Segment(s) of degree " << vdeg << endl;
744   }
745   else cout << " Not Done " << endl;
746 }