0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / Adaptor3d / Adaptor3d_CurveOnSurface.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #define No_Standard_OutOfRange
15
16
17 #include <Adaptor3d_CurveOnSurface.hxx>
18
19 #include <Adaptor2d_Curve2d.hxx>
20 #include <Adaptor3d_Surface.hxx>
21 #include <Adaptor3d_InterFunc.hxx>
22 #include <ElCLib.hxx>
23 #include <ElSLib.hxx>
24 #include <Geom2d_BezierCurve.hxx>
25 #include <Geom2d_BSplineCurve.hxx>
26 #include <Geom_BezierCurve.hxx>
27 #include <Geom_BSplineCurve.hxx>
28 #include <Geom_OffsetSurface.hxx>
29 #include <Geom_SurfaceOfRevolution.hxx>
30 #include <gp_Ax22d.hxx>
31 #include <gp_Circ.hxx>
32 #include <gp_Circ2d.hxx>
33 #include <gp_Elips.hxx>
34 #include <gp_Elips2d.hxx>
35 #include <gp_Hypr.hxx>
36 #include <gp_Hypr2d.hxx>
37 #include <gp_Lin.hxx>
38 #include <gp_Lin2d.hxx>
39 #include <gp_Parab.hxx>
40 #include <gp_Parab2d.hxx>
41 #include <gp_Pnt.hxx>
42 #include <gp_Pnt2d.hxx>
43 #include <gp_Vec.hxx>
44 #include <gp_Vec2d.hxx>
45 #include <math_FunctionRoots.hxx>
46 #include <Precision.hxx>
47 #include <Standard_Assert.hxx>
48 #include <Standard_DomainError.hxx>
49 #include <Standard_NoSuchObject.hxx>
50 #include <Standard_NotImplemented.hxx>
51 #include <TColgp_Array1OfPnt.hxx>
52 #include <TColgp_Array1OfPnt2d.hxx>
53 #include <TColStd_Array1OfInteger.hxx>
54 #include <TColStd_Array1OfReal.hxx>
55 #include <TColStd_HSequenceOfReal.hxx>
56
57 IMPLEMENT_STANDARD_RTTIEXT(Adaptor3d_CurveOnSurface, Adaptor3d_Curve)
58
59 static gp_Pnt to3d(const gp_Pln& Pl, const gp_Pnt2d& P)
60 {
61   return ElSLib::Value(P.X(),P.Y(),Pl);
62 }
63
64 static gp_Vec to3d(const gp_Pln& Pl, const gp_Vec2d& V)
65 {
66   gp_Vec Vx = Pl.XAxis().Direction();
67   gp_Vec Vy = Pl.YAxis().Direction();
68   Vx.Multiply(V.X());
69   Vy.Multiply(V.Y());
70   Vx.Add(Vy);
71   return Vx;
72 }
73
74 static gp_Ax2 to3d(const gp_Pln& Pl, const gp_Ax22d& A)
75 {
76   gp_Pnt P = to3d(Pl,A.Location());
77   gp_Vec VX = to3d(Pl,A.XAxis().Direction());
78   gp_Vec VY = to3d(Pl,A.YAxis().Direction());
79   return gp_Ax2(P,VX.Crossed(VY),VX);
80 }
81
82 static gp_Circ to3d(const gp_Pln& Pl, const gp_Circ2d& C)
83 {
84   return gp_Circ(to3d(Pl,C.Axis()),C.Radius());
85 }
86
87 static gp_Elips to3d(const gp_Pln& Pl, const gp_Elips2d& E)
88 {
89   return gp_Elips(to3d(Pl,E.Axis()),E.MajorRadius(),E.MinorRadius());
90 }
91
92 static gp_Hypr to3d(const gp_Pln& Pl, const gp_Hypr2d& H)
93 {
94   return gp_Hypr(to3d(Pl,H.Axis()),H.MajorRadius(),H.MinorRadius());
95 }
96
97 static gp_Parab to3d(const gp_Pln& Pl, const gp_Parab2d& P)
98 {
99   return gp_Parab(to3d(Pl,P.Axis()),P.Focal());
100 }
101
102 static gp_Vec SetLinearForm(const gp_Vec2d& DW,  const gp_Vec2d& D2W,  const gp_Vec2d& D3W,
103                             const gp_Vec&   D1U, const gp_Vec&   D1V,  const gp_Vec&   D2U,
104                             const gp_Vec&   D2V, const gp_Vec&   D2UV, const gp_Vec&   D3U,
105                             const gp_Vec&   D3V, const gp_Vec&   D3UUV,const gp_Vec&   D3UVV)
106 {gp_Vec V31, V32, V33, V34,V3 ;
107  V31.SetLinearForm(DW.X(),D1U,
108                    D2W.X()*DW.X(),D2U,
109                    D2W.X()*DW.Y(),D2UV);
110  V31.SetLinearForm(D3W.Y(),D1V,
111                    D2W.Y()*DW.X(),D2UV,
112                    D2W.Y()*DW.Y(),D2V,
113                    V31);
114  V32.SetLinearForm(DW.X()*DW.X()*DW.Y(),D3UUV,
115                    DW.X()*DW.Y()*DW.Y(),D3UVV);
116  V32.SetLinearForm(D2W.X()*DW.Y()+DW.X()*D2W.Y(),D2UV,
117                    DW.X()*DW.Y()*DW.Y(),D3UVV,
118                    V32);
119  V33.SetLinearForm(2*D2W.X()*DW.X(),D2U,
120                    DW.X()*DW.X()*DW.X(),D3U,
121                    DW.X()*DW.X()*DW.Y(),D3UUV);
122  
123  V34.SetLinearForm(2*D2W.Y()*DW.Y(),D2V,
124                    DW.Y()*DW.Y()*DW.X(),D3UVV,
125                    DW.Y()*DW.Y()*DW.Y(),D3V);
126  V3.SetLinearForm(1,V31,2,V32,1,V33,V34);
127  return V3;
128 }
129
130 //=======================================================================
131 static void CompareBounds(gp_Pnt2d& P1,
132                           gp_Pnt2d& P2)//SVV
133 {
134    Standard_Real Lx = P1.X(),Ly = P1.Y();
135    Standard_Real Rx = P2.X(),Ry = P2.Y();
136    
137    if (Lx > Rx) { P1.SetX(Rx); P2.SetX(Lx);}
138    if (Ly > Ry) { P1.SetY(Ry); P2.SetY(Ly);}
139 }
140
141 //=======================================================================
142 //function :Hunt
143 //purpose  : 
144 //=======================================================================
145 static void Hunt(const TColStd_Array1OfReal& Arr,
146                  const Standard_Real Coord,
147                  Standard_Integer& Iloc)
148 {//Warning: Hunt is used to find number of knot which equals coordinate component,
149   //        when coordinate component definitly equals a knot only.
150   Standard_Real Tol=Precision::PConfusion()/10;
151   Standard_Integer i=1; 
152   while((i <= Arr.Upper()) && (Abs(Coord - Arr(i)) > Tol)){
153     i++;}
154  
155   if(Abs(Coord - Arr(i)) < Tol)
156     Iloc = i;
157   else
158     if(Abs(Coord - Arr(i)) > Tol) 
159       throw Standard_NotImplemented("Adaptor3d_CurveOnSurface:Hunt");
160 }
161
162 //=======================================================================
163 //function :ReverseParam
164 //purpose  : 
165 //=======================================================================
166
167 static void ReverseParam(const Standard_Real In1,
168                          const Standard_Real In2,
169                          Standard_Real& Out1,
170                          Standard_Real& Out2 )
171 {
172
173   if(In1>In2)  {Out1=In2;
174                 Out2=In1;}
175   else         {Out1=In1;
176                 Out2=In2;}
177 }
178 //=======================================================================
179 //function :ReverseParam
180 //purpose  : 
181 //=======================================================================
182
183 static void ReverseParam(const Standard_Integer In1,
184                          const Standard_Integer In2,
185                          Standard_Integer& Out1,
186                          Standard_Integer& Out2 )
187 {
188   if(In1>In2)  {Out1=In2;
189                 Out2=In1;}
190   else         {Out1=In1;
191                 Out2=In2;}
192 }
193
194 //=======================================================================
195 //function :FindBounds
196 //purpose  : 
197 //=======================================================================
198 static void FindBounds(const TColStd_Array1OfReal& Arr,
199                        const Standard_Real Coord,
200                        const Standard_Real Der,
201                        Standard_Integer& Bound1,
202                        Standard_Integer& Bound2,
203                        Standard_Boolean& DerNull)
204
205 {
206   Standard_Integer N=0;
207   Standard_Real Tol=Precision::PConfusion()/10;
208   Hunt(Arr,Coord,N);
209   DerNull=Standard_False;
210   
211   if(N==Bound1){ if(Abs(Der) > Tol) DerNull = Standard_False;
212                       if(Abs(Der)<= Tol) DerNull = Standard_True;
213                       Bound1=N;Bound2=N+1; return;
214                     }
215   if(N==Bound2){ if( Abs(Der) > Tol ) DerNull = Standard_False;
216                       if( Abs(Der)<= Tol ) DerNull = Standard_True;
217                       Bound1=N-1;Bound2=N; return;
218                     }
219   if((N!=Bound1)&&(N!=Bound2))  { 
220     if(Abs(Der) > Tol ) { 
221       if(Der>0) {Bound1=N;Bound2= N+1;}
222       else
223       if(Der<0){Bound1=N-1;Bound2=N;}
224       DerNull = Standard_False;
225     }
226     if(Abs(Der) <=Tol ) {
227       DerNull = Standard_True;
228       Bound1=N-1;
229       Bound2=N+1;
230     }
231   } 
232 }
233
234 //=======================================================================
235 //function :Locate1Coord
236 //purpose  : along BSpline curve
237 //=======================================================================
238
239 static void Locate1Coord(const Standard_Integer Index,
240                          const gp_Pnt2d& UV, 
241                          const gp_Vec2d& DUV,
242                          const Handle(Geom_BSplineCurve)& BSplC,
243                          gp_Pnt2d& LeftBot, gp_Pnt2d& RightTop)
244 {
245   Standard_Real Comp1=0, DComp1=0, cur, f = 0.0, l = 0.0;
246   Standard_Real Tol = Precision::PConfusion()/10;
247   Standard_Integer i = 1, Bnd1, Bnd2;
248   Standard_Boolean DIsNull= Standard_False; 
249   TColStd_Array1OfReal Arr(1,BSplC->NbKnots());  BSplC->Knots(Arr);
250   
251   if(Index==1) {    Comp1=UV.X();  DComp1=DUV.X(); } 
252   if(Index==2) {    Comp1=UV.Y();  DComp1=DUV.Y(); } 
253
254   Standard_Integer Lo = BSplC->FirstUKnotIndex(), Up = BSplC->LastUKnotIndex();
255
256   i = Lo;
257   while ( ( Abs(BSplC->Knot(i)-Comp1)>Tol )&& (i!=Up ) ) i++;
258   cur=BSplC->Knot(i);
259
260   if( Abs(Comp1-cur)<=Tol) {
261  
262     Bnd1 = Lo; Bnd2 = Up;
263     FindBounds(Arr,cur,DComp1,Bnd1,Bnd2,DIsNull); 
264     ReverseParam(Bnd1,Bnd2,Bnd1,Bnd2);
265     
266     if(DIsNull==Standard_False){
267       if(Index==1)  {LeftBot.SetX(BSplC->Knot(Bnd1));
268                      RightTop.SetX(BSplC->Knot(Bnd2));}
269       else 
270         if(Index==2){ LeftBot.SetY(BSplC->Knot(Bnd1));
271                       RightTop.SetY(BSplC->Knot(Bnd2)); }
272     }
273     else
274       if(DIsNull==Standard_True){
275         if( Abs( Comp1-(f=BSplC->Knot(Lo))) <= Tol)
276           {       
277             if(Index==1)   { LeftBot.SetX(BSplC->Knot(Lo));
278                              RightTop.SetX(BSplC->Knot(Lo+1));}
279             else if(Index==2)  { LeftBot.SetY(BSplC->Knot(Lo));
280                                  RightTop.SetY(BSplC->Knot(Lo+1));}
281            } else
282              if( Abs( Comp1-(l=BSplC->Knot(Up))) <= Tol)
283                {
284                  if(Index==1)   {  LeftBot.SetX(BSplC->Knot(Up-1));
285                                    RightTop.SetX(BSplC->Knot(Up));}
286                  else if(Index==2)  {LeftBot.SetY(BSplC->Knot(Up-1));
287                                      RightTop.SetY(BSplC->Knot(Up));}
288                }else
289                  if(Index==1)   {  LeftBot.SetX(BSplC->Knot(Bnd1));
290                                    RightTop.SetX(BSplC->Knot(Bnd2));}
291                  else if(Index==2)  {LeftBot.SetY(BSplC->Knot(Bnd1));
292                                      RightTop.SetY(BSplC->Knot(Bnd2));}
293       }
294   } 
295   else//*********if Coord != Knot
296     {
297       i=Lo;
298       while (i < Up) {
299         //if((f=BSplC->Knot(i))<Comp1 && (l=BSplC->Knot(i+1))>Comp1) break;
300         //skl 28.03.2002 for OCC233
301         f=BSplC->Knot(i);
302         l=BSplC->Knot(i+1);
303         if(f<Comp1 && l>Comp1) break;
304         i++; 
305       }
306       ReverseParam(f,l,f,l);
307      
308       if(i!=Up)   {
309         if(Abs(DComp1)<Tol) 
310           { if(Index==1) {LeftBot.SetX(f); RightTop.SetX(l);}else
311               if(Index==2) {LeftBot.SetY(f); RightTop.SetY(l); }
312           }else
313             if(Abs(DComp1)>Tol) 
314               { 
315                 if(Index==1) {
316                   if(DComp1>0) {LeftBot.SetX(Comp1); RightTop.SetX(l);}   else
317                     if(DComp1<0) {LeftBot.SetX(f); RightTop.SetX(Comp1);}
318                 }
319                 else
320                   if(Index==2) {
321                     if(DComp1>0) {LeftBot.SetY(Comp1); RightTop.SetY(l);} else
322                       if(DComp1<0) {LeftBot.SetY(f); RightTop.SetY(Comp1);};
323                   }
324               }
325       }else
326         if(i==Up)   {
327           if(Index==1) {LeftBot.SetX(Comp1); RightTop.SetX(BSplC->Knot(i));}else
328             if(Index==2) {LeftBot.SetY(Comp1); RightTop.SetY(BSplC->Knot(i)); }
329         }
330     }
331 }
332
333
334 //=======================================================================
335 //function :Locate1Coord
336 //purpose  : 
337 //=======================================================================
338
339 static void Locate1Coord(const Standard_Integer Index,
340         const gp_Pnt2d& UV, 
341         const gp_Vec2d& DUV,
342         const Handle(Geom_BSplineSurface)& BSplS,
343         Standard_Boolean& DIsNull,
344         gp_Pnt2d& LeftBot, 
345         gp_Pnt2d& RightTop)
346 {
347   Standard_Real Comp1=0,DComp1=0; 
348   Standard_Real Tol = Precision::PConfusion()/10;
349   Standard_Integer i=1, Up=0, Up1, Up2, Down=0, Down1, Down2;
350   Standard_Real cur = 0.;
351
352   DIsNull= Standard_False; 
353
354   Up1 =  BSplS->LastUKnotIndex();
355   Down1 = BSplS->FirstUKnotIndex();
356   Up2 =  BSplS->LastVKnotIndex();
357   Down2 = BSplS->FirstVKnotIndex();
358
359   if(Index==1)
360   { 
361     i = Down1; 
362     Comp1 =  UV.X(); 
363     DComp1= DUV.X(); 
364     Up=Up1; 
365     Down=Down1;
366
367     while ( ( Abs(BSplS->UKnot(i)-Comp1)>Tol )&&(i!=Up1 ) )
368     {
369       i++;
370     }
371
372     cur = BSplS->UKnot(i); 
373   }
374   else if(Index==2)
375   {
376     i = Down2;
377     Comp1 = UV.Y();
378     DComp1=DUV.Y();
379     Up=Up2;
380     Down=Down2;
381
382     while ( ( Abs(BSplS->VKnot(i)-Comp1)>Tol )&&(i!=Up2 ) )
383     {
384       i++;
385     }
386
387     cur = BSplS->VKnot(i);
388   }
389   
390   if( Abs(Comp1-cur)<=Tol ) 
391   { 
392     Standard_Integer Bnd1 = Down, Bnd2 = Up;
393     if(Index==1)
394     {
395       TColStd_Array1OfReal Arr1(1,BSplS->NbUKnots());
396       BSplS->UKnots(Arr1); //   Up1=Arr1.Upper(); Down1=Arr1.Lower();
397       FindBounds(Arr1,cur,DUV.X(),Bnd1,Bnd2,DIsNull); 
398     }
399     else if(Index==2)
400     {
401       TColStd_Array1OfReal Arr2(1,BSplS->NbVKnots());
402       BSplS->VKnots(Arr2); //   Up2=Arr2.Upper(); Down2=Arr2.Lower();
403       FindBounds(Arr2,cur,DUV.Y(),Bnd1,Bnd2,DIsNull); 
404     }
405     
406     ReverseParam(Bnd1,Bnd2,Bnd1,Bnd2);
407
408     if(DIsNull==Standard_False)
409     {
410       if(Index==1)
411       {
412         LeftBot.SetX(BSplS->UKnot(Bnd1));
413         RightTop.SetX(BSplS->UKnot(Bnd2));
414       }
415       else if(Index==2)
416       { 
417         LeftBot.SetY(BSplS->VKnot(Bnd1));
418         RightTop.SetY(BSplS->VKnot(Bnd2));
419       }
420     }      
421   }
422   else//*********if Coord != Knot
423   {
424     if( (Index==1)&&(Comp1 < BSplS->UKnot(Down)) )
425     { 
426       LeftBot.SetX(BSplS->UKnot(Down)); 
427       RightTop.SetX( BSplS->UKnot(Down + 1) );
428       return;
429     }
430     else if( (Index==2)&&(Comp1 < BSplS->VKnot(Down)) )
431     { 
432       LeftBot.SetY(BSplS->VKnot(Down)); 
433       RightTop.SetY( BSplS->VKnot(Down + 1) );
434       return;
435     }
436     else if( (Index==1)&&(Comp1 > BSplS->UKnot(Up)) )
437     { 
438       RightTop.SetX(BSplS->UKnot(Up - 1)); 
439       LeftBot.SetX( BSplS->UKnot(Up) );
440       return;
441     }
442     else if( (Index==2)&&(Comp1 > BSplS->VKnot(Up)) )
443     { 
444       RightTop.SetY(BSplS->VKnot(Up - 1)); 
445       LeftBot.SetY( BSplS->VKnot(Up) );
446       return;
447     } 
448     else
449     {
450       Standard_Real f = 0., l = 1.;
451       if (Index==1)
452       {
453         f=BSplS->UKnot(Down);
454         l=BSplS->UKnot(Up);
455       }
456       else if (Index == 2)
457       {
458         f=BSplS->VKnot(Down);
459         l=BSplS->VKnot(Up);
460       }
461
462       i = Down;
463       if ((!(Comp1 < f))&&(!(Comp1 > l)))
464       {
465         if (Index==1)
466         {
467           while (!(((f=BSplS->UKnot(i)) < Comp1)&&((l=BSplS->UKnot(i+1)) > Comp1)) && (i<Up)) 
468           {
469             i++;
470           }
471         }
472         else if (Index==2)
473         {
474           while (!(((f=BSplS->VKnot(i)) < Comp1)&&((l=BSplS->VKnot(i+1)) > Comp1)) && (i<Up)) 
475           {
476             i++;
477           }
478         }
479       }
480       else
481         ReverseParam(f,l,f,l);
482
483       if(i!=Up)
484       {
485         if(Abs(DComp1)>Tol)
486         {
487           if(Index==1) 
488           {  
489             if(DComp1>0)
490             { 
491               LeftBot.SetX(Comp1); 
492               RightTop.SetX(l);
493             }
494             else if(DComp1<0)
495             {
496               LeftBot.SetX(f); 
497               RightTop.SetX(Comp1);
498             }
499           }
500           else if(Index==2)
501           {
502             if(DComp1>0)
503             { 
504               LeftBot.SetY(Comp1); 
505               RightTop.SetY(l);
506             }
507             else if(DComp1<0)
508             { 
509               LeftBot.SetY(f); 
510               RightTop.SetY(Comp1);
511             }
512           }
513         }
514         else
515         {
516           if(Abs(DComp1)<Tol)
517           {
518             if(Index==1)
519             {
520               LeftBot.SetX(f); 
521               RightTop.SetX(l);
522             }
523             else if(Index==2) 
524             { 
525               LeftBot.SetY(f); 
526               RightTop.SetY(l);
527             }
528           }
529         }
530       } 
531       else if(i==Up)
532       {
533         if(Index==1)
534         {
535           LeftBot.SetX(Comp1);
536           RightTop.SetX(BSplS->UKnot(i));
537         }
538         else if(Index==2)
539         { 
540           LeftBot.SetY(Comp1); 
541           RightTop.SetY(BSplS->VKnot(i));
542         }
543       }
544     }
545   }
546 }
547 //=======================================================================
548 //function :Locate2Coord
549 //purpose  : along non-BSpline curve
550 //=======================================================================
551
552
553 static void Locate2Coord(const Standard_Integer Index,
554                          const gp_Pnt2d& UV, const gp_Vec2d& DUV, 
555                          const Standard_Real I1, 
556                          const Standard_Real I2,
557                          gp_Pnt2d& LeftBot, gp_Pnt2d& RightTop)
558 {
559   Standard_Real Tol=Precision::PConfusion()/10;
560   Standard_Real Comp1=0,DComp1=0;
561   if(Index==1)   {   Comp1=UV.X();
562                      DComp1=DUV.X();} 
563   else
564     if(Index==2)   {Comp1=UV.Y();
565                     DComp1=DUV.Y();}
566   
567   if((Comp1!=I1)&&(Comp1!=I2))
568     { if(Abs(DComp1) > Tol)
569         {  if(DComp1 < 0) 
570              {  if(Index==1) {  LeftBot.SetX(I1);
571                                 RightTop.SetX(Comp1);}
572                 if(Index==2) {  LeftBot.SetY(I1);
573                                 RightTop.SetY(Comp1);}
574               }
575         else
576           if(DComp1 > 0) 
577             {   if(Index==1) {  LeftBot.SetX(Comp1);
578                                 RightTop.SetX(I2);}
579                 if(Index==2) {  LeftBot.SetY(Comp1);
580                                 RightTop.SetY(I2);}
581               }
582           else { if(Index==1) { LeftBot.SetX(I1); 
583                                 RightTop.SetX(I2);}
584                  if(Index==2) { LeftBot.SetY(I1);
585                                 RightTop.SetY(I2);}
586                }
587          }
588     else 
589       if(Abs(DComp1)<=Tol) {
590                               if(Index==1) { LeftBot.SetX(I1) ;
591                                              RightTop.SetX(I2);}
592                               if(Index==2) { LeftBot.SetY(I1) ;
593                                              RightTop.SetY(I2);}
594                             }
595     }else 
596       if(Abs(Comp1-I1)<Tol)
597         { if(Index==1) { LeftBot.SetX(I1) ;
598                          RightTop.SetX(I2);}
599           if(Index==2) { LeftBot.SetY(I1) ;
600                          RightTop.SetY(I2);}
601         }
602       else
603         if(Abs(Comp1-I2)<Tol)
604           {        if(Index==1) { LeftBot.SetX(I1); 
605                                   RightTop.SetX(I2);}
606                    if(Index==2) { LeftBot.SetY(I1);
607                                   RightTop.SetY(I2);}
608                  } 
609 }
610
611 //=======================================================================
612 //function :Locate2Coord
613 //purpose  : 
614 //=======================================================================
615
616 static void Locate2Coord(const Standard_Integer Index,
617                          const gp_Pnt2d& UV, const gp_Vec2d& DUV, 
618                          const Handle(Geom_BSplineSurface)& BSplS,
619                          const TColStd_Array1OfReal& Arr,
620                          gp_Pnt2d& LeftBot, gp_Pnt2d& RightTop)
621 {
622   Standard_Real Comp=0,DComp=0,Tmp1=0.0,Tmp2=0.0;
623   Standard_Real Tol=Precision::PConfusion()/10;
624   Standard_Integer N=0, NUp=0, NLo=0;
625   if(Index==1)
626     { Comp=UV.X();
627       DComp=DUV.Y();
628       NUp = BSplS->LastUKnotIndex();
629       NLo = BSplS->FirstUKnotIndex();
630     }
631   if(Index==2)
632      { Comp=UV.Y();
633        DComp=DUV.X(); 
634        NUp = BSplS->LastVKnotIndex();
635        NLo = BSplS->FirstVKnotIndex();
636      }
637   
638   if((DComp > 0)&&(Abs(DComp)>Tol)) {  
639     Hunt(Arr,Comp,N);
640     if (N >= NUp){
641       //limit case: Hunt() cought upper knot. Take the last span. 
642       N = NUp - 1;
643     }
644     if(Index==1) {  Tmp1=BSplS->UKnot(N);
645                     Tmp2=BSplS->UKnot(N+1);}
646     else
647       if(Index==2) {      Tmp1=BSplS->VKnot(N);
648                           Tmp2=BSplS->VKnot(N+1);}
649     
650     ReverseParam(Tmp1,Tmp2,Tmp1,Tmp2);
651     
652     if(Index==1) {      LeftBot.SetX(Tmp1);
653                         RightTop.SetX(Tmp2);}
654     else
655       if(Index==2) {      LeftBot.SetY(Tmp1);
656                           RightTop.SetY(Tmp2);}
657     }
658   else
659     if((DComp < 0)&&(Abs(DComp)>Tol)){      
660      Hunt(Arr,Comp,N);
661      if (N <= NLo) {
662        //limit case: Hunt() cought lower knot. Take the first span.
663        N = NLo + 1;
664      }
665      if(Index==1) {       Tmp1=BSplS->UKnot(N-1);
666                           Tmp2=BSplS->UKnot(N);}
667         else
668           if(Index==2) { Tmp1=BSplS->VKnot(N-1);
669                          Tmp2=BSplS->VKnot(N);}
670      
671         ReverseParam(Tmp1,Tmp2,Tmp1,Tmp2);
672      
673         if(Index==1) {    LeftBot.SetX(Tmp1);
674                           RightTop.SetX(Tmp2);}
675         else
676           if(Index==2) {            LeftBot.SetY(Tmp1);
677                                     RightTop.SetY(Tmp2);}
678    } 
679 }
680
681
682
683 //=======================================================================
684 //function : Adaptor3d_CurveOnSurface
685 //purpose  : 
686 //=======================================================================
687
688 Adaptor3d_CurveOnSurface::Adaptor3d_CurveOnSurface()
689      : myType(GeomAbs_OtherCurve), myIntCont(GeomAbs_CN)
690 {}
691
692 //=======================================================================
693 //function : Adaptor3d_CurveOnSurface
694 //purpose  : 
695 //=======================================================================
696
697 Adaptor3d_CurveOnSurface::Adaptor3d_CurveOnSurface
698 (const Handle(Adaptor3d_Surface)& S) 
699      : myType(GeomAbs_OtherCurve), myIntCont(GeomAbs_CN)
700 {
701   Load(S);
702 }
703
704 //=======================================================================
705 //function : Adaptor3d_CurveOnSurface
706 //purpose  : 
707 //=======================================================================
708
709 Adaptor3d_CurveOnSurface::Adaptor3d_CurveOnSurface
710 (const Handle(Adaptor2d_Curve2d)& C,
711  const Handle(Adaptor3d_Surface)& S)
712      : myType(GeomAbs_OtherCurve), myIntCont(GeomAbs_CN)
713 {
714   Load(S);
715   Load(C);
716 }
717
718 //=======================================================================
719 //function : ShallowCopy
720 //purpose  : 
721 //=======================================================================
722
723 Handle(Adaptor3d_Curve) Adaptor3d_CurveOnSurface::ShallowCopy() const
724 {
725   Handle(Adaptor3d_CurveOnSurface) aCopy = new Adaptor3d_CurveOnSurface();
726
727   if (!mySurface.IsNull())
728   {
729     aCopy->mySurface = mySurface->ShallowCopy();
730   }
731   if (!myCurve.IsNull())
732   {
733     aCopy->myCurve = myCurve->ShallowCopy();
734   }
735   aCopy->myType      = myType;
736   aCopy->myCirc      = myCirc;
737   aCopy->myLin       = myLin;
738   if (!myFirstSurf.IsNull())
739   {
740     aCopy->myFirstSurf = myFirstSurf->ShallowCopy();
741   }
742   if (!myLastSurf.IsNull())
743   {
744     aCopy->myLastSurf = myLastSurf->ShallowCopy();
745   }
746   aCopy->myIntervals = myIntervals;
747   aCopy->myIntCont   = myIntCont;
748
749   return aCopy;
750 }
751
752 //=======================================================================
753 //function : Load
754 //purpose  : 
755 //=======================================================================
756
757 void Adaptor3d_CurveOnSurface::Load(const Handle(Adaptor3d_Surface)& S) 
758 {
759   mySurface = S;
760   if (!myCurve.IsNull()) EvalKPart();
761 }
762
763 //=======================================================================
764 //function : Load
765 //purpose  :
766 //=======================================================================
767
768 void Adaptor3d_CurveOnSurface::Load(const Handle(Adaptor2d_Curve2d)& C)
769 {
770   myCurve = C;
771   if (mySurface.IsNull())
772   {
773     return;
774   }
775
776   EvalKPart();
777
778   GeomAbs_SurfaceType SType = mySurface->GetType();
779   if (SType == GeomAbs_OffsetSurface)
780   {
781     SType = mySurface->BasisSurface()->GetType();
782   }
783
784   if (SType == GeomAbs_BSplineSurface ||  
785       SType == GeomAbs_SurfaceOfExtrusion ||
786       SType == GeomAbs_SurfaceOfRevolution)
787   {
788     EvalFirstLastSurf();
789   }
790 }
791
792 //=======================================================================
793 //function : Load
794 //purpose  : 
795 //=======================================================================
796
797 void Adaptor3d_CurveOnSurface::Load (const Handle(Adaptor2d_Curve2d)& C,
798                                      const Handle(Adaptor3d_Surface)& S) 
799 {
800   Load (C);
801   Load (S);
802 }
803
804 //=======================================================================
805 //function : FirstParameter
806 //purpose  : 
807 //=======================================================================
808
809 Standard_Real Adaptor3d_CurveOnSurface::FirstParameter() const 
810 {
811   return myCurve->FirstParameter();
812 }
813
814 //=======================================================================
815 //function : LastParameter
816 //purpose  : 
817 //=======================================================================
818
819 Standard_Real Adaptor3d_CurveOnSurface::LastParameter() const 
820 {
821   return myCurve->LastParameter();
822 }
823
824 //=======================================================================
825 //function : Continuity
826 //purpose  : 
827 //=======================================================================
828
829 GeomAbs_Shape Adaptor3d_CurveOnSurface::Continuity() const
830 {
831   GeomAbs_Shape ContC  = myCurve->Continuity();
832   GeomAbs_Shape ContSu = mySurface->UContinuity();
833   if ( ContSu < ContC) ContC = ContSu;
834   GeomAbs_Shape ContSv = mySurface->VContinuity();
835   if ( ContSv < ContC) ContC = ContSv;
836
837   return ContC;
838 }
839
840 // Auxiliary: adds roots of equation to sorted sequence of parameters
841 // along curve, keeping it sorted and avoiding repetitions (within tolerance Tol)
842 static void AddIntervals (const Handle(TColStd_HSequenceOfReal)& theParameters, 
843                           const math_FunctionRoots& theRoots, Standard_Real theTol)
844 {
845   if (! theRoots.IsDone() || theRoots.IsAllNull())
846     return;
847
848   Standard_Integer nsol = theRoots.NbSolutions();
849   for (Standard_Integer i = 1; i <= nsol; i++)
850   {
851     Standard_Real param = theRoots.Value(i);
852     if (param - theParameters->Value(1) < theTol) // skip param if equal to or less than theParameters(1)
853       continue;
854     for (Standard_Integer j=2; j <= theParameters->Length(); ++j)
855     {
856       Standard_Real aDelta = theParameters->Value(j) - param;
857       if (aDelta > theTol)
858       {
859         theParameters->InsertBefore (j, param);
860         break;
861       }
862       else if (aDelta >= -theTol) // param == theParameters(j) within Tol
863         break;
864     }
865   }
866 }
867
868 //=======================================================================
869 //function : NbIntervals
870 //purpose  : 
871 //=======================================================================
872
873 Standard_Integer Adaptor3d_CurveOnSurface::NbIntervals (const GeomAbs_Shape S) const
874 {
875   if(S == myIntCont && !myIntervals.IsNull())
876     return myIntervals->Length()-1;
877   
878   Standard_Integer nu,nv,nc;
879   nu=mySurface->NbUIntervals(S);
880   nv=mySurface->NbVIntervals(S);
881   nc=myCurve->NbIntervals(S);
882
883   // Allocate the memory for arrays TabU, TabV, TabC only once using the buffer TabBuf.
884   TColStd_Array1OfReal TabBuf(1, nu + nv + nc + 3);
885   TColStd_Array1OfReal TabU(TabBuf(1), 1, nu+1);
886   TColStd_Array1OfReal TabV(TabBuf(nu + 2), 1, nv+1);
887   TColStd_Array1OfReal TabC(TabBuf(nu + nv + 3), 1, nc+1);
888
889   Standard_Integer NbSample = 20;
890   Standard_Real U,V,Tdeb,Tfin;
891   Tdeb=myCurve->FirstParameter();
892   Tfin=myCurve->LastParameter();
893
894   myCurve->Intervals(TabC,S);
895
896   Standard_Real Tol= Precision::PConfusion()/10;
897
898   // sorted sequence of parameters defining continuity intervals;
899   // started with own intervals of curve and completed by 
900   // additional points coming from surface discontinuities
901   Handle(TColStd_HSequenceOfReal) aIntervals = new TColStd_HSequenceOfReal;
902   for (Standard_Integer i = 1; i <= nc + 1; i++)
903   {
904     aIntervals->Append(TabC(i));
905   }
906  
907   if (nu>1)
908   {
909     mySurface->UIntervals(TabU,S);
910     for(Standard_Integer iu = 2;iu <= nu; iu++)
911     {
912       U = TabU.Value(iu);
913       Adaptor3d_InterFunc Func(myCurve,U,1);
914       math_FunctionRoots Resol(Func,Tdeb,Tfin,NbSample,Tol,Tol,Tol,0.);
915       AddIntervals (aIntervals, Resol, Tol);
916     }
917   }
918   if (nv>1)
919   {
920     mySurface->VIntervals(TabV,S);
921     for(Standard_Integer iv = 2;iv <= nv; iv++)
922     {
923       V = TabV.Value(iv);
924       Adaptor3d_InterFunc Func(myCurve,V,2);
925       math_FunctionRoots Resol(Func,Tdeb,Tfin,NbSample,Tol,Tol,Tol,0.);
926       AddIntervals (aIntervals, Resol, Tol);
927     }
928   }
929
930   // for case intervals==1 and first point == last point SequenceOfReal
931   // contains only one value, therefore it is necessary to add second
932   // value into aIntervals which will be equal first value.
933   if (aIntervals->Length() == 1)
934     aIntervals->Append (aIntervals->Value(1));
935
936   const_cast<Adaptor3d_CurveOnSurface*>(this)->myIntervals = aIntervals;
937   const_cast<Adaptor3d_CurveOnSurface*>(this)->myIntCont = S;
938   return myIntervals->Length() - 1;
939 }
940
941 //=======================================================================
942 //function : Intervals
943 //purpose  : 
944 //=======================================================================
945
946 void Adaptor3d_CurveOnSurface::Intervals(TColStd_Array1OfReal& T,
947                                          const GeomAbs_Shape S) const
948 {
949   NbIntervals(S);
950   Standard_ASSERT_RAISE (T.Length() == myIntervals->Length(), "Error: Wrong size of array buffer in call to Adaptor3d_CurveOnSurface::Intervals");
951   for(Standard_Integer i=1; i<=myIntervals->Length(); i++) {
952     T(i) = myIntervals->Value(i);
953   }
954 }
955
956 //=======================================================================
957 //function : Trim
958 //purpose  : 
959 //=======================================================================
960
961 Handle(Adaptor3d_Curve) Adaptor3d_CurveOnSurface::Trim
962 (const Standard_Real First, 
963  const Standard_Real Last, 
964  const Standard_Real Tol) const 
965 {
966   Handle(Adaptor3d_CurveOnSurface) HCS = new Adaptor3d_CurveOnSurface();
967   HCS->Load(mySurface);
968   HCS->Load(myCurve->Trim(First,Last,Tol));
969   return HCS;
970 }
971
972 //=======================================================================
973 //function : IsClosed
974 //purpose  : 
975 //=======================================================================
976
977 Standard_Boolean Adaptor3d_CurveOnSurface::IsClosed() const
978 {
979   return myCurve->IsClosed();
980 }
981
982 //=======================================================================
983 //function : IsPeriodic
984 //purpose  : 
985 //=======================================================================
986
987 Standard_Boolean Adaptor3d_CurveOnSurface::IsPeriodic() const
988 {
989   if (myType == GeomAbs_Circle ||
990       myType == GeomAbs_Ellipse)
991     return Standard_True;
992   
993   return myCurve->IsPeriodic();
994 }
995
996 //=======================================================================
997 //function : Period
998 //purpose  : 
999 //=======================================================================
1000
1001 Standard_Real Adaptor3d_CurveOnSurface::Period() const
1002 {
1003   if (myType == GeomAbs_Circle ||
1004       myType == GeomAbs_Ellipse)
1005     return (2.*M_PI);
1006   
1007   return myCurve->Period();
1008 }
1009
1010 //=======================================================================
1011 //function : Value
1012 //purpose  : 
1013 //=======================================================================
1014
1015 gp_Pnt Adaptor3d_CurveOnSurface::Value(const Standard_Real U ) const
1016 {
1017   gp_Pnt P;
1018   gp_Pnt2d Puv;
1019   
1020   if      (myType == GeomAbs_Line  ) P = ElCLib::Value(U,myLin );
1021   else if (myType == GeomAbs_Circle) P = ElCLib::Value(U,myCirc);
1022   else {
1023     myCurve->D0(U,Puv);
1024     mySurface->D0(Puv.X(),Puv.Y(),P);
1025   }
1026
1027   return P;
1028 }
1029
1030 //=======================================================================
1031 //function : D0
1032 //purpose  : 
1033 //=======================================================================
1034
1035 void Adaptor3d_CurveOnSurface::D0(const Standard_Real U ,
1036                                   gp_Pnt& P) const 
1037 {
1038   gp_Pnt2d Puv;
1039   
1040   if      (myType == GeomAbs_Line  ) P = ElCLib::Value(U,myLin );
1041   else if (myType == GeomAbs_Circle) P = ElCLib::Value(U,myCirc);
1042   else {
1043     myCurve->D0(U,Puv);
1044     mySurface->D0(Puv.X(),Puv.Y(),P);
1045   }
1046
1047 }
1048
1049
1050 //=======================================================================
1051 //function : D1
1052 //purpose  : 
1053 //=======================================================================
1054
1055 void Adaptor3d_CurveOnSurface::D1(const Standard_Real U ,
1056                                 gp_Pnt& P,
1057                                 gp_Vec& V) const 
1058 {
1059   gp_Pnt2d Puv;
1060   gp_Vec2d Duv;
1061   gp_Vec D1U,D1V;
1062   
1063   Standard_Real FP = myCurve->FirstParameter();
1064   Standard_Real LP = myCurve->LastParameter();
1065   
1066   Standard_Real Tol= Precision::PConfusion()/10; 
1067   if( ( Abs(U-FP)<Tol)&&(!myFirstSurf.IsNull()) )
1068     {
1069       myCurve->D1(U,Puv,Duv);
1070       myFirstSurf->D1(Puv.X(),Puv.Y(),P,D1U,D1V);
1071       V.SetLinearForm(Duv.X(),D1U,Duv.Y(),D1V);
1072     }
1073   else
1074     if( (Abs(U-LP)<Tol)&&(!myLastSurf.IsNull()) )
1075       {
1076         myCurve->D1(U,Puv,Duv);
1077         myLastSurf->D1(Puv.X(),Puv.Y(),P,D1U,D1V);
1078         V.SetLinearForm(Duv.X(),D1U,Duv.Y(),D1V);
1079       }
1080     else
1081       if      (myType == GeomAbs_Line  ) ElCLib::D1(U,myLin ,P,V);
1082       else if (myType == GeomAbs_Circle) ElCLib::D1(U,myCirc,P,V);
1083       else {
1084         myCurve->D1(U,Puv,Duv);
1085         mySurface->D1(Puv.X(),Puv.Y(),P,D1U,D1V);
1086         V.SetLinearForm(Duv.X(),D1U,Duv.Y(),D1V);
1087       }
1088 }
1089 //=======================================================================
1090 //function : D2
1091 //purpose  : 
1092 //=======================================================================
1093
1094 void Adaptor3d_CurveOnSurface::D2(const Standard_Real U,
1095                                 gp_Pnt& P,
1096                                 gp_Vec& V1,
1097                                 gp_Vec& V2) const
1098
1099   gp_Pnt2d UV;
1100   gp_Vec2d DW,D2W; 
1101   gp_Vec D1U,D1V,D2U,D2V,D2UV;
1102   
1103   Standard_Real FP = myCurve->FirstParameter();
1104   Standard_Real LP = myCurve->LastParameter();
1105   
1106   Standard_Real Tol= Precision::PConfusion()/10; 
1107   if( (Abs(U-FP)<Tol)&&(!myFirstSurf.IsNull()) )
1108     {
1109       myCurve->D2(U,UV,DW,D2W);
1110       myFirstSurf->D2(UV.X(),UV.Y(),P,D1U,D1V,D2U,D2V,D2UV);
1111       
1112       V1.SetLinearForm(DW.X(),D1U,DW.Y(),D1V);
1113       V2.SetLinearForm(D2W.X(), D1U, D2W.Y(), D1V, 2.*DW.X()*DW.Y(),D2UV);
1114       V2.SetLinearForm(DW.X()*DW.X(), D2U, DW.Y()*DW.Y(), D2V, V2);  
1115     }
1116   else  
1117     if( (Abs(U-LP)<Tol)&&(!myLastSurf.IsNull()) )
1118       {
1119         myCurve->D2(U,UV,DW,D2W);
1120         myLastSurf->D2(UV.X(),UV.Y(),P,D1U,D1V,D2U,D2V,D2UV);
1121         
1122         V1.SetLinearForm(DW.X(),D1U,DW.Y(),D1V);
1123         V2.SetLinearForm(D2W.X(), D1U, D2W.Y(), D1V, 2.*DW.X()*DW.Y(),D2UV);
1124         V2.SetLinearForm(DW.X()*DW.X(), D2U, DW.Y()*DW.Y(), D2V, V2);  
1125       }
1126     else
1127       if (myType == GeomAbs_Line  ) {
1128         ElCLib::D1(U,myLin,P,V1);
1129           V2.SetCoord(0.,0.,0.);
1130         }
1131       else if (myType == GeomAbs_Circle) ElCLib::D2(U,myCirc,P,V1,V2);
1132       else {
1133         myCurve->D2(U,UV,DW,D2W);
1134         mySurface->D2(UV.X(),UV.Y(),P,D1U,D1V,D2U,D2V,D2UV);
1135         
1136         V1.SetLinearForm(DW.X(),D1U,DW.Y(),D1V);
1137         V2.SetLinearForm(D2W.X(), D1U, D2W.Y(), D1V, 2.*DW.X()*DW.Y(),D2UV);
1138         V2.SetLinearForm(DW.X()*DW.X(), D2U, DW.Y()*DW.Y(), D2V, V2);  
1139       }
1140 }
1141
1142 //=======================================================================
1143 //function : D3
1144 //purpose  : 
1145 //=======================================================================
1146
1147 void Adaptor3d_CurveOnSurface::D3
1148   (const Standard_Real U,
1149    gp_Pnt& P,
1150    gp_Vec& V1,
1151    gp_Vec& V2,
1152    gp_Vec& V3) const
1153
1154   
1155   Standard_Real Tol= Precision::PConfusion()/10; 
1156   gp_Pnt2d UV;
1157   gp_Vec2d DW,D2W,D3W;
1158   gp_Vec D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV;
1159   
1160   Standard_Real FP = myCurve->FirstParameter();
1161   Standard_Real LP = myCurve->LastParameter();
1162   
1163   if( (Abs(U-FP)<Tol)&&(!myFirstSurf.IsNull()) )
1164     { myCurve->D3(U,UV,DW,D2W,D3W);
1165       myFirstSurf->D3(UV.X(),UV.Y(),P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
1166       V1.SetLinearForm(DW.X(),D1U,DW.Y(),D1V);
1167       V2.SetLinearForm(D2W.X(), D1U, D2W.Y(), D1V, 2.*DW.X()*DW.Y(),D2UV);
1168       V2.SetLinearForm(DW.X()*DW.X(), D2U, DW.Y()*DW.Y(), D2V, V2); 
1169       V3=SetLinearForm( DW, D2W, D3W, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
1170     }else
1171       
1172       if( (Abs(U-LP)<Tol)&&(!myLastSurf.IsNull()) )
1173         { myCurve->D3(U,UV,DW,D2W,D3W);
1174           myLastSurf->D3(UV.X(),UV.Y(),P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
1175           V1.SetLinearForm(DW.X(),D1U,DW.Y(),D1V);
1176           
1177           V2.SetLinearForm(D2W.X(), D1U, D2W.Y(), D1V, 2.*DW.X()*DW.Y(),D2UV);
1178           V2.SetLinearForm(DW.X()*DW.X(), D2U, DW.Y()*DW.Y(), D2V, V2);  
1179           V3=SetLinearForm( DW, D2W, D3W, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);  
1180         }
1181       else
1182         if (myType == GeomAbs_Line  ) {
1183           ElCLib::D1(U,myLin,P,V1);
1184             V2.SetCoord(0.,0.,0.);
1185             V3.SetCoord(0.,0.,0.);
1186           }
1187         else if (myType == GeomAbs_Circle) ElCLib::D3(U,myCirc,P,V1,V2,V3);
1188         else {
1189           myCurve->D3(U,UV,DW,D2W,D3W);
1190           mySurface->D3(UV.X(),UV.Y(),P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
1191           V1.SetLinearForm(DW.X(),D1U,DW.Y(),D1V);
1192           
1193           V2.SetLinearForm(D2W.X(), D1U, D2W.Y(), D1V, 2.*DW.X()*DW.Y(),D2UV);
1194           V2.SetLinearForm(DW.X()*DW.X(), D2U, DW.Y()*DW.Y(), D2V, V2);  
1195           V3=SetLinearForm( DW, D2W, D3W, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);  
1196         }
1197 }
1198
1199
1200 //=======================================================================
1201 //function : DN
1202 //purpose  : 
1203 //=======================================================================
1204
1205 gp_Vec Adaptor3d_CurveOnSurface::DN
1206   (const Standard_Real U, 
1207    const Standard_Integer N) const 
1208 {
1209   gp_Pnt P;
1210   gp_Vec V1, V2, V;
1211   switch (N) {
1212   case 1:
1213     D1(U,P,V);
1214     break ;
1215   case 2: 
1216     D2(U,P,V1,V);
1217     break ;
1218   case 3: 
1219     D3(U,P,V1,V2,V);
1220     break ;
1221   default:
1222     throw Standard_NotImplemented("Adaptor3d_CurveOnSurface:DN");
1223     break;
1224   }
1225   return V;
1226 }
1227
1228
1229 //=======================================================================
1230 //function : Resolution
1231 //purpose  : 
1232 //=======================================================================
1233
1234 Standard_Real Adaptor3d_CurveOnSurface::Resolution
1235   (const Standard_Real R3d) const
1236 {
1237   Standard_Real ru,rv;
1238   ru = mySurface->UResolution(R3d);
1239   rv = mySurface->VResolution(R3d);
1240   return myCurve->Resolution(Min(ru,rv)); 
1241 }
1242
1243
1244 //=======================================================================
1245 //function : GetType
1246 //purpose  : 
1247 //=======================================================================
1248
1249 GeomAbs_CurveType Adaptor3d_CurveOnSurface::GetType() const 
1250 {
1251   return myType;
1252
1253
1254
1255 //=======================================================================
1256 //function : Line
1257 //purpose  : 
1258 //=======================================================================
1259
1260 gp_Lin Adaptor3d_CurveOnSurface::Line() const
1261 {
1262   Standard_NoSuchObject_Raise_if(myType != GeomAbs_Line, "Adaptor3d_CurveOnSurface::Line(): curve is not a line")
1263   return myLin;
1264 }
1265
1266 //=======================================================================
1267 //function : Circle
1268 //purpose  : 
1269 //=======================================================================
1270
1271 gp_Circ Adaptor3d_CurveOnSurface::Circle() const
1272 {
1273   Standard_NoSuchObject_Raise_if(myType != GeomAbs_Circle, "Adaptor3d_CurveOnSurface::Line(): curve is not a circle")
1274   return myCirc;
1275 }
1276
1277 //=======================================================================
1278 //function : Ellipse
1279 //purpose  : 
1280 //=======================================================================
1281
1282 gp_Elips Adaptor3d_CurveOnSurface::Ellipse() const
1283 {
1284   return to3d(mySurface->Plane(),myCurve->Ellipse());
1285 }
1286
1287 //=======================================================================
1288 //function : Hyperbola
1289 //purpose  : 
1290 //=======================================================================
1291
1292 gp_Hypr Adaptor3d_CurveOnSurface::Hyperbola() const
1293 {
1294   return to3d(mySurface->Plane(),myCurve->Hyperbola());
1295 }
1296
1297 //=======================================================================
1298 //function : Parabola
1299 //purpose  : 
1300 //=======================================================================
1301
1302 gp_Parab Adaptor3d_CurveOnSurface::Parabola() const
1303 {
1304   return to3d(mySurface->Plane(),myCurve->Parabola());
1305 }
1306
1307 Standard_Integer  Adaptor3d_CurveOnSurface::Degree() const
1308 {
1309   
1310   // on a parametric surface should multiply
1311   // return TheCurve2dTool::Degree(myCurve);
1312
1313   return myCurve->Degree();
1314 }
1315
1316 //=======================================================================
1317 //function : IsRational
1318 //purpose  : 
1319 //=======================================================================
1320
1321 Standard_Boolean Adaptor3d_CurveOnSurface::IsRational() const
1322 {
1323   return ( myCurve->IsRational() ||
1324           mySurface->IsURational() ||
1325           mySurface->IsVRational()   );
1326 }
1327
1328 //=======================================================================
1329 //function : NbPoles
1330 //purpose  : 
1331 //=======================================================================
1332
1333 Standard_Integer  Adaptor3d_CurveOnSurface::NbPoles() const
1334 {
1335   // on a parametric surface should multiply
1336   return myCurve->NbPoles();
1337 }
1338
1339 //=======================================================================
1340 //function : NbKnots
1341 //purpose  : 
1342 //=======================================================================
1343
1344 Standard_Integer Adaptor3d_CurveOnSurface::NbKnots() const {
1345   if (mySurface->GetType()==GeomAbs_Plane)
1346     return myCurve->NbKnots();
1347   else {
1348     throw Standard_NoSuchObject();
1349   }
1350 }
1351
1352 //=======================================================================
1353 //function : Bezier
1354 //purpose  : 
1355 //=======================================================================
1356
1357 Handle(Geom_BezierCurve) Adaptor3d_CurveOnSurface::Bezier() const  
1358 {
1359   Standard_NoSuchObject_Raise_if
1360     ( mySurface->GetType() != GeomAbs_Plane,
1361      "Adaptor3d_CurveOnSurface : Bezier");
1362
1363   Handle(Geom2d_BezierCurve) Bez2d = myCurve->Bezier();
1364   Standard_Integer NbPoles = Bez2d->NbPoles();
1365
1366   const gp_Pln& Plane = mySurface->Plane();
1367
1368   TColgp_Array1OfPnt Poles(1,NbPoles);
1369   for ( Standard_Integer i=1; i<= NbPoles; i++) {
1370     Poles(i) = to3d( Plane, Bez2d->Pole(i));
1371   }
1372   Handle(Geom_BezierCurve) Bez;
1373
1374   if (Bez2d->IsRational()) {
1375     TColStd_Array1OfReal Weights(1,NbPoles);
1376     Bez2d->Weights(Weights);
1377     Bez = new Geom_BezierCurve(Poles,Weights);
1378   }
1379   else {
1380     Bez = new Geom_BezierCurve(Poles);
1381   }
1382   return Bez;
1383 }
1384
1385 //=======================================================================
1386 //function : BSpline
1387 //purpose  : 
1388 //=======================================================================
1389
1390 Handle(Geom_BSplineCurve) Adaptor3d_CurveOnSurface::BSpline() const  
1391 {
1392   Standard_NoSuchObject_Raise_if
1393     ( mySurface->GetType() != GeomAbs_Plane,
1394      "Adaptor3d_CurveOnSurface : BSpline");
1395
1396   Handle(Geom2d_BSplineCurve) Bsp2d = myCurve->BSpline();
1397   Standard_Integer NbPoles = Bsp2d->NbPoles();
1398
1399   const gp_Pln& Plane = mySurface->Plane();
1400
1401   TColgp_Array1OfPnt Poles(1,NbPoles);
1402   for ( Standard_Integer i=1; i<= NbPoles; i++) {
1403     Poles(i) = to3d( Plane, Bsp2d->Pole(i));
1404   }
1405
1406   TColStd_Array1OfReal    Knots(1,Bsp2d->NbKnots());
1407   TColStd_Array1OfInteger Mults(1,Bsp2d->NbKnots());
1408   Bsp2d->Knots(Knots);
1409   Bsp2d->Multiplicities(Mults);
1410
1411   Handle(Geom_BSplineCurve) Bsp;
1412
1413   if (Bsp2d->IsRational()) {
1414     TColStd_Array1OfReal Weights(1,NbPoles);
1415     Bsp2d->Weights(Weights);
1416     Bsp = new Geom_BSplineCurve(Poles,Weights,Knots,Mults,
1417                                 Bsp2d->Degree(),
1418                                 Bsp2d->IsPeriodic());
1419   }
1420   else {
1421     Bsp = new Geom_BSplineCurve(Poles,Knots,Mults,
1422                                 Bsp2d->Degree(),
1423                                 Bsp2d->IsPeriodic());
1424   }
1425   return Bsp;
1426 }
1427
1428 //=======================================================================
1429 //function : GetCurve
1430 //purpose  : 
1431 //=======================================================================
1432
1433 const Handle(Adaptor2d_Curve2d)& Adaptor3d_CurveOnSurface::GetCurve() const
1434 {
1435   return myCurve;
1436 }
1437
1438 //=======================================================================
1439 //function : GetSurface
1440 //purpose  : 
1441 //=======================================================================
1442
1443 const Handle(Adaptor3d_Surface)& Adaptor3d_CurveOnSurface::GetSurface() const 
1444 {
1445   return mySurface;
1446 }
1447
1448 //=======================================================================
1449 //function : ChangeCurve
1450 //purpose  : 
1451 //=======================================================================
1452
1453 Handle(Adaptor2d_Curve2d)& Adaptor3d_CurveOnSurface::ChangeCurve() 
1454 {
1455   return myCurve;
1456 }
1457
1458 //=======================================================================
1459 //function : ChangeSurface
1460 //purpose  : 
1461 //=======================================================================
1462
1463 Handle(Adaptor3d_Surface)& Adaptor3d_CurveOnSurface::ChangeSurface() {
1464   return mySurface;
1465 }
1466
1467 //=======================================================================
1468 //function : EvalKPart
1469 //purpose  : 
1470 //=======================================================================
1471
1472 void Adaptor3d_CurveOnSurface::EvalKPart()
1473 {
1474   myType = GeomAbs_OtherCurve;
1475
1476   GeomAbs_SurfaceType STy = mySurface->GetType();
1477   GeomAbs_CurveType   CTy = myCurve->GetType();
1478   if (STy == GeomAbs_Plane) {
1479     myType =  CTy;
1480     if (myType == GeomAbs_Circle) 
1481       myCirc = to3d(mySurface->Plane(),myCurve->Circle());
1482     else if (myType == GeomAbs_Line) {
1483       gp_Pnt P;
1484       gp_Vec V;
1485       gp_Pnt2d Puv;
1486       gp_Vec2d Duv;
1487       myCurve->D1(0.,Puv,Duv);
1488       gp_Vec D1U,D1V;
1489       mySurface->D1(Puv.X(),Puv.Y(),P,D1U,D1V);
1490       V.SetLinearForm(Duv.X(),D1U,Duv.Y(),D1V); 
1491       myLin = gp_Lin(P,V);
1492     }
1493   }
1494   else {
1495     if ( CTy == GeomAbs_Line) {
1496       gp_Dir2d D = myCurve->Line().Direction();
1497       if ( D.IsParallel(gp::DX2d(),Precision::Angular())) { // Iso V.
1498         if ( STy == GeomAbs_Sphere) {
1499           gp_Pnt2d  P    = myCurve->Line().Location();
1500           if ( Abs( Abs(P.Y()) -M_PI/2. ) >= Precision::PConfusion()) {
1501             myType = GeomAbs_Circle;
1502             gp_Sphere Sph  =  mySurface->Sphere();
1503             gp_Ax3    Axis = Sph.Position();
1504             myCirc   = ElSLib::SphereVIso(Axis,
1505                                           Sph.Radius(),
1506                                           P.Y());
1507             gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
1508             gp_Ax1 AxeRev(Axis.Location(), DRev);
1509             myCirc.Rotate(AxeRev, P.X());
1510             if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) {
1511               gp_Ax2 Ax = myCirc.Position();
1512               Ax.SetDirection(Ax.Direction().Reversed());
1513               myCirc.SetPosition(Ax);
1514             }
1515           }
1516         }
1517         else if ( STy == GeomAbs_Cylinder) {
1518           myType = GeomAbs_Circle;
1519           gp_Cylinder Cyl  = mySurface->Cylinder();
1520           gp_Pnt2d    P    = myCurve->Line().Location();
1521           gp_Ax3      Axis = Cyl.Position();
1522           myCirc           = ElSLib::CylinderVIso(Axis,
1523                                                   Cyl.Radius(),
1524                                                   P.Y());
1525           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
1526           gp_Ax1 AxeRev(Axis.Location(), DRev);
1527           myCirc.Rotate(AxeRev, P.X());
1528           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) {
1529             gp_Ax2 Ax = myCirc.Position();
1530             Ax.SetDirection(Ax.Direction().Reversed());
1531             myCirc.SetPosition(Ax);
1532           }
1533         }
1534         else if ( STy == GeomAbs_Cone) {
1535           myType = GeomAbs_Circle;
1536           gp_Cone  Cone = mySurface->Cone();
1537           gp_Pnt2d P    = myCurve->Line().Location();
1538           gp_Ax3   Axis = Cone.Position();
1539           myCirc        = ElSLib::ConeVIso(Axis,
1540                                            Cone.RefRadius(),
1541                                            Cone.SemiAngle(),
1542                                            P.Y());
1543           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
1544           gp_Ax1 AxeRev(Axis.Location(), DRev);
1545           myCirc.Rotate(AxeRev, P.X());
1546           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) {
1547             gp_Ax2 Ax = myCirc.Position();
1548             Ax.SetDirection(Ax.Direction().Reversed());
1549             myCirc.SetPosition(Ax);
1550           }
1551         }
1552         else if ( STy == GeomAbs_Torus) {
1553           myType = GeomAbs_Circle;
1554           gp_Torus Tore = mySurface->Torus();
1555           gp_Pnt2d P    = myCurve->Line().Location();
1556           gp_Ax3   Axis = Tore.Position();
1557           myCirc        = ElSLib::TorusVIso(Axis,
1558                                             Tore.MajorRadius(),
1559                                             Tore.MinorRadius(),
1560                                             P.Y());
1561           gp_Dir DRev = Axis.XDirection().Crossed(Axis.YDirection());
1562           gp_Ax1 AxeRev(Axis.Location(), DRev);
1563           myCirc.Rotate(AxeRev, P.X());
1564           if ( D.IsOpposite(gp::DX2d(),Precision::Angular())) {
1565             gp_Ax2 Ax = myCirc.Position();
1566             Ax.SetDirection(Ax.Direction().Reversed());
1567             myCirc.SetPosition(Ax);
1568           }
1569         }
1570       }
1571       else if ( D.IsParallel(gp::DY2d(),Precision::Angular())) { // Iso U.
1572         if ( STy == GeomAbs_Sphere) {
1573           myType = GeomAbs_Circle;
1574           gp_Sphere Sph  = mySurface->Sphere();
1575           gp_Pnt2d  P    = myCurve->Line().Location();
1576           gp_Ax3    Axis = Sph.Position();
1577           // calcul de l'iso 0.
1578           myCirc         = ElSLib::SphereUIso(Axis, Sph.Radius(),0.);
1579
1580           // mise a sameparameter (rotation du cercle - decalage du Y)
1581           gp_Dir DRev = Axis.XDirection().Crossed(Axis. Direction());
1582           gp_Ax1 AxeRev(Axis.Location(),DRev);
1583           myCirc.Rotate(AxeRev, P.Y());
1584
1585           // transformation en iso U ( = P.X())
1586           DRev = Axis.XDirection().Crossed(Axis.YDirection());
1587           AxeRev = gp_Ax1(Axis.Location(), DRev);
1588           myCirc.Rotate(AxeRev, P.X());
1589           
1590           if ( D.IsOpposite(gp::DY2d(),Precision::Angular())) {
1591             gp_Ax2 Ax = myCirc.Position();
1592             Ax.SetDirection(Ax.Direction().Reversed());
1593             myCirc.SetPosition(Ax);
1594           }
1595         }
1596         else if ( STy == GeomAbs_Cylinder) {
1597           myType = GeomAbs_Line;
1598           gp_Cylinder Cyl = mySurface->Cylinder();
1599           gp_Pnt2d    P   = myCurve->Line().Location();
1600           myLin           = ElSLib::CylinderUIso(Cyl.Position(),
1601                                                  Cyl.Radius(),
1602                                                  P.X());
1603           gp_Vec Tr(myLin.Direction());
1604           Tr.Multiply(P.Y());
1605           myLin.Translate(Tr);
1606           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
1607             myLin.Reverse();
1608         }
1609         else if ( STy == GeomAbs_Cone) {
1610           myType = GeomAbs_Line;
1611           gp_Cone  Cone = mySurface->Cone();
1612           gp_Pnt2d P    = myCurve->Line().Location();
1613           myLin         = ElSLib::ConeUIso(Cone.Position(),
1614                                            Cone.RefRadius(),
1615                                            Cone.SemiAngle(),
1616                                            P.X());
1617           gp_Vec Tr(myLin.Direction());
1618           Tr.Multiply(P.Y());
1619           myLin.Translate(Tr);    
1620           if ( D.IsOpposite(gp::DY2d(),Precision::Angular()))
1621             myLin.Reverse();
1622         }
1623         else if ( STy == GeomAbs_Torus) {
1624           myType = GeomAbs_Circle;
1625           gp_Torus Tore = mySurface->Torus();
1626           gp_Pnt2d P    = myCurve->Line().Location();
1627           gp_Ax3   Axis = Tore.Position();
1628           myCirc        = ElSLib::TorusUIso(Axis,
1629                                             Tore.MajorRadius(),
1630                                             Tore.MinorRadius(),
1631                                             P.X());
1632           myCirc.Rotate(myCirc.Axis(),P.Y());
1633           
1634           if ( D.IsOpposite(gp::DY2d(),Precision::Angular())) {
1635             gp_Ax2 Ax = myCirc.Position();
1636             Ax.SetDirection(Ax.Direction().Reversed());
1637             myCirc.SetPosition(Ax);
1638           }
1639         }
1640       }
1641     }
1642   }
1643 }
1644 //=======================================================================
1645 //function :EvalFirstLastSurf 
1646 //purpose  : 
1647 //=======================================================================
1648
1649 void Adaptor3d_CurveOnSurface::EvalFirstLastSurf()
1650
1651   Standard_Real FirstPar,LastPar;
1652   gp_Pnt2d UV, LeftBot, RightTop;
1653   gp_Vec2d DUV;
1654   Standard_Real Tol= Precision::PConfusion()/10;
1655   Standard_Boolean Ok = Standard_True;
1656   
1657   
1658   FirstPar=myCurve->FirstParameter();
1659   myCurve->D1(FirstPar,UV,DUV);
1660
1661   if(DUV.Magnitude() <= Tol) Ok = Standard_False;
1662
1663   if(Ok) {
1664
1665     switch(mySurface->GetType()) {
1666     case GeomAbs_BSplineSurface :
1667       LocatePart(UV,DUV,mySurface,LeftBot,RightTop);
1668       break;
1669     case GeomAbs_SurfaceOfRevolution :
1670     case  GeomAbs_SurfaceOfExtrusion :  
1671       Ok = LocatePart_RevExt(UV,DUV,mySurface,LeftBot,RightTop);
1672       break;
1673     case GeomAbs_OffsetSurface :
1674       Ok = LocatePart_Offset(UV,DUV,mySurface,LeftBot,RightTop);
1675       break;
1676       default :
1677         throw Standard_NotImplemented("Adaptor3d_CurveOnSurface::EvalFirstLastSurf");
1678       break;
1679     }
1680   }
1681
1682   if (Ok) {
1683
1684     CompareBounds(LeftBot,RightTop); //SVV
1685     
1686     myFirstSurf = mySurface->UTrim(LeftBot.X(),RightTop.X(),Tol);
1687     myFirstSurf = myFirstSurf->VTrim(LeftBot.Y(),RightTop.Y(),Tol);
1688
1689   }
1690   else {
1691     myFirstSurf = mySurface;
1692   }
1693   
1694   LastPar=myCurve->LastParameter();
1695   Ok = Standard_True;
1696   myCurve->D1(LastPar,UV,DUV);
1697   DUV.Reverse(); //We want the other part
1698
1699   if(DUV.Magnitude() <= Tol) Ok = Standard_False;
1700
1701   if(Ok) {
1702
1703     switch(mySurface->GetType()) {
1704     case GeomAbs_BSplineSurface :
1705       LocatePart(UV,DUV,mySurface,LeftBot,RightTop);
1706       break;
1707     case GeomAbs_SurfaceOfRevolution :
1708     case  GeomAbs_SurfaceOfExtrusion :  
1709       Ok = LocatePart_RevExt(UV,DUV,mySurface,LeftBot,RightTop);
1710       break;
1711     case GeomAbs_OffsetSurface :
1712       Ok = LocatePart_Offset(UV,DUV,mySurface,LeftBot,RightTop);
1713       break;
1714       default :
1715         throw Standard_NotImplemented("Adaptor3d_CurveOnSurface::EvalFirstLastSurf");
1716       break;
1717     }
1718   }
1719
1720   if (Ok) {
1721
1722     CompareBounds(LeftBot, RightTop); //SVV
1723
1724     myLastSurf = mySurface->UTrim(LeftBot.X(),RightTop.X(),Tol);
1725     myLastSurf = myLastSurf->VTrim(LeftBot.Y(),RightTop.Y(),Tol);
1726
1727   }
1728   else {
1729     myLastSurf = mySurface;
1730   }
1731 }
1732
1733 //=======================================================================
1734 //function :LocatePart_RevExt
1735 //purpose  : processes Knots 
1736 //=======================================================================
1737
1738 Standard_Boolean Adaptor3d_CurveOnSurface::LocatePart_RevExt(const gp_Pnt2d& UV, 
1739                                                            const gp_Vec2d& DUV,
1740                                                            const Handle(Adaptor3d_Surface)& S,
1741                                                            gp_Pnt2d& LeftBot, 
1742                                                            gp_Pnt2d& RightTop) const
1743
1744   Handle(Adaptor3d_Curve) AHC = S->BasisCurve();
1745
1746   if (AHC->GetType() == GeomAbs_BSplineCurve) {
1747     Handle( Geom_BSplineCurve) BSplC;
1748     BSplC = AHC->BSpline();
1749  
1750     if((S->GetType())==GeomAbs_SurfaceOfExtrusion) { 
1751       Locate1Coord(1,UV,DUV,BSplC,LeftBot,RightTop);
1752       Locate2Coord(2,UV,DUV,S->FirstVParameter(),S->LastVParameter(),LeftBot,RightTop); 
1753     }
1754     else if((S->GetType())==GeomAbs_SurfaceOfRevolution)  { 
1755       Locate1Coord(2,UV,DUV,BSplC,LeftBot,RightTop);
1756       Locate2Coord(1,UV,DUV,S->FirstUParameter(),S->LastUParameter(),LeftBot,RightTop);
1757     } 
1758
1759     Standard_Real u1,u2,v1,v2;
1760     ReverseParam(LeftBot.X(),RightTop.X(),u1,u2);
1761     LeftBot.SetX(u1);
1762     RightTop.SetX(u2);
1763     ReverseParam(LeftBot.Y(),RightTop.Y(),v1,v2);
1764     LeftBot.SetY(v1);
1765     RightTop.SetY(v2);
1766     return Standard_True;
1767   }
1768   return Standard_False;
1769 }
1770
1771 //=======================================================================
1772 //function :LocatePart_OffsetSurface
1773 //purpose  : 
1774 //=======================================================================
1775
1776 Standard_Boolean Adaptor3d_CurveOnSurface::
1777    LocatePart_Offset(const gp_Pnt2d& UV, const gp_Vec2d& DUV,
1778                      const Handle(Adaptor3d_Surface)& S,
1779                      gp_Pnt2d& LeftBot, gp_Pnt2d& RightTop) const
1780 {
1781   Standard_Boolean Ok = Standard_True;
1782   Handle( Adaptor3d_Surface) AHS;
1783   Handle( Geom_BSplineSurface) BSplS;
1784   AHS = S->BasisSurface();
1785   GeomAbs_SurfaceType  BasisSType = AHS->GetType();
1786   switch(BasisSType) {
1787   case GeomAbs_SurfaceOfRevolution:
1788   case GeomAbs_SurfaceOfExtrusion :
1789     Ok = LocatePart_RevExt(UV,DUV,AHS,LeftBot,RightTop);
1790     break;
1791       
1792   case GeomAbs_BSplineSurface:
1793     LocatePart(UV,DUV,AHS,LeftBot,RightTop);
1794     break;
1795
1796     default : 
1797       Ok=Standard_False;
1798   }
1799   return Ok;
1800 }
1801
1802 //=======================================================================
1803 //function :LocatePart
1804 //purpose  : for BSplineSurface
1805 //=======================================================================
1806
1807 void Adaptor3d_CurveOnSurface::LocatePart(const gp_Pnt2d& UV, const gp_Vec2d& DUV,
1808                                         const Handle(Adaptor3d_Surface)& S,
1809                                         gp_Pnt2d& LeftBot, gp_Pnt2d& RightTop) const
1810 {
1811   Handle( Geom_BSplineSurface) BSplS;
1812   BSplS = S->BSpline();
1813   Standard_Boolean  DUIsNull=Standard_False,
1814   DVIsNull=Standard_False;
1815       
1816   Locate1Coord(1,UV,DUV,BSplS,DUIsNull,LeftBot,RightTop);
1817   Locate1Coord(2,UV,DUV,BSplS,DVIsNull,LeftBot,RightTop); 
1818   
1819   if((DUIsNull==Standard_True)&&(DVIsNull==Standard_False)) {
1820     TColStd_Array1OfReal ArrU(1,BSplS->NbUKnots());
1821     BSplS->UKnots(ArrU);
1822     Locate2Coord(1,UV,DUV,BSplS,ArrU,LeftBot,RightTop); 
1823   }
1824   else if((DVIsNull==Standard_True)&&(DUIsNull==Standard_False)) {
1825     TColStd_Array1OfReal ArrV(1,BSplS->NbVKnots());
1826     BSplS->VKnots(ArrV);
1827     Locate2Coord(2,UV,DUV,BSplS,ArrV,LeftBot,RightTop);
1828     }
1829 }
1830
1831
1832