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