7f03fff0cfaef6b87f1b48d00578305371880a8c
[occt.git] / src / AdvApp2Var / AdvApp2Var_ApproxAFunc2Var.cxx
1 // File:        AdvApp2Var_ApproxAFunc2Var.cxx
2 // Created:     Wed Jul  3 15:34:08 1996
3 // Author:      Joelle CHAUVET
4 //              <jct@sgi38>
5 // Modified:    Wed Jan 15 10:04:41 1997
6 //    by:       Joelle CHAUVET
7 //              G1135 : Constructor with criterion
8 //                      Private methods 'Init','InitGrid','Perform','ConvertBS',
9 //                                      'ComputePatches','ComputeConstraints',
10 //                                      'Compute3DErrors','ComputeCritError'
11 //                      Public method 'CritError'
12 //                      Fields 'myConditions','myResults','myConstraints'
13 // Modified:    Fri Oct  3 14:58:05 1997
14 //    by:       Joelle CHAUVET
15 //              GeomConvert_CompBezierSurfacesToBSplineSurface est remplace par 
16 //              Convert_GridPolynomialToPoles dans ConvertBS 
17
18 #include <AdvApp2Var_ApproxAFunc2Var.hxx>
19 #include <AdvApp2Var_EvaluatorFunc2Var.hxx>
20 #include <AdvApp2Var_Criterion.hxx>
21 #include <AdvApp2Var_Context.hxx>
22 #include <AdvApp2Var_Patch.hxx>
23 #include <AdvApp2Var_Network.hxx>
24 #include <AdvApp2Var_Node.hxx>
25 #include <AdvApp2Var_Iso.hxx>
26 #include <AdvApp2Var_Strip.hxx>
27 #include <AdvApp2Var_Framework.hxx>
28 #include <AdvApprox_Cutting.hxx>
29
30 #include <Standard_ConstructionError.hxx>
31 #include <Standard_OutOfRange.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TColStd_HArray2OfInteger.hxx>
34 #include <TColStd_HArray1OfReal.hxx>
35 #include <TColStd_HArray2OfReal.hxx>
36
37 #include <gp_XY.hxx>
38 #include <gp_Pnt2d.hxx>
39 #include <gp_Pnt.hxx>
40 #include <TColgp_HArray2OfPnt.hxx>
41
42 #include <Convert_GridPolynomialToPoles.hxx>
43
44 #include <Geom_BezierSurface.hxx>
45
46
47 //=======================================================================
48 //function : AdvApp2Var_ApproxAFunc2Var
49 //purpose  : 
50 //=======================================================================
51
52  AdvApp2Var_ApproxAFunc2Var::
53 AdvApp2Var_ApproxAFunc2Var(const Standard_Integer Num1DSS,
54                            const Standard_Integer Num2DSS,
55                            const Standard_Integer Num3DSS,
56                            const Handle(TColStd_HArray1OfReal)& OneDTol,
57                            const Handle(TColStd_HArray1OfReal)& TwoDTol,
58                            const Handle(TColStd_HArray1OfReal)& ThreeDTol,
59                            const Handle(TColStd_HArray2OfReal)& OneDTolFr,
60                            const Handle(TColStd_HArray2OfReal)& TwoDTolFr,
61                            const Handle(TColStd_HArray2OfReal)& ThreeDTolFr,
62                            const Standard_Real FirstInU,
63                            const Standard_Real LastInU,
64                            const Standard_Real FirstInV,
65                            const Standard_Real LastInV,
66                            const GeomAbs_IsoType FavorIso,
67                            const GeomAbs_Shape ContInU,
68                            const GeomAbs_Shape ContInV,
69                            const Standard_Integer PrecisCode,
70                            const Standard_Integer MaxDegInU,
71                            const Standard_Integer MaxDegInV,
72                            const Standard_Integer MaxPatch,
73                            const AdvApp2Var_EvaluatorFunc2Var& Func,
74                            AdvApprox_Cutting& UChoice,
75                            AdvApprox_Cutting& VChoice) :
76 my1DTolerances(OneDTol),
77 my2DTolerances(TwoDTol),
78 my3DTolerances(ThreeDTol),
79 my1DTolOnFront(OneDTolFr),
80 my2DTolOnFront(TwoDTolFr),
81 my3DTolOnFront(ThreeDTolFr),
82 myFirstParInU(FirstInU),
83 myLastParInU(LastInU),
84 myFirstParInV(FirstInV),
85 myLastParInV(LastInV),
86 myFavoriteIso(FavorIso),
87 myContInU(ContInU),
88 myContInV(ContInV),
89 myPrecisionCode(PrecisCode),
90 myMaxDegInU(MaxDegInU),
91 myMaxDegInV(MaxDegInV),
92 myMaxPatches(MaxPatch),
93 myEvaluator(Func),
94 myDone(Standard_False),
95 myHasResult(Standard_False)
96 {
97   myNumSubSpaces[0] = Num1DSS;
98   myNumSubSpaces[1] = Num2DSS;
99   myNumSubSpaces[2] = Num3DSS;
100   Init();
101   Perform(UChoice,VChoice,Func);
102   ConvertBS();
103 }
104
105 //=======================================================================
106 //function : AdvApp2Var_ApproxAFunc2Var
107 //purpose  : 
108 //=======================================================================
109
110  AdvApp2Var_ApproxAFunc2Var::
111 AdvApp2Var_ApproxAFunc2Var(const Standard_Integer Num1DSS,
112                            const Standard_Integer Num2DSS,
113                            const Standard_Integer Num3DSS,
114                            const Handle(TColStd_HArray1OfReal)& OneDTol,
115                            const Handle(TColStd_HArray1OfReal)& TwoDTol,
116                            const Handle(TColStd_HArray1OfReal)& ThreeDTol,
117                            const Handle(TColStd_HArray2OfReal)& OneDTolFr,
118                            const Handle(TColStd_HArray2OfReal)& TwoDTolFr,
119                            const Handle(TColStd_HArray2OfReal)& ThreeDTolFr,
120                            const Standard_Real FirstInU,
121                            const Standard_Real LastInU,
122                            const Standard_Real FirstInV,
123                            const Standard_Real LastInV,
124                            const GeomAbs_IsoType FavorIso,
125                            const GeomAbs_Shape ContInU,
126                            const GeomAbs_Shape ContInV,
127                            const Standard_Integer PrecisCode,
128                            const Standard_Integer MaxDegInU,
129                            const Standard_Integer MaxDegInV,
130                            const Standard_Integer MaxPatch,
131                            const AdvApp2Var_EvaluatorFunc2Var& Func,
132                            const AdvApp2Var_Criterion& Crit,
133                            AdvApprox_Cutting& UChoice,
134                            AdvApprox_Cutting& VChoice) :
135 my1DTolerances(OneDTol),
136 my2DTolerances(TwoDTol),
137 my3DTolerances(ThreeDTol),
138 my1DTolOnFront(OneDTolFr),
139 my2DTolOnFront(TwoDTolFr),
140 my3DTolOnFront(ThreeDTolFr),
141 myFirstParInU(FirstInU),
142 myLastParInU(LastInU),
143 myFirstParInV(FirstInV),
144 myLastParInV(LastInV),
145 myFavoriteIso(FavorIso),
146 myContInU(ContInU),
147 myContInV(ContInV),
148 myPrecisionCode(PrecisCode),
149 myMaxDegInU(MaxDegInU),
150 myMaxDegInV(MaxDegInV),
151 myMaxPatches(MaxPatch),
152 myEvaluator(Func),
153 myDone(Standard_False),
154 myHasResult(Standard_False)
155 {
156   myNumSubSpaces[0] = Num1DSS;
157   myNumSubSpaces[1] = Num2DSS;
158   myNumSubSpaces[2] = Num3DSS;
159   Init();
160   Perform(UChoice,VChoice,Func,Crit);
161   ConvertBS();
162 }
163
164 //=======================================================================
165 //function : Init
166 //purpose  : Initialisation of the approximation
167 //=======================================================================
168
169 void AdvApp2Var_ApproxAFunc2Var::Init()
170 {
171   Standard_Integer ifav,iu=0,iv=0,ndu,ndv;
172   switch (myFavoriteIso) {
173   case GeomAbs_IsoU :
174     ifav = 1;
175     break;
176   case GeomAbs_IsoV :
177     ifav = 2;
178     break;
179   default :
180     ifav = 2;
181     break;
182   }
183   switch (myContInU) {
184   case GeomAbs_C0 :
185     iu = 0;
186     break;
187   case GeomAbs_C1 :
188     iu = 1;
189     break;
190   case GeomAbs_C2 :
191     iu = 2;
192     break;
193   default :
194     Standard_ConstructionError::Raise("AdvApp2Var_ApproxAFunc2Var : UContinuity Error");
195   }
196   switch (myContInV) {
197   case GeomAbs_C0 :
198     iv = 0;
199     break;
200   case GeomAbs_C1 :
201     iv = 1;
202     break;
203   case GeomAbs_C2 :
204     iv = 2;
205     break;
206   default :
207     Standard_ConstructionError::Raise("AdvApp2Var_ApproxAFunc2Var : VContinuity Error");
208   }
209   ndu = Max(myMaxDegInU+1,2*iu+2);
210   ndv = Max(myMaxDegInV+1,2*iv+2);
211   if (ndu<2*iu+2)
212     Standard_ConstructionError::Raise("AdvApp2Var_ApproxAFunc2Var : UMaxDegree Error");
213   if (ndv<2*iv+2)
214     Standard_ConstructionError::Raise("AdvApp2Var_ApproxAFunc2Var : VMaxDegree Error");
215   myPrecisionCode = Max(0,Min(myPrecisionCode,3));
216   AdvApp2Var_Context Conditions(ifav,iu,iv,ndu,ndv,
217                                 myPrecisionCode,
218                                 myNumSubSpaces[0],
219                                 myNumSubSpaces[1],
220                                 myNumSubSpaces[2],
221                                 my1DTolerances,
222                                 my2DTolerances,
223                                 my3DTolerances,
224                                 my1DTolOnFront,
225                                 my2DTolOnFront,
226                                 my3DTolOnFront);
227   myConditions = Conditions;
228   InitGrid(1);
229 }
230
231
232 //=======================================================================
233 //function : InitGrid
234 //purpose  : Initialisation of the approximation with regular cuttings
235 //=======================================================================
236
237 void AdvApp2Var_ApproxAFunc2Var::InitGrid(const Standard_Integer NbInt)
238 {
239   Standard_Integer iu=myConditions.UOrder(),iv=myConditions.VOrder(),iint;
240
241   AdvApp2Var_Patch M0(myFirstParInU,myLastParInU,myFirstParInV,myLastParInV,iu,iv);
242
243   AdvApp2Var_SequenceOfPatch Net;
244   Net.Append(M0);
245
246   TColStd_SequenceOfReal TheU,TheV;
247   TheU.Append(myFirstParInU);
248   TheV.Append(myFirstParInV);
249   TheU.Append(myLastParInU);
250   TheV.Append(myLastParInV);
251
252   AdvApp2Var_Network Result(Net,TheU,TheV);
253
254
255   gp_XY UV1(myFirstParInU,myFirstParInV);
256   AdvApp2Var_Node C1(UV1,iu,iv);
257   gp_XY UV2(myLastParInU,myFirstParInV);
258   AdvApp2Var_Node C2(UV2,iu,iv);
259   gp_XY UV4(myLastParInU,myLastParInV);
260   AdvApp2Var_Node C4(UV4,iu,iv);
261   gp_XY UV3(myFirstParInU,myLastParInV);
262   AdvApp2Var_Node C3(UV3,iu,iv);
263   AdvApp2Var_SequenceOfNode Bag;
264   Bag.Append(C1);
265   Bag.Append(C2);
266   Bag.Append(C3);
267   Bag.Append(C4);
268
269   AdvApp2Var_Iso V0(GeomAbs_IsoV,myFirstParInV,
270                     myFirstParInU,myLastParInU,myFirstParInV,myLastParInV,
271                     1,iu,iv);
272   AdvApp2Var_Iso V1(GeomAbs_IsoV,myLastParInV,
273                     myFirstParInU,myLastParInU,myFirstParInV,myLastParInV,
274                     2,iu,iv);
275   AdvApp2Var_Iso U0(GeomAbs_IsoU,myFirstParInU,
276                     myFirstParInU,myLastParInU,myFirstParInV,myLastParInV,
277                     3,iu,iv);
278   AdvApp2Var_Iso U1(GeomAbs_IsoU,myLastParInU,
279                     myFirstParInU,myLastParInU,myFirstParInV,myLastParInV,
280                     4,iu,iv);
281
282   AdvApp2Var_Strip BU0,BV0;
283   BU0.Append(V0);
284   BU0.Append(V1);
285   BV0.Append(U0);
286   BV0.Append(U1);
287
288   AdvApp2Var_SequenceOfStrip UStrip,VStrip;
289   UStrip.Append(BU0);
290   VStrip.Append(BV0);
291
292   AdvApp2Var_Framework Constraints(Bag,UStrip,VStrip);
293
294 // decoupes regulieres si NbInt>1
295   Standard_Real deltu = (myLastParInU-myFirstParInU)/NbInt,
296                 deltv = (myLastParInV-myFirstParInV)/NbInt;
297   for (iint=1;iint<=NbInt-1;iint++) {
298     Result.UpdateInU(myFirstParInU+iint*deltu);
299     Constraints.UpdateInU(myFirstParInU+iint*deltu);
300     Result.UpdateInV(myFirstParInV+iint*deltv);
301     Constraints.UpdateInV(myFirstParInV+iint*deltv);
302   }
303   myResult = Result;
304   myConstraints = Constraints;
305 }
306
307 //=======================================================================
308 //function : Perform
309 //purpose  : Computation of the approximation
310 //=======================================================================
311
312 void AdvApp2Var_ApproxAFunc2Var::Perform(const AdvApprox_Cutting& UChoice,
313                                          const AdvApprox_Cutting& VChoice,
314                                          const AdvApp2Var_EvaluatorFunc2Var& Func)
315 {
316   ComputePatches(UChoice,VChoice,Func);
317   myHasResult = myDone = Standard_True;
318   Compute3DErrors();
319 }
320
321 //=======================================================================
322 //function : Perform
323 //purpose  : Computation of the approximation
324 //=======================================================================
325
326 void AdvApp2Var_ApproxAFunc2Var::Perform(const AdvApprox_Cutting& UChoice,
327                                          const AdvApprox_Cutting& VChoice,
328                                          const AdvApp2Var_EvaluatorFunc2Var& Func,
329                                          const AdvApp2Var_Criterion& Crit)
330 {
331   ComputePatches(UChoice,VChoice,Func,Crit);
332   myHasResult = myDone = Standard_True;
333   Compute3DErrors();
334   ComputeCritError();
335 }
336
337 //=======================================================================
338 //function : ComputePatches
339 //purpose  : Computation of the polynomial approximations
340 //=======================================================================
341
342 void AdvApp2Var_ApproxAFunc2Var::ComputePatches(const AdvApprox_Cutting& UChoice,
343                                                 const AdvApprox_Cutting& VChoice,
344                                          const AdvApp2Var_EvaluatorFunc2Var& Func)
345 {
346   Standard_Real Udec, Vdec;
347   Standard_Boolean Umore, Vmore;
348   Standard_Integer NbPatch, NbU, NbV, NumDec;
349   Standard_Integer FirstNA;
350
351   while (myResult.FirstNotApprox(FirstNA)) {
352
353 // completude de l'ensemble des contraintes 
354     ComputeConstraints(UChoice, VChoice, Func);
355
356 // discretisation des contraintes relatives au carreau
357     myResult(FirstNA).Discretise(myConditions,myConstraints,Func);
358     if ( ! myResult(FirstNA).IsDiscretised() ) {
359       myHasResult =  myDone = Standard_False;
360       Standard_ConstructionError::Raise
361               ("AdvApp2Var_ApproxAFunc2Var : Surface Discretisation Error");
362     }
363
364 // calcul du nombre et du type de decoupes autorisees
365 // en fonction du nombre de carreaux max et de la validite des decoupes suiv.
366     NbU = myResult.NbPatchInU();
367     NbV = myResult.NbPatchInV();
368     NbPatch = NbU*NbV;
369     Umore = UChoice.Value(myResult(FirstNA).U0(), myResult(FirstNA).U1(),Udec);
370     Vmore = VChoice.Value(myResult(FirstNA).V0(), myResult(FirstNA).V1(),Vdec);
371
372     NumDec = 0;
373     if ( ((NbPatch+NbV)<=myMaxPatches) && ((NbPatch+NbU)>myMaxPatches)
374          && (Umore) ) NumDec = 1;
375     if ( ((NbPatch+NbV)>myMaxPatches) && ((NbPatch+NbU)<=myMaxPatches) 
376          && (Vmore) ) NumDec = 2;
377     if ( ((NbPatch+NbV)<=myMaxPatches) && ((NbPatch+NbU)<=myMaxPatches) ) {
378       if ( Umore ) NumDec = 3;
379       if ( (NbV>NbU) && Vmore ) NumDec = 4;
380     }
381     if ( (NbU+1)*(NbV+1)<=myMaxPatches ) {
382       if ( !Umore && !Vmore ) NumDec=0;
383       if ( Umore && !Vmore ) NumDec=3;
384       if ( !Umore && Vmore ) NumDec=4;
385       if ( Umore && Vmore ) NumDec=5;
386     }
387
388 // approximation du carreau
389     myResult(FirstNA).MakeApprox(myConditions,myConstraints,NumDec);
390
391     if ( ! myResult(FirstNA).IsApproximated() ) {
392       switch (myResult(FirstNA).CutSense()) {
393       case 0 :
394 //      On ne peut plus decouper : on garde le resultat
395         if ( myResult(FirstNA).HasResult()) {
396           myResult(FirstNA).OverwriteApprox();
397         }
398         else {
399           myHasResult =  myDone = Standard_False;
400           Standard_ConstructionError::Raise
401               ("AdvApp2Var_ApproxAFunc2Var : Surface Approximation Error");
402         }
403         break;
404       case 1 :
405 //      Il faut decouper en U
406         myResult.UpdateInU(Udec);
407         myConstraints.UpdateInU(Udec);
408         break;
409       case 2 :
410 //      Il faut decouper en V
411         myResult.UpdateInV(Vdec);
412         myConstraints.UpdateInV(Vdec);
413         break;
414       case 3 :
415 //      Il faut decouper en U et en V
416         myResult.UpdateInU(Udec);
417         myConstraints.UpdateInU(Udec);
418         myResult.UpdateInV(Vdec);
419         myConstraints.UpdateInV(Vdec);
420         break;
421       default :
422         myHasResult =  myDone = Standard_False;
423         Standard_ConstructionError::Raise
424               ("AdvApp2Var_ApproxAFunc2Var : Surface Approximation Error");
425       }
426     }
427   }
428 }
429
430 //=======================================================================
431 //function : ComputePatches
432 //purpose  : Computation of the polynomial approximations
433 //=======================================================================
434
435 void AdvApp2Var_ApproxAFunc2Var::ComputePatches(const AdvApprox_Cutting& UChoice,
436                                          const AdvApprox_Cutting& VChoice,
437                                          const AdvApp2Var_EvaluatorFunc2Var& Func,
438                                          const AdvApp2Var_Criterion& Crit)
439 {
440   Standard_Real Udec, Vdec, CritValue, m0=0., m1=0.;
441   Standard_Boolean Umore, Vmore, CritAbs = (Crit.Type() == AdvApp2Var_Absolute);
442   Standard_Integer NbPatch, NbU, NbV, NbInt, NumDec;
443   Standard_Integer FirstNA, decision=0;
444
445   while (myResult.FirstNotApprox(FirstNA)) {
446
447 // completude de l'ensemble des contraintes 
448     ComputeConstraints(UChoice, VChoice, Func, Crit);
449     if (decision>0) {
450       m0 = m1;
451       m1 = 0.;
452     }
453
454 // discretisation des contraintes relatives au carreau
455     myResult(FirstNA).Discretise(myConditions,myConstraints,Func);
456     if ( ! myResult(FirstNA).IsDiscretised() ) {
457       myHasResult =  myDone = Standard_False;
458       Standard_ConstructionError::Raise
459               ("AdvApp2Var_ApproxAFunc2Var : Surface Discretisation Error");
460     }
461
462 // calcul du nombre et du type de decoupes autorisees
463 // en fonction du nombre de carreaux max et de la validite des decoupes suiv.
464     NbU = myResult.NbPatchInU();
465     NbV = myResult.NbPatchInV();
466     NbPatch = NbU*NbV;
467     NbInt = NbU;
468     Umore = UChoice.Value(myResult(FirstNA).U0(), myResult(FirstNA).U1(),Udec);
469     Vmore = VChoice.Value(myResult(FirstNA).V0(), myResult(FirstNA).V1(),Vdec);
470
471     NumDec = 0;
472     if ( ((NbPatch+NbV)<=myMaxPatches) && ((NbPatch+NbU)>myMaxPatches)
473          && (Umore) ) NumDec = 1;
474     if ( ((NbPatch+NbV)>myMaxPatches) && ((NbPatch+NbU)<=myMaxPatches) 
475          && (Vmore) ) NumDec = 2;
476     if ( ((NbPatch+NbV)<=myMaxPatches) && ((NbPatch+NbU)<=myMaxPatches) ) {
477       if ( Umore ) NumDec = 3;
478       if ( (NbV>NbU) && Vmore ) NumDec = 4;
479     }
480     if ( (NbU+1)*(NbV+1)<=myMaxPatches ) {
481       if ( !Umore && !Vmore ) NumDec=0;
482       if ( Umore && !Vmore ) NumDec=1;
483       if ( !Umore && Vmore ) NumDec=2;
484       if ( Umore && Vmore ) NumDec=5;
485     }
486
487 // approximation du carreau
488     if ( CritAbs ) {
489       myResult(FirstNA).MakeApprox(myConditions,myConstraints,0);
490     }
491     else {
492       myResult(FirstNA).MakeApprox(myConditions,myConstraints,NumDec);
493     }
494     if (NumDec>=3) NumDec = NumDec - 2;
495
496 // evaluation du critere sur le carreau
497     if ( myResult(FirstNA).HasResult() ) {
498       Crit.Value(myResult(FirstNA),myConditions);
499       CritValue = myResult(FirstNA).CritValue();
500       if (m1<CritValue) m1 = CritValue;
501     }
502 // doit-on decouper ?
503     decision = myResult(FirstNA).CutSense(Crit,NumDec);
504     Standard_Boolean Regular = (Crit.Repartition() ==  AdvApp2Var_Regular);
505 //    Standard_Boolean Regular = Standard_True;
506     if (Regular && decision>0) {
507       NbInt++;
508       InitGrid(NbInt);
509     }
510     else {
511       switch (decision) {
512       case 0 :
513 //      On ne peut plus decouper : on garde le resultat
514         if ( myResult(FirstNA).HasResult() ) {
515           myResult(FirstNA).OverwriteApprox();
516         }
517         else {
518           myHasResult =  myDone = Standard_False;
519           Standard_ConstructionError::Raise
520             ("AdvApp2Var_ApproxAFunc2Var : Surface Approximation Error");
521         }
522         break;
523       case 1 :
524 //      Il faut decouper en U
525         myResult.UpdateInU(Udec);
526         myConstraints.UpdateInU(Udec);
527         break;
528       case 2 :
529 //      Il faut decouper en V
530         myResult.UpdateInV(Vdec);
531         myConstraints.UpdateInV(Vdec);
532         break;
533       case 3 :
534 //      Il faut decouper en U et en V
535         myResult.UpdateInU(Udec);
536         myConstraints.UpdateInU(Udec);
537         myResult.UpdateInV(Vdec);
538         myConstraints.UpdateInV(Vdec);
539         break;
540         default :
541         myHasResult =  myDone = Standard_False;
542         Standard_ConstructionError::Raise
543           ("AdvApp2Var_ApproxAFunc2Var : Surface Approximation Error");
544       }
545     }
546   }
547 }
548
549 //=======================================================================
550 //function : ComputeConstraints without Criterion
551 //purpose  : Approximation of the constraints
552 //=======================================================================
553
554 void AdvApp2Var_ApproxAFunc2Var::ComputeConstraints(const AdvApprox_Cutting& UChoice,
555                                          const AdvApprox_Cutting& VChoice,
556                                          const AdvApp2Var_EvaluatorFunc2Var& Func)
557 {
558   Standard_Real dec;
559   Standard_Boolean more;
560   Standard_Integer ind1, ind2, NbPatch, NbU, NbV;
561   AdvApp2Var_Iso Is;
562   Standard_Integer indN1, indN2;
563   Standard_Integer iu = myConditions.UOrder(), iv = myConditions.VOrder();
564   AdvApp2Var_Node N1(iu,iv), N2(iu,iv);
565
566   while ( myConstraints.FirstNotApprox(ind1, ind2, Is) ) {
567
568 // approximation de l'iso et calcul des contraintes aux extremites
569     indN1 = myConstraints.FirstNode(Is.Type(),ind1,ind2);
570     N1 = myConstraints.Node(indN1);
571     indN2 = myConstraints.LastNode(Is.Type(),ind1,ind2);
572     N2 = myConstraints.Node(indN2);
573
574     Is.MakeApprox(myConditions,
575                   myFirstParInU, myLastParInU,
576                   myFirstParInV, myLastParInV,
577                   Func, N1 , N2);
578
579     if (Is.IsApproximated()) {
580 // L'iso est approchee a la tolerance voulue
581       myConstraints.ChangeIso(ind1,ind2,Is);
582       myConstraints.ChangeNode(indN1) = N1;
583       myConstraints.ChangeNode(indN2) = N2;
584     }
585
586     else {
587 // Pas d'approximation satisfaisante
588       NbU = myResult.NbPatchInU();
589       NbV = myResult.NbPatchInV();
590       if (Is.Type()==GeomAbs_IsoV) {
591         NbPatch = (NbU+1)*NbV;
592         more = UChoice.Value(Is.T0(),Is.T1(),dec);
593       }
594       else {
595         NbPatch = (NbV+1)*NbU;
596         more = VChoice.Value(Is.T0(),Is.T1(),dec);
597       }
598
599       if (NbPatch<=myMaxPatches && more) {
600 //      On peut decouper l'iso
601         if (Is.Type()==GeomAbs_IsoV) {
602           myResult.UpdateInU(dec);
603           myConstraints.UpdateInU(dec);
604         }
605         else {
606           myResult.UpdateInV(dec);
607           myConstraints.UpdateInV(dec);
608         }
609       }
610
611       else {
612 //      On ne peut plus decouper : on garde le resultat
613         if (Is.HasResult()) {
614           Is.OverwriteApprox();
615           myConstraints.ChangeIso(ind1,ind2,Is);
616           myConstraints.ChangeNode(indN1) = N1;
617           myConstraints.ChangeNode(indN2) = N2; 
618         }
619         else {
620           myHasResult =  myDone = Standard_False;
621           Standard_ConstructionError::Raise
622             ("AdvApp2Var_ApproxAFunc2Var : Curve Approximation Error");
623         }
624       }
625     }
626   }
627 }
628
629
630 //=======================================================================
631 //function : ComputeConstraints with Criterion
632 //purpose  : Approximation of the constraints
633 //=======================================================================
634
635 void AdvApp2Var_ApproxAFunc2Var::ComputeConstraints(const AdvApprox_Cutting& UChoice,
636                                          const AdvApprox_Cutting& VChoice,
637                                          const AdvApp2Var_EvaluatorFunc2Var& Func,
638                                          const AdvApp2Var_Criterion& Crit)
639 {
640   Standard_Real dec;
641   Standard_Boolean more, CritRel = (Crit.Type() == AdvApp2Var_Relative);
642   Standard_Integer ind1, ind2, NbPatch, NbU, NbV;
643   AdvApp2Var_Iso Is;
644   Standard_Integer indN1, indN2;
645   Standard_Integer iu = myConditions.UOrder(), iv = myConditions.VOrder();
646   AdvApp2Var_Node N1(iu,iv), N2(iu,iv);
647
648     while ( myConstraints.FirstNotApprox(ind1, ind2, Is) ) {
649
650 // approximation de l'iso et calcul des contraintes aux extremites
651       indN1 = myConstraints.FirstNode(Is.Type(),ind1,ind2);
652       N1 = myConstraints.Node(indN1);
653       indN2 = myConstraints.LastNode(Is.Type(),ind1,ind2);
654       N2 = myConstraints.Node(indN2);
655
656       Is.MakeApprox(myConditions,
657                     myFirstParInU, myLastParInU,
658                     myFirstParInV, myLastParInV,
659                     Func, N1 , N2);
660
661       if (Is.IsApproximated()) {
662 // L'iso est approchee a la tolerance voulue
663         myConstraints.ChangeIso(ind1,ind2,Is);
664         myConstraints.ChangeNode(indN1) = N1;
665         myConstraints.ChangeNode(indN2) = N2;
666       }
667
668       else {
669 // Pas d'approximation satisfaisante
670         NbU = myResult.NbPatchInU();
671         NbV = myResult.NbPatchInV();
672         if (Is.Type()==GeomAbs_IsoV) {
673           NbPatch = (NbU+1)*NbV;
674           more = UChoice.Value(Is.T0(),Is.T1(),dec);
675         }
676         else {
677           NbPatch = (NbV+1)*NbU;
678           more = VChoice.Value(Is.T0(),Is.T1(),dec);
679         }
680
681 //      Pour forcer l'Overwrite si le critere est Absolu
682         more = more && (CritRel);
683
684         if (NbPatch<=myMaxPatches && more) {
685 //      On peut decouper l'iso
686           if (Is.Type()==GeomAbs_IsoV) {
687             myResult.UpdateInU(dec);
688             myConstraints.UpdateInU(dec);
689           }
690           else {
691             myResult.UpdateInV(dec);
692             myConstraints.UpdateInV(dec);
693           }
694         }
695
696         else {
697 //      On ne peut plus decouper : on garde le resultat
698           if (Is.HasResult()) {
699             Is.OverwriteApprox();
700             myConstraints.ChangeIso(ind1,ind2,Is);
701             myConstraints.ChangeNode(indN1) = N1;
702             myConstraints.ChangeNode(indN2) = N2;       
703           }
704           else {
705             myHasResult =  myDone = Standard_False;
706             Standard_ConstructionError::Raise
707               ("AdvApp2Var_ApproxAFunc2Var : Curve Approximation Error");
708           }
709         }
710       }
711     }
712 }
713
714 //=======================================================================
715 //function : Compute3DErrors
716 //purpose  : Computation of the 3D errors
717 //=======================================================================
718
719 void AdvApp2Var_ApproxAFunc2Var::Compute3DErrors()
720 {
721
722   Standard_Integer iesp,ipat;
723   Standard_Real error_max,error_moy,error_U0,error_V0,error_U1,error_V1;
724   Standard_Real Tol,F1Tol,F2Tol,F3Tol,F4Tol;
725   if ( myNumSubSpaces[2] > 0 ) {
726     my3DMaxError = new (TColStd_HArray1OfReal) (1,myNumSubSpaces[2]);
727     my3DAverageError = new (TColStd_HArray1OfReal) (1,myNumSubSpaces[2]);
728     my3DUFrontError = new (TColStd_HArray1OfReal) (1,myNumSubSpaces[2]);
729     my3DVFrontError = new (TColStd_HArray1OfReal) (1,myNumSubSpaces[2]);
730     for (iesp=1;iesp<=myNumSubSpaces[2];iesp++) {
731       error_max = 0;
732       error_moy = 0.;
733       error_U0 = 0.;
734       error_V0 = 0.;
735       error_U1 = 0.;
736       error_V1 = 0.;
737       Tol = my3DTolerances->Value(iesp);
738       F1Tol = my3DTolOnFront->Value(iesp,1);
739       F2Tol = my3DTolOnFront->Value(iesp,2);
740       F3Tol = my3DTolOnFront->Value(iesp,3);
741       F4Tol = my3DTolOnFront->Value(iesp,4);
742       for (ipat=1;ipat<=myResult.NbPatch();ipat++) {
743         error_max = Max((myResult(ipat).MaxErrors())->Value(iesp),error_max);
744         error_U0 = Max((myResult(ipat).IsoErrors())->Value(iesp,3),error_U0);
745         error_U1 = Max((myResult(ipat).IsoErrors())->Value(iesp,4),error_U1);
746         error_V0 = Max((myResult(ipat).IsoErrors())->Value(iesp,1),error_V0);
747         error_V1 = Max((myResult(ipat).IsoErrors())->Value(iesp,2),error_V1);
748         error_moy += (myResult(ipat).AverageErrors())->Value(iesp);
749       }
750       my3DMaxError->SetValue(iesp,error_max);
751       my3DUFrontError->SetValue(iesp,Max(error_U0,error_U1));
752       my3DVFrontError->SetValue(iesp,Max(error_V0,error_V1));
753       error_moy /= (Standard_Real) myResult.NbPatch();
754       my3DAverageError->SetValue(iesp,error_moy);
755       if ( error_max>Tol 
756           || error_U0>F3Tol || error_U1>F4Tol 
757           || error_V0>F1Tol || error_V1>F2Tol) {
758         myDone = Standard_False;
759       }
760     }
761   }
762 }
763
764
765 //=======================================================================
766 //function : ComputeCritError
767 //purpose  : Computation of the max value of the Criterion
768 //=======================================================================
769
770 void AdvApp2Var_ApproxAFunc2Var::ComputeCritError()
771 {
772
773   Standard_Integer iesp,ipat;
774   Standard_Real crit_max;
775   if ( myNumSubSpaces[2] > 0 ) {
776     for (iesp=1;iesp<=myNumSubSpaces[2];iesp++) {
777       crit_max = 0.;
778       for (ipat=1;ipat<=myResult.NbPatch();ipat++) {
779         crit_max = Max((myResult(ipat).CritValue()),crit_max);
780       }
781       myCriterionError = crit_max;
782     }
783   }
784 }
785
786 //=======================================================================
787 //function : ConvertBS
788 //purpose  : Convertion of the approximation in BSpline Surface
789 //=======================================================================
790
791 void AdvApp2Var_ApproxAFunc2Var::ConvertBS()
792 {
793  // Homogeneisation des degres
794   Standard_Integer iu = myConditions.UOrder(), iv = myConditions.VOrder();
795   Standard_Integer ncfu = myConditions.ULimit(), ncfv = myConditions.VLimit();
796   myResult.SameDegree(iu,iv,ncfu,ncfv);
797   myDegreeInU = ncfu - 1;
798   myDegreeInV = ncfv - 1;
799
800  // Calcul des surfaces resultats
801   mySurfaces = new ( TColGeom_HArray1OfSurface) (1,  myNumSubSpaces[2]);
802
803   Standard_Integer j;
804   TColStd_Array1OfReal UKnots (1, myResult.NbPatchInU()+1);
805   for (j=1; j<=UKnots.Length(); j++) { UKnots.SetValue(j, myResult.UParameter(j)); } 
806  
807   TColStd_Array1OfReal VKnots (1, myResult.NbPatchInV()+1);
808   for (j=1; j<=VKnots.Length(); j++) { VKnots.SetValue(j, myResult.VParameter(j)); }
809
810  // Preparation des donnees pour la conversion grille de polynomes --> poles
811   Handle(TColStd_HArray1OfReal) Uint1 = 
812     new (TColStd_HArray1OfReal) (1,2);
813   Uint1->SetValue(1, -1);
814   Uint1->SetValue(2, 1);
815   Handle(TColStd_HArray1OfReal) Vint1 = 
816     new (TColStd_HArray1OfReal) (1,2);
817   Vint1->SetValue(1, -1);
818   Vint1->SetValue(2, 1);
819
820   Handle(TColStd_HArray1OfReal) Uint2 = 
821     new (TColStd_HArray1OfReal) (1,myResult.NbPatchInU()+1);
822   for (j=1; j<=Uint2->Length(); j++) { Uint2->SetValue(j, myResult.UParameter(j)); } 
823   Handle(TColStd_HArray1OfReal) Vint2 = 
824     new (TColStd_HArray1OfReal) (1,myResult.NbPatchInV()+1);
825   for (j=1; j<=Vint2->Length(); j++) { Vint2->SetValue(j, myResult.VParameter(j)); } 
826
827   Standard_Integer nmax = myResult.NbPatchInU()*myResult.NbPatchInV(),
828                    Size_eq = myConditions.ULimit() * myConditions.VLimit() * 3;
829
830   Handle(TColStd_HArray2OfInteger) NbCoeff = 
831     new (TColStd_HArray2OfInteger) (1, nmax, 1, 2);
832   Handle(TColStd_HArray1OfReal) Poly = 
833     new (TColStd_HArray1OfReal) (1, nmax * Size_eq);
834
835   Standard_Integer SSP, i;
836   for (SSP=1; SSP <= myNumSubSpaces[2]; SSP++) { 
837
838     // Creation de la grille de polynomes
839     Standard_Integer n=0,icf=1,ieq;
840     for (j=1; j<=myResult.NbPatchInV(); j++) {
841       for (i=1; i<=myResult.NbPatchInU(); i++) {
842         n++;
843         NbCoeff->SetValue(n,1, myResult.Patch(i,j).NbCoeffInU());
844         NbCoeff->SetValue(n,2, myResult.Patch(i,j).NbCoeffInV());
845         for (ieq=1; ieq<=Size_eq;ieq++) {
846           Poly->SetValue(icf,(myResult.Patch(i,j).Coefficients(SSP,myConditions))
847                                   ->Value(ieq));
848           icf++;
849         }
850       }
851     }
852   
853     // Conversion en poles
854     Convert_GridPolynomialToPoles CvP (myResult.NbPatchInU(),myResult.NbPatchInV(),
855                                        iu,iv,myMaxDegInU,myMaxDegInV,NbCoeff,
856                                        Poly,Uint1,Vint1,Uint2,Vint2);
857     if ( !CvP.IsDone() ) { myDone = Standard_False; }
858    
859     // Conversion en BSpline
860     mySurfaces->ChangeValue(SSP) = new (Geom_BSplineSurface) 
861         ( CvP.Poles()->Array2(),   
862           CvP.UKnots()->Array1(),  CvP.VKnots()->Array1(),
863           CvP.UMultiplicities()->Array1(), CvP.VMultiplicities()->Array1(),
864           CvP.UDegree(), CvP.VDegree() );
865   }
866 }
867
868 //=======================================================================
869 //function : MaxError
870 //purpose  : 
871 //=======================================================================
872
873 Handle(TColStd_HArray1OfReal)
874  AdvApp2Var_ApproxAFunc2Var::MaxError(const Standard_Integer Dimension) const
875 {
876   Handle (TColStd_HArray1OfReal) EPtr;
877   if (Dimension <1 || Dimension >3) {
878     Standard_OutOfRange::Raise
879       ("AdvApp2Var_ApproxAFunc2Var::MaxError : Dimension must be equal to 1,2 or 3 !");
880   }
881   switch (Dimension) {
882   case 1:
883     EPtr = my1DMaxError;
884     break;
885   case 2:
886     EPtr = my2DMaxError;
887     break;
888   case 3:
889     EPtr = my3DMaxError;
890     break;
891   }
892   return EPtr;
893 }
894
895 //=======================================================================
896 //function : AverageError
897 //purpose  : 
898 //=======================================================================
899
900 Handle(TColStd_HArray1OfReal)
901  AdvApp2Var_ApproxAFunc2Var::AverageError(const Standard_Integer Dimension) const 
902 {
903   Handle (TColStd_HArray1OfReal) EPtr;
904   if (Dimension <1 || Dimension >3) {
905     Standard_OutOfRange::Raise
906       ("AdvApp2Var_ApproxAFunc2Var::AverageError : Dimension must be equal to 1,2 or 3 !");
907   }
908   switch (Dimension) {
909   case 1:
910     EPtr = my1DAverageError;
911     break;
912   case 2:
913     EPtr = my2DAverageError;
914     break;
915   case 3:
916     EPtr = my3DAverageError;
917     break;
918   }
919   return EPtr;
920 }
921
922 //=======================================================================
923 //function : UFrontError
924 //purpose  : 
925 //=======================================================================
926
927 Handle(TColStd_HArray1OfReal)
928  AdvApp2Var_ApproxAFunc2Var::UFrontError(const Standard_Integer Dimension) const 
929 {
930   Handle (TColStd_HArray1OfReal) EPtr;
931   if (Dimension <1 || Dimension >3) {
932     Standard_OutOfRange::Raise
933       ("AdvApp2Var_ApproxAFunc2Var::UFrontError : Dimension must be equal to 1,2 or 3 !");
934   }
935   switch (Dimension) {
936   case 1:
937     EPtr = my1DUFrontError;
938     break;
939   case 2:
940     EPtr = my2DUFrontError;
941     break;
942   case 3:
943     EPtr = my3DUFrontError;
944     break;
945   }
946   return EPtr;
947 }
948
949 //=======================================================================
950 //function : VFrontError
951 //purpose  : 
952 //=======================================================================
953
954 Handle(TColStd_HArray1OfReal)
955  AdvApp2Var_ApproxAFunc2Var::VFrontError(const Standard_Integer Dimension) const 
956 {
957   Handle (TColStd_HArray1OfReal) EPtr;
958   if (Dimension <=0 || Dimension >3) {
959     Standard_OutOfRange::Raise
960       ("AdvApp2Var_ApproxAFunc2Var::VFrontError : Dimension must be equal to 1,2 or 3 !");
961   }
962   switch (Dimension) {
963   case 1:
964     EPtr = my1DVFrontError;
965     break;
966   case 2:
967     EPtr = my2DVFrontError;
968     break;
969   case 3:
970     EPtr = my3DVFrontError;
971     break;
972   }
973   return EPtr;
974 }
975
976 //=======================================================================
977 //function : MaxError
978 //purpose  : 
979 //=======================================================================
980
981 Standard_Real
982  AdvApp2Var_ApproxAFunc2Var::MaxError(const Standard_Integer Dimension,
983                                       const Standard_Integer SSPIndex) const 
984 {
985   if (Dimension !=3 || SSPIndex !=1) {
986     Standard_OutOfRange::Raise
987       ("AdvApp2Var_ApproxAFunc2Var::MaxError: ONE Surface 3D only !");
988   }
989   Handle (TColStd_HArray1OfReal) EPtr = MaxError(Dimension);
990   return EPtr->Value(SSPIndex);
991 }
992
993 //=======================================================================
994 //function : AverageError
995 //purpose  : 
996 //=======================================================================
997
998 Standard_Real
999  AdvApp2Var_ApproxAFunc2Var::AverageError(const Standard_Integer Dimension,
1000                                           const Standard_Integer SSPIndex) const 
1001 {
1002   if (Dimension !=3 || SSPIndex !=1) {
1003     Standard_OutOfRange::Raise
1004       ("AdvApp2Var_ApproxAFunc2Var::AverageError : ONE Surface 3D only !");
1005   }
1006   Handle (TColStd_HArray1OfReal) EPtr = AverageError(Dimension);
1007   return EPtr->Value(SSPIndex);
1008 }
1009
1010 //=======================================================================
1011 //function : UFrontError
1012 //purpose  : 
1013 //=======================================================================
1014
1015 Standard_Real
1016  AdvApp2Var_ApproxAFunc2Var::UFrontError(const Standard_Integer Dimension,
1017                                          const Standard_Integer SSPIndex) const 
1018 {
1019   if (Dimension !=3 || SSPIndex !=1) {
1020     Standard_OutOfRange::Raise
1021       ("AdvApp2Var_ApproxAFunc2Var::UFrontError : ONE Surface 3D only !");
1022   }
1023   Handle (TColStd_HArray1OfReal) EPtr = UFrontError(Dimension);
1024   return EPtr->Value(SSPIndex);
1025 }
1026
1027 //=======================================================================
1028 //function : VFrontError
1029 //purpose  : 
1030 //=======================================================================
1031
1032 Standard_Real
1033  AdvApp2Var_ApproxAFunc2Var::VFrontError(const Standard_Integer Dimension,
1034                                          const Standard_Integer SSPIndex) const 
1035 {
1036   if (Dimension !=3 || SSPIndex !=1) {
1037     Standard_OutOfRange::Raise
1038       ("AdvApp2Var_ApproxAFunc2Var::VFrontError : ONE Surface 3D only !");
1039   }
1040   Handle (TColStd_HArray1OfReal) EPtr = VFrontError(Dimension);
1041   return EPtr->Value(SSPIndex);
1042 }
1043
1044
1045 //=======================================================================
1046 //function : CritError
1047 //purpose  : 
1048 //=======================================================================
1049
1050 Standard_Real
1051  AdvApp2Var_ApproxAFunc2Var::CritError(const Standard_Integer Dimension,
1052                                        const Standard_Integer SSPIndex) const 
1053 {
1054   if (Dimension !=3 || SSPIndex !=1) {
1055     Standard_OutOfRange::Raise
1056       ("AdvApp2Var_ApproxAFunc2Var::CritError: ONE Surface 3D only !");
1057   }
1058   return myCriterionError;
1059 }
1060
1061 //=======================================================================
1062 //function : Dump
1063 //purpose  : 
1064 //=======================================================================
1065
1066 void AdvApp2Var_ApproxAFunc2Var::Dump(Standard_OStream& o) const 
1067 {
1068   Standard_Integer iesp=1,NbKU,NbKV,ik;
1069   o<<endl;
1070   if (!myHasResult) { o<<"No result"<<endl; }
1071   else {
1072     o<<"There is a result";
1073     if (myDone) {
1074       o<<" within the requested tolerance "<<my3DTolerances->Value(iesp)<<endl;
1075     }
1076     else if (my3DMaxError->Value(iesp)>my3DTolerances->Value(iesp)) {
1077       o<<" WITHOUT the requested tolerance "<<my3DTolerances->Value(iesp)<<endl;
1078     }
1079     else {
1080       o<<" WITHOUT the requested continuities "<<endl;
1081     }
1082     o<<endl;
1083     o<<"Result max error :"<<my3DMaxError->Value(iesp)<<endl;
1084     o<<"Result average error :"<<my3DAverageError->Value(iesp)<<endl;
1085     o<<"Result max error on U frontiers :"<<my3DUFrontError->Value(iesp)<<endl;
1086     o<<"Result max error on V frontiers :"<<my3DVFrontError->Value(iesp)<<endl;
1087     o<<endl;
1088     o<<"Degree of Bezier patches in U : "<<myDegreeInU
1089       <<"  in V : "<<myDegreeInV<<endl;
1090     o<<endl;
1091     Handle(Geom_BSplineSurface) S
1092       = Handle(Geom_BSplineSurface)::DownCast(mySurfaces->Value(iesp));
1093     o<<"Number of poles in U : "<<S->NbUPoles()
1094       <<"  in V : "<<S->NbVPoles()<<endl;
1095     o<<endl;
1096     NbKU = S->NbUKnots();
1097     NbKV = S->NbVKnots();
1098     o<<"Number of knots in U : "<<NbKU<<endl;
1099     for (ik=1;ik<=NbKU;ik++) {
1100       o<<"   "<<ik<<" : "<<S->UKnot(ik)<<"   mult : "<<S->UMultiplicity(ik)<<endl;
1101     }
1102     o<<endl;
1103     o<<"Number of knots in V : "<<NbKV<<endl;
1104     for (ik=1;ik<=NbKV;ik++) {
1105       o<<"   "<<ik<<" : "<<S->VKnot(ik)<<"   mult : "<<S->VMultiplicity(ik)<<endl;
1106     }
1107     o<<endl;
1108   }
1109 }