239343: OCC fails to work with offset surfaces with singularities
[occt.git] / src / Geom / Geom_OsculatingSurface.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #include <Geom_OsculatingSurface.ixx>
19 #include <Geom_BezierSurface.hxx>
20 #include <TColgp_Array2OfPnt.hxx>
21 #include <TColgp_HArray2OfPnt.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23 #include <TColStd_Array1OfInteger.hxx>
24 #include <TColStd_HArray2OfInteger.hxx>
25 #include <TColStd_HArray1OfReal.hxx>
26 #include <TColStd_HArray1OfInteger.hxx>
27 #include <TColgp_Array1OfPnt.hxx>
28 #include <TColgp_Array2OfVec.hxx>
29 #include <BSplSLib.hxx>
30 #include <Convert_GridPolynomialToPoles.hxx>
31 #include <Precision.hxx>
32 #include <PLib.hxx>
33
34 //=======================================================================
35 //function : Geom_OffsetOsculatingSurface
36 //purpose  : 
37 //=======================================================================
38
39 Geom_OsculatingSurface::Geom_OsculatingSurface()
40 : myAlong(1,4)
41 {
42 }
43 //=======================================================================
44 //function : Geom_OffsetOsculatingSurface
45 //purpose  : 
46 //=======================================================================
47
48 Geom_OsculatingSurface::Geom_OsculatingSurface(const Handle(Geom_Surface)& BS, 
49                                                const Standard_Real Tol)
50 : myAlong(1,4)
51 {
52   Init(BS,Tol);
53 }
54
55 //=======================================================================
56 //function : Init
57 //purpose  : 
58 //=======================================================================
59
60 void Geom_OsculatingSurface::Init(const Handle(Geom_Surface)& BS,
61                                   const Standard_Real Tol)
62 {
63   ClearOsculFlags();
64   myTol=Tol; 
65   Standard_Real TolMin=0.;//consider all singularities below Tol, not just above 1.e-12 (id23943)
66   Standard_Boolean OsculSurf = Standard_True;
67   myBasisSurf = Handle(Geom_Surface)::DownCast(BS->Copy());
68   myOsculSurf1 = new Geom_HSequenceOfBSplineSurface();
69   myOsculSurf2 = new Geom_HSequenceOfBSplineSurface();
70   if ((BS->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) || 
71       (BS->IsKind(STANDARD_TYPE(Geom_BezierSurface)))) 
72     {
73       Standard_Real U1=0,U2=0,V1=0,V2=0;
74       
75       Standard_Integer i = 1;
76       BS->Bounds(U1,U2,V1,V2);
77       myAlong.SetValue(1,IsQPunctual(BS,V1,GeomAbs_IsoV,TolMin,Tol));
78       myAlong.SetValue(2,IsQPunctual(BS,V2,GeomAbs_IsoV,TolMin,Tol));
79       myAlong.SetValue(3,IsQPunctual(BS,U1,GeomAbs_IsoU,TolMin,Tol));
80       myAlong.SetValue(4,IsQPunctual(BS,U2,GeomAbs_IsoU,TolMin,Tol));
81 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
82       cout<<myAlong(1)<<endl<<myAlong(2)<<endl<<myAlong(3)<<endl<<myAlong(4)<<endl;
83 #endif
84       if (myAlong(1) || myAlong(2) || myAlong(3) || myAlong(4)) 
85         {
86           Handle(Geom_BSplineSurface) InitSurf, L,S;
87           if (BS->IsKind(STANDARD_TYPE(Geom_BezierSurface))) 
88             {
89               Handle(Geom_BezierSurface) BzS = Handle(Geom_BezierSurface)::DownCast(BS);
90               TColgp_Array2OfPnt P(1,BzS->NbUPoles(),1,BzS->NbVPoles());
91               TColStd_Array1OfReal UKnots(1,2);
92               TColStd_Array1OfReal VKnots(1,2);
93               TColStd_Array1OfInteger UMults(1,2);
94               TColStd_Array1OfInteger VMults(1,2);
95               for (i=1;i<=2;i++)
96                 {
97                   UKnots.SetValue(i,(i-1));
98                   VKnots.SetValue(i,(i-1));
99                   UMults.SetValue(i,BzS->UDegree()+1);
100                   VMults.SetValue(i,BzS->VDegree()+1);
101                 }
102               BzS->Poles(P);
103               InitSurf = new Geom_BSplineSurface(P,UKnots,VKnots,
104                                                  UMults,VMults,
105                                                  BzS->UDegree(),
106                                                  BzS->VDegree(),
107                                                  BzS->IsUPeriodic(),
108                                                  BzS->IsVPeriodic());
109             }
110           else 
111             {
112               InitSurf = Handle(Geom_BSplineSurface)::DownCast(myBasisSurf);
113             }
114 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
115           cout<<"UDEG: "<<InitSurf->UDegree()<<endl;
116           cout<<"VDEG: "<<InitSurf->VDegree()<<endl;
117 #endif
118           
119           if(IsAlongU() && IsAlongV()) ClearOsculFlags();
120           //      Standard_ConstructionError_Raise_if((IsAlongU() && IsAlongV()),"Geom_OsculatingSurface");
121           if ((IsAlongU() && InitSurf->VDegree()>1) ||
122               (IsAlongV() && InitSurf->UDegree()>1)) 
123             {
124               myKdeg = new TColStd_HSequenceOfInteger();
125               Standard_Integer k=0;
126               Standard_Boolean IsQPunc;
127               Standard_Integer UKnot,VKnot;
128               if (myAlong(1) || myAlong(2)) 
129                 {
130                   for (i=1;i<InitSurf->NbUKnots();i++) 
131                     {
132                       if (myAlong(1)) 
133                         {
134                           S = InitSurf; k=0; IsQPunc=Standard_True;
135                           UKnot=i;
136                           VKnot=1;
137                           while(IsQPunc) 
138                             {
139                               OsculSurf  = BuildOsculatingSurface(V1,UKnot,VKnot,S,L);
140                               if(!OsculSurf) break;
141                               k++;
142 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
143                               cout<<"1.k = "<<k<<endl;
144 #endif
145                               IsQPunc=IsQPunctual(L,V1,GeomAbs_IsoV,0.,Tol);
146                               UKnot=1;
147                               VKnot=1;
148                               S=L;
149                               
150                             }
151                           if (OsculSurf)
152                             myOsculSurf1->Append(L);
153                           else
154                             ClearOsculFlags(); //myAlong.SetValue(1,Standard_False);
155                           if (myAlong(2) && OsculSurf) 
156                             {
157                               S = InitSurf; k=0; IsQPunc=Standard_True;
158                               UKnot=i;
159                               VKnot=InitSurf->NbVKnots()-1;
160                               
161                               while(IsQPunc) 
162                                 {
163                                   OsculSurf = BuildOsculatingSurface(V2,UKnot,VKnot,S,L);
164                                   if(!OsculSurf) break;
165                                   k++;
166 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
167                                   cout<<"2.k = "<<k<<endl;
168 #endif
169                                   IsQPunc=IsQPunctual(L,V2,GeomAbs_IsoV,0.,Tol);
170                                   UKnot=1;
171                                   VKnot=1;
172                                   S=L;
173                                 }
174                               if(OsculSurf)
175                                 {
176                                   myOsculSurf2->Append(L);
177                                   myKdeg->Append(k);
178                                 }
179                             } 
180                         }
181                       else 
182                         //if (myAlong(2)) 
183                         {
184                           S = InitSurf; k=0; IsQPunc=Standard_True;
185                           UKnot=i;
186                           VKnot=InitSurf->NbVKnots()-1;
187                           while(IsQPunc) 
188                             {
189                               OsculSurf = BuildOsculatingSurface(V2,UKnot,VKnot,S,L);
190                               if(!OsculSurf) break;
191                               k++;
192 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
193                               cout<<"2.k = "<<k<<endl;
194 #endif
195                               IsQPunc=IsQPunctual(L,V2,GeomAbs_IsoV,0.,Tol);
196                               UKnot=1;
197                               VKnot=1;
198                               S=L;
199                               
200                             }
201                           if(OsculSurf)
202                             {
203                               myOsculSurf2->Append(L);
204                               myKdeg->Append(k);
205                             }
206                           else
207                             ClearOsculFlags(); //myAlong.SetValue(2,Standard_False);
208                         }
209                     }
210                 }
211               if (myAlong(3) || myAlong(4)) 
212                 {
213                   for (i=1;i<InitSurf->NbVKnots();i++) 
214                     {
215                       if (myAlong(3)) 
216                         {
217                           S = InitSurf; k=0; IsQPunc=Standard_True;
218                           UKnot=1;
219                           VKnot=i;
220                           while(IsQPunc) 
221                             {
222                               OsculSurf = BuildOsculatingSurface(U1,UKnot,VKnot,S,L);
223                               if(!OsculSurf) break;
224                               k++;
225 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
226                               cout<<"1.k = "<<k<<endl;
227 #endif
228                               IsQPunc=IsQPunctual(L,U1,GeomAbs_IsoU,0.,Tol);
229                               UKnot=1;
230                               VKnot=1;
231                               S=L;
232                             }
233                           if(OsculSurf)
234                             myOsculSurf1->Append(L);
235                           else
236                             ClearOsculFlags(); //myAlong.SetValue(3,Standard_False);
237                           if (myAlong(4) && OsculSurf )
238                             {
239                               S = InitSurf; k=0; IsQPunc=Standard_True;
240                               UKnot=InitSurf->NbUKnots()-1;
241                               VKnot=i;
242                               while(IsQPunc) 
243                                 {
244                                   OsculSurf  = BuildOsculatingSurface(U2,UKnot,VKnot,S,L);
245                                   if(!OsculSurf) break;
246                                   k++;
247 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
248                                   cout<<"2.k = "<<k<<endl;
249 #endif
250                                   IsQPunc=IsQPunctual(L,U2,GeomAbs_IsoU,0.,Tol);
251                                   UKnot=1;
252                                   VKnot=1;
253                                   S=L;
254                                 }
255                               if(OsculSurf)
256                                 {
257                                   myOsculSurf2->Append(L);
258                                   myKdeg->Append(k);
259                                 }
260                             }
261                         }
262                       else 
263                         {
264                           S = InitSurf; k=0; IsQPunc=Standard_True;
265                           UKnot=InitSurf->NbUKnots()-1;
266                           VKnot=i;
267                           while(IsQPunc) 
268                             {
269                               OsculSurf  = BuildOsculatingSurface(U2,UKnot,VKnot,S,L);
270                               if(!OsculSurf) break;
271                               k++;
272 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
273                               cout<<"2.k = "<<k<<endl;
274 #endif
275                               IsQPunc=IsQPunctual(L,U2,GeomAbs_IsoU,0.,Tol);
276                               UKnot=1;
277                               VKnot=1;
278                               S=L;
279                             }
280                           if(OsculSurf)
281                             {
282                               myOsculSurf2->Append(L);
283                               myKdeg->Append(k);
284                             }
285                           else
286                             ClearOsculFlags(); //myAlong.SetValue(4,Standard_False);
287                         }
288                     }
289                 }
290             }
291           else
292             {
293               ClearOsculFlags();
294             } 
295         }
296     }
297   else
298     ClearOsculFlags();
299 }
300
301 //=======================================================================
302 //function : BasisSurface
303 //purpose  : 
304 //=======================================================================
305
306  Handle(Geom_Surface) Geom_OsculatingSurface::BasisSurface() const
307 {
308   return myBasisSurf;
309 }
310
311 //=======================================================================
312 //function : Tolerance
313 //purpose  : 
314 //=======================================================================
315
316 Standard_Real Geom_OsculatingSurface::Tolerance() const
317 {
318   return myTol;
319 }
320
321 //=======================================================================
322 //function : UOscSurf
323 //purpose  : 
324 //=======================================================================
325
326 Standard_Boolean Geom_OsculatingSurface::UOscSurf
327                   (const Standard_Real U,
328                    const Standard_Real V,
329                    Standard_Boolean& t,
330                    Handle(Geom_BSplineSurface)& L) const
331 {
332   Standard_Boolean along = Standard_False;
333   if (myAlong(1) || myAlong(2)) 
334   {
335     Standard_Integer NU = 1, NV = 1;
336     Standard_Real u1,u2,v1,v2;
337     t = Standard_False;
338     myBasisSurf->Bounds(u1,u2,v1,v2);
339     Standard_Integer NbUK,NbVK;
340     Standard_Boolean isToSkipSecond = Standard_False;
341     if (myBasisSurf->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) 
342     {
343       Handle(Geom_BSplineSurface) BSur = 
344               *((Handle(Geom_BSplineSurface)*)& myBasisSurf);
345       NbUK = BSur->NbUKnots();
346       NbVK = BSur->NbVKnots();
347       TColStd_Array1OfReal UKnots(1,NbUK);
348       TColStd_Array1OfReal VKnots(1,NbVK);
349       BSur->UKnots(UKnots);
350       BSur->VKnots(VKnots);
351       BSplCLib::Hunt(UKnots,U,NU);
352       BSplCLib::Hunt(VKnots,V,NV);
353       if (NU < 1) NU=1;
354       if (NU >= NbUK) NU=NbUK-1;
355       if (NbVK==2 && NV==1)
356         // Need to find the closest end
357         if (VKnots(NbVK)-V > V-VKnots(1))
358           isToSkipSecond = Standard_True;
359     }
360     else {NU = 1; NV = 1 ; NbVK = 2 ;}
361
362     if (myAlong(1) && NV == 1) 
363     {
364       L = *((Handle(Geom_BSplineSurface)*)& myOsculSurf1->Value(NU));
365       along = Standard_True;
366     }
367     if (myAlong(2) && (NV == NbVK-1) && !isToSkipSecond)
368     {
369       // t means that derivative vector of osculating surface is opposite
370       // to the original. This happens when (v-t)^k is negative, i.e.
371       // difference between degrees (k) is odd and t is the last parameter
372       if (myKdeg->Value(NU)%2) t = Standard_True;
373       L = *((Handle(Geom_BSplineSurface)*)& myOsculSurf2->Value(NU));
374       along = Standard_True;
375     }
376   }
377   return along;
378 }
379
380 //=======================================================================
381 //function : VOscSurf
382 //purpose  : 
383 //=======================================================================
384
385 Standard_Boolean Geom_OsculatingSurface::VOscSurf
386                   (const Standard_Real U,
387                    const Standard_Real V,
388                    Standard_Boolean& t,
389                    Handle(Geom_BSplineSurface)& L) const
390 {
391   Standard_Boolean along = Standard_False;
392   if (myAlong(3) || myAlong(4)) 
393   {
394     Standard_Integer NU = 1, NV = 1;
395     Standard_Real u1,u2,v1,v2;
396     t = Standard_False;
397     myBasisSurf->Bounds(u1,u2,v1,v2);
398     Standard_Integer NbUK,NbVK;
399     Standard_Boolean isToSkipSecond = Standard_False;
400     if (myBasisSurf->IsKind(STANDARD_TYPE(Geom_BSplineSurface))) 
401     {
402       Handle(Geom_BSplineSurface) BSur = 
403                     *((Handle(Geom_BSplineSurface)*)& myBasisSurf);
404       NbUK = BSur->NbUKnots();
405       NbVK = BSur->NbVKnots();
406       TColStd_Array1OfReal UKnots(1,NbUK);
407       TColStd_Array1OfReal VKnots(1,NbVK);
408       BSur->UKnots(UKnots);
409       BSur->VKnots(VKnots);
410       BSplCLib::Hunt(UKnots,U,NU);
411       BSplCLib::Hunt(VKnots,V,NV);
412       if (NV < 1) NV=1;
413       if (NV >= NbVK) NV=NbVK-1;
414       if (NbUK==2 && NU==1)
415         // Need to find the closest end
416         if (UKnots(NbUK)-U > U-UKnots(1))
417           isToSkipSecond = Standard_True;
418     }
419     else {NU = 1; NV = 1 ; NbUK = 2;}
420
421     if (myAlong(3) && NU == 1)  
422     {
423       L = *((Handle(Geom_BSplineSurface)*)& myOsculSurf1->Value(NV));
424       along = Standard_True;
425     }
426     if (myAlong(4) && (NU == NbUK-1) && !isToSkipSecond)
427     {
428       if (myKdeg->Value(NV)%2) t = Standard_True;
429       L = *((Handle(Geom_BSplineSurface)*)& myOsculSurf2->Value(NV));
430       along = Standard_True;
431     }
432   }
433   return along;
434 }
435
436 //=======================================================================
437 //function : BuildOsculatingSurface
438 //purpose  : 
439 //=======================================================================
440
441 Standard_Boolean  Geom_OsculatingSurface::BuildOsculatingSurface
442        (const Standard_Real Param,
443         const Standard_Integer SUKnot,
444         const Standard_Integer SVKnot,
445         const Handle(Geom_BSplineSurface)& BS,
446         Handle(Geom_BSplineSurface)& BSpl) const
447 {
448   Standard_Integer i, j;
449   Standard_Boolean OsculSurf=Standard_True;
450 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
451   cout<<"t = "<<Param<<endl;
452   cout<<"======================================"<<endl<<endl;
453 #endif
454
455 // for cache
456   Standard_Integer MinDegree,
457                   MaxDegree ;
458   Standard_Real udeg, vdeg;
459   udeg = BS->UDegree();
460   vdeg = BS->VDegree();
461   if( (IsAlongU() && vdeg <=1) || (IsAlongV() && udeg <=1))
462   {
463 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
464       cout<<" surface osculatrice nulle "<<endl;
465 #endif
466       //Standard_ConstructionError::Raise("Geom_OsculatingSurface");
467       OsculSurf=Standard_False;
468   }
469   else
470   {
471       MinDegree = (Standard_Integer ) Min(udeg,vdeg) ;
472       MaxDegree = (Standard_Integer ) Max(udeg,vdeg) ;
473
474       TColgp_Array2OfPnt cachepoles(1, MaxDegree + 1, 1, MinDegree + 1);
475 // end for cache
476
477 // for polynomial grid 
478       Standard_Integer MaxUDegree, MaxVDegree;
479       Standard_Integer UContinuity, VContinuity;
480
481       Handle(TColStd_HArray2OfInteger) NumCoeffPerSurface = 
482                                    new TColStd_HArray2OfInteger(1, 1, 1, 2);
483       Handle(TColStd_HArray1OfReal) PolynomialUIntervals = 
484                                    new TColStd_HArray1OfReal(1, 2);
485       Handle(TColStd_HArray1OfReal) PolynomialVIntervals = 
486                                    new TColStd_HArray1OfReal(1, 2);
487       Handle(TColStd_HArray1OfReal) TrueUIntervals = 
488                                    new TColStd_HArray1OfReal(1, 2);
489       Handle(TColStd_HArray1OfReal) TrueVIntervals = 
490                                    new TColStd_HArray1OfReal(1, 2);
491       MaxUDegree = (Standard_Integer ) udeg;
492       MaxVDegree = (Standard_Integer ) vdeg;
493
494       for (i=1;i<=2;i++) 
495       {
496         PolynomialUIntervals->ChangeValue(i) = i-1;
497         PolynomialVIntervals->ChangeValue(i) = i-1;
498         TrueUIntervals->ChangeValue(i) = BS->UKnot(SUKnot+i-1);
499         TrueVIntervals->ChangeValue(i) = BS->VKnot(SVKnot+i-1);
500       }
501
502
503       Standard_Integer OscUNumCoeff=0, OscVNumCoeff=0;
504       if (IsAlongU()) 
505       {
506 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
507         cout<<">>>>>>>>>>> AlongU"<<endl;
508 #endif
509         OscUNumCoeff = (Standard_Integer ) udeg + 1;  
510         OscVNumCoeff = (Standard_Integer ) vdeg;  
511       }
512       if (IsAlongV()) 
513       {
514 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
515         cout<<">>>>>>>>>>> AlongV"<<endl;
516 #endif
517         OscUNumCoeff = (Standard_Integer ) udeg;  
518         OscVNumCoeff = (Standard_Integer ) vdeg + 1;  
519       }
520       NumCoeffPerSurface->ChangeValue(1,1) = OscUNumCoeff;  
521       NumCoeffPerSurface->ChangeValue(1,2) = OscVNumCoeff;  
522
523       Handle(TColStd_HArray1OfReal) Coefficients = new TColStd_HArray1OfReal(1, 
524              NumCoeffPerSurface->Value(1,1)*NumCoeffPerSurface->Value(1,2)*3);
525 //    end for polynomial grid
526
527 //    building the cache
528       Standard_Integer ULocalIndex, VLocalIndex;
529       Standard_Real ucacheparameter, vcacheparameter,uspanlength, vspanlength;
530       TColgp_Array2OfPnt NewPoles(1, BS->NbUPoles(), 1, BS->NbVPoles());
531       TColStd_Array1OfReal UFlatKnots(1, BS->NbUPoles() + BS->UDegree() + 1);
532       TColStd_Array1OfReal VFlatKnots(1, BS->NbVPoles() + BS->VDegree() + 1);
533       BS->Poles(NewPoles);
534       BS->UKnotSequence(UFlatKnots);
535       BS->VKnotSequence(VFlatKnots);
536
537       VLocalIndex = 0;
538       ULocalIndex = 0;
539       for(j = 1; j <= SVKnot; j++) VLocalIndex += BS->VMultiplicity(j);
540       for(i = 1; i <= SUKnot; i++) ULocalIndex += BS->UMultiplicity(i);
541       ucacheparameter = BS->UKnot(SUKnot);
542       vcacheparameter = BS->VKnot(SVKnot);
543       vspanlength = BS->VKnot(SVKnot + 1) - BS->VKnot(SVKnot);
544       uspanlength = BS->UKnot(SUKnot + 1) - BS->UKnot(SUKnot);
545
546       // On se ramene toujours a un parametrage tel que localement ce soit l'iso 
547       // u=0 ou v=0 qui soit degeneree
548
549       Standard_Boolean IsVNegative = Param > vcacheparameter + vspanlength/2;
550       Standard_Boolean IsUNegative = Param > ucacheparameter + uspanlength/2;
551
552       if (IsAlongU() && (Param > vcacheparameter + vspanlength/2))
553         vcacheparameter = vcacheparameter +  vspanlength;
554       if (IsAlongV() && (Param > ucacheparameter + uspanlength/2))
555         ucacheparameter = ucacheparameter +  uspanlength;
556
557       BSplSLib::BuildCache(ucacheparameter,   
558                            vcacheparameter,   
559                            uspanlength,         
560                            vspanlength,         
561                            BS->IsUPeriodic(),
562                            BS->IsVPeriodic(),
563                            BS->UDegree(),       
564                            BS->VDegree(),       
565                            ULocalIndex,         
566                            VLocalIndex,         
567                            UFlatKnots,
568                            VFlatKnots,
569                            NewPoles,
570                            BSplSLib::NoWeights(),
571                            cachepoles,
572                            BSplSLib::NoWeights());
573       Standard_Integer m, n, index;
574       TColgp_Array2OfPnt OscCoeff(1,OscUNumCoeff , 1, OscVNumCoeff);
575
576       if (IsAlongU()) 
577         {
578           if (udeg > vdeg) 
579             {
580               for(n = 1; n <= udeg + 1; n++) 
581                 for(m = 1; m <= vdeg; m++)
582                   OscCoeff(n,m) = cachepoles(n,m+1) ;
583             }
584           else
585             {
586               for(n = 1; n <= udeg + 1; n++) 
587                 for(m = 1; m <= vdeg; m++)
588                   OscCoeff(n,m) = cachepoles(m+1,n) ;
589             }
590           if (IsVNegative) PLib::VTrimming(-1,0,OscCoeff,PLib::NoWeights2());
591
592           index=1;
593           for(n = 1; n <= udeg + 1; n++) 
594             for(m = 1; m <= vdeg; m++)
595               {
596                 Coefficients->ChangeValue(index++) = OscCoeff(n,m).X();
597                 Coefficients->ChangeValue(index++) = OscCoeff(n,m).Y();
598                 Coefficients->ChangeValue(index++) = OscCoeff(n,m).Z();
599               }
600         }
601
602       if (IsAlongV()) 
603         {
604           if (udeg > vdeg) 
605             {
606               for(n = 1; n <= udeg; n++) 
607                 for(m = 1; m <= vdeg + 1; m++)
608                   OscCoeff(n,m) = cachepoles(n+1,m);
609             }
610           else
611             {
612               for(n = 1; n <= udeg; n++) 
613                 for(m = 1; m <= vdeg + 1; m++)
614                   OscCoeff(n,m) = cachepoles(m,n+1);
615             }
616           if (IsUNegative) PLib::UTrimming(-1,0,OscCoeff,PLib::NoWeights2());
617           index=1;
618           for(n = 1; n <= udeg; n++) 
619             for(m = 1; m <= vdeg + 1; m++)
620               {
621                 Coefficients->ChangeValue(index++) = OscCoeff(n,m).X();
622                 Coefficients->ChangeValue(index++) = OscCoeff(n,m).Y();
623                 Coefficients->ChangeValue(index++) = OscCoeff(n,m).Z();
624               }
625         }
626
627       if (IsAlongU()) MaxVDegree--;
628       if (IsAlongV()) MaxUDegree--;
629       UContinuity = - 1;
630       VContinuity = - 1;
631
632       Convert_GridPolynomialToPoles Data(1,1,
633                                          UContinuity,
634                                          VContinuity,
635                                          MaxUDegree,
636                                          MaxVDegree,
637                                          NumCoeffPerSurface,
638                                          Coefficients,
639                                          PolynomialUIntervals,
640                                          PolynomialVIntervals,
641                                          TrueUIntervals,
642                                          TrueVIntervals);
643   
644 //      Handle(Geom_BSplineSurface) BSpl = 
645         BSpl =new Geom_BSplineSurface(Data.Poles()->Array2(),
646                                 Data.UKnots()->Array1(),
647                                 Data.VKnots()->Array1(),
648                                 Data.UMultiplicities()->Array1(),
649                                 Data.VMultiplicities()->Array1(),
650                                 Data.UDegree(),
651                                 Data.VDegree(),
652                                 0, 0);
653 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
654       cout<<"^====================================^"<<endl<<endl;
655 #endif
656
657 //      L=BSpl;
658     }
659   return OsculSurf;
660 }
661
662 //=======================================================================
663 //function : IsQPunctual
664 //purpose  : 
665 //=======================================================================
666
667 Standard_Boolean Geom_OsculatingSurface::IsQPunctual
668                   (const Handle(Geom_Surface)& S,
669                    const Standard_Real         Param,
670                    const GeomAbs_IsoType       IT,
671                    const Standard_Real         TolMin,
672                    const Standard_Real         TolMax) const
673 {
674     Standard_Real U1=0,U2=0,V1=0,V2=0,T;
675     Standard_Boolean Along = Standard_True;
676     S->Bounds(U1,U2,V1,V2);
677     gp_Vec D1U,D1V;
678     gp_Pnt P;
679     Standard_Real Step,D1NormMax;
680     if (IT == GeomAbs_IsoV) 
681     {
682       Step = (U2 - U1)/10;
683       D1NormMax=0.;
684       for (T=U1;T<=U2;T=T+Step) 
685       {
686         S->D1(T,Param,P,D1U,D1V);
687         D1NormMax=Max(D1NormMax,D1U.Magnitude());
688       }
689
690 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
691       cout << " D1NormMax = " << D1NormMax << endl;
692 #endif
693       if (D1NormMax >TolMax || D1NormMax < TolMin ) 
694            Along = Standard_False;
695     }
696     else 
697     {
698       Step = (V2 - V1)/10;
699       D1NormMax=0.;
700       for (T=V1;T<=V2;T=T+Step) 
701       {
702         S->D1(Param,T,P,D1U,D1V);
703         D1NormMax=Max(D1NormMax,D1V.Magnitude());
704       }
705 #if defined(DEB) && defined(OCCT_DEVELOPMENT)
706       cout << " D1NormMax = " << D1NormMax << endl;
707 #endif
708       if (D1NormMax >TolMax || D1NormMax < TolMin ) 
709            Along = Standard_False;
710
711
712     }
713     return Along;
714 }
715
716 //=======================================================================
717 //function : HasOscSurf
718 //purpose  : 
719 //=======================================================================
720
721  Standard_Boolean Geom_OsculatingSurface::HasOscSurf() const
722 {
723   return (myAlong(1) || myAlong(2) || myAlong(3) || myAlong(4));
724 }
725
726 //=======================================================================
727 //function : IsAlongU
728 //purpose  : 
729 //=======================================================================
730
731 Standard_Boolean Geom_OsculatingSurface::IsAlongU() const
732 {
733   return (myAlong(1) || myAlong(2));
734 }
735 //=======================================================================
736 //function : IsAlongV
737 //purpose  : 
738 //=======================================================================
739
740 Standard_Boolean Geom_OsculatingSurface::IsAlongV() const
741 {
742   return (myAlong(3) || myAlong(4));
743 }
744
745
746 //=======================================================================
747 //function : IsGetSeqOfL1
748 //purpose  : 
749 //=======================================================================
750
751 const Geom_SequenceOfBSplineSurface& Geom_OsculatingSurface::GetSeqOfL1() const
752 {
753   return myOsculSurf1->Sequence();
754 }
755 //=======================================================================
756 //function : IsGetSeqOfL2
757 //purpose  : 
758 //=======================================================================
759
760 const Geom_SequenceOfBSplineSurface& Geom_OsculatingSurface::GetSeqOfL2() const
761 {
762   return myOsculSurf2->Sequence();
763 }
764 //=======================================================================
765 //function : ClearOsculFlags
766 //purpose  : 
767 //=======================================================================
768
769 void Geom_OsculatingSurface::ClearOsculFlags()
770 {
771     myAlong.SetValue(1,Standard_False);
772     myAlong.SetValue(2,Standard_False);
773     myAlong.SetValue(3,Standard_False);
774     myAlong.SetValue(4,Standard_False);
775
776 }
777
778
779