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