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