e6092da8837a36e71d7b9da73a16279052b730de
[occt.git] / src / BndLib / BndLib_Add2dCurve.cxx
1 // Copyright (c) 1996-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Adaptor2d_Curve2d.hxx>
17 #include <Bnd_Box2d.hxx>
18 #include <BndLib_Add2dCurve.hxx>
19 #include <Geom2d_BezierCurve.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <Geom2d_Circle.hxx>
22 #include <Geom2d_Conic.hxx>
23 #include <Geom2d_Curve.hxx>
24 #include <Geom2d_Ellipse.hxx>
25 #include <Geom2d_Geometry.hxx>
26 #include <Geom2d_Hyperbola.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom2d_OffsetCurve.hxx>
29 #include <Geom2d_Parabola.hxx>
30 #include <Geom2d_TrimmedCurve.hxx>
31 #include <Geom2dAdaptor_Curve.hxx>
32 #include <gp.hxx>
33 #include <Precision.hxx>
34 #include <Standard_Type.hxx>
35
36 //=======================================================================
37 //function : BndLib_Box2dCurve
38 //purpose  : 
39 //=======================================================================
40 class BndLib_Box2dCurve  {
41  public:
42   BndLib_Box2dCurve();
43
44   virtual ~BndLib_Box2dCurve();
45
46   void SetCurve(const Handle(Geom2d_Curve)& aC);
47
48   const Handle(Geom2d_Curve)& Curve() const;
49
50   void SetRange(const Standard_Real aT1,
51                 const Standard_Real aT2);
52
53   void Range(Standard_Real& aT1,
54              Standard_Real& aT2) const;
55
56   const Bnd_Box2d& Box() const;
57
58   void Perform();
59
60   void Clear();
61
62   Standard_Integer ErrorStatus() const;
63   //
64   //-----------------------------
65  protected:
66   void CheckData();
67   void GetInfoBase();
68   void PerformLineConic();
69   void PerformBezier();
70   void PerformBSpline();
71   void PerformOther();
72   void D0(const Standard_Real, gp_Pnt2d&);
73   //
74   void Compute(const Handle(Geom2d_Conic)&,
75                const GeomAbs_CurveType,
76                const Standard_Real,
77                const Standard_Real,
78                Bnd_Box2d& aBox2D);
79   //
80   static
81     Standard_Integer Compute(const Handle(Geom2d_Conic)&,
82                              const GeomAbs_CurveType,
83                              Standard_Real *);
84   static
85     Standard_Boolean IsTypeBase(const Handle(Geom2d_Curve)& ,
86                               GeomAbs_CurveType& );
87   static
88     Standard_Real AdjustToPeriod(const Standard_Real ,
89                                  const Standard_Real );
90   //
91   void PerformOnePoint();
92   //-----------------------------
93  protected:
94   Handle(Geom2d_Curve) myCurve;
95   Bnd_Box2d myBox;
96   Standard_Integer myErrorStatus;
97   Handle(Geom2d_Curve) myCurveBase;
98   Standard_Real myOffsetBase;
99   Standard_Boolean myOffsetFlag;
100   Standard_Real myT1;
101   Standard_Real myT2;
102   GeomAbs_CurveType myTypeBase;
103 };
104
105
106 //=======================================================================
107 //function : 
108 //purpose  : 
109 //=======================================================================
110 BndLib_Box2dCurve::BndLib_Box2dCurve()
111 {
112   Clear();
113 }
114 //=======================================================================
115 //function : ~
116 //purpose  : 
117 //=======================================================================
118 BndLib_Box2dCurve::~BndLib_Box2dCurve()
119 {
120 }
121 //=======================================================================
122 //function : Clear
123 //purpose  : 
124 //=======================================================================
125 void BndLib_Box2dCurve::Clear()
126 {
127   myBox.SetVoid();
128   //
129   myErrorStatus=-1;
130   myTypeBase=GeomAbs_OtherCurve;
131   myOffsetBase=0.;
132   myOffsetFlag=Standard_False;
133 }
134 //=======================================================================
135 //function : SetCurve
136 //purpose  : 
137 //=======================================================================
138 void BndLib_Box2dCurve::SetCurve(const Handle(Geom2d_Curve)& aC2D)
139 {
140   myCurve=aC2D;
141 }
142 //=======================================================================
143 //function : Curve
144 //purpose  : 
145 //=======================================================================
146 const Handle(Geom2d_Curve)& BndLib_Box2dCurve::Curve()const
147 {
148   return myCurve;
149 }
150 //=======================================================================
151 //function : SetRange
152 //purpose  : 
153 //=======================================================================
154 void BndLib_Box2dCurve::SetRange(const Standard_Real aT1,
155                                  const Standard_Real aT2)
156 {
157   myT1=aT1;
158   myT2=aT2;
159 }
160 //=======================================================================
161 //function : tRange
162 //purpose  : 
163 //=======================================================================
164 void BndLib_Box2dCurve::Range(Standard_Real& aT1,
165                               Standard_Real& aT2) const
166 {
167   aT1=myT1;
168   aT2=myT2;
169 }
170 //=======================================================================
171 //function : ErrorStatus
172 //purpose  : 
173 //=======================================================================
174 Standard_Integer BndLib_Box2dCurve::ErrorStatus()const
175 {
176   return myErrorStatus;
177 }
178 //=======================================================================
179 //function : Box
180 //purpose  : 
181 //=======================================================================
182 const Bnd_Box2d& BndLib_Box2dCurve::Box()const
183 {
184   return myBox;
185 }
186 //=======================================================================
187 //function : CheckData
188 //purpose  : 
189 //=======================================================================
190 void BndLib_Box2dCurve::CheckData()
191 {
192   myErrorStatus=0;
193   //
194   if(myCurve.IsNull()) {
195     myErrorStatus=10;
196     return;
197   }
198   //
199   if(myT1>myT2) {
200     myErrorStatus=12; // invalid range
201     return;
202   }
203 }
204 //=======================================================================
205 //function : Perform
206 //purpose  : 
207 //=======================================================================
208 void BndLib_Box2dCurve::Perform()
209 {
210   Clear();
211   // 
212   myErrorStatus=0;
213   //
214   CheckData();
215   if(myErrorStatus) {
216     return;
217   }
218   //
219   if (myT1==myT2) {
220     PerformOnePoint();
221     return;
222   }
223   //
224   GetInfoBase();
225   if(myErrorStatus) {
226     return;
227   }
228   // 
229   if (myTypeBase==GeomAbs_Line ||
230       myTypeBase==GeomAbs_Circle ||
231       myTypeBase==GeomAbs_Ellipse ||
232       myTypeBase==GeomAbs_Parabola ||
233       myTypeBase==GeomAbs_Hyperbola) { // LineConic
234     PerformLineConic();
235   }
236   else if (myTypeBase==GeomAbs_BezierCurve) { // Bezier
237     PerformBezier();
238   }
239   else if (myTypeBase==GeomAbs_BSplineCurve) { //B-Spline
240     PerformBSpline();
241   }
242   else {
243     myErrorStatus=11; // unknown type base
244   }
245 }
246 //=======================================================================
247 //function : PerformOnePoint
248 //purpose  : 
249 //=======================================================================
250 void BndLib_Box2dCurve::PerformOnePoint()
251 {
252   gp_Pnt2d aP2D;
253   //
254   myCurve->D0(myT1, aP2D);
255   myBox.Add(aP2D);
256 }
257 //=======================================================================
258 //function : PerformBezier
259 //purpose  : 
260 //=======================================================================
261 void BndLib_Box2dCurve::PerformBezier()
262 {
263   if (myOffsetFlag) {
264     PerformOther();
265     return;
266   }
267   //
268   Standard_Integer i, aNbPoles;
269   Standard_Real aT1, aT2, aTb[2];
270   gp_Pnt2d aP2D;
271   Handle(Geom2d_Geometry) aG;
272   Handle(Geom2d_BezierCurve) aCBz, aCBzSeg;
273   //
274   myErrorStatus=0;
275   Bnd_Box2d& aBox2D=myBox;
276   //
277   aCBz=Handle(Geom2d_BezierCurve)::DownCast(myCurveBase);
278   aT1=aCBz->FirstParameter();
279   aT2=aCBz->LastParameter();
280   //
281   aTb[0]=myT1;
282   if (aTb[0]<aT1) {
283     aTb[0]=aT1;
284   }
285   //
286   aTb[1]=myT2;
287   if (aTb[1]>aT2) {
288     aTb[1]=aT2;
289   }
290   //
291   if (!(aT1==aTb[0] && aT2==aTb[1])) {  
292     aG=aCBz->Copy();
293     //
294     aCBzSeg=Handle(Geom2d_BezierCurve)::DownCast(aG);
295     aCBzSeg->Segment(aTb[0], aTb[1]);
296     aCBz=aCBzSeg;
297   }
298   //
299   aNbPoles=aCBz->NbPoles();
300   for (i=1; i<=aNbPoles; ++i) {
301     aP2D=aCBz->Pole(i);
302     aBox2D.Add(aP2D);
303   }
304 }
305 //=======================================================================
306 //function : PerformBSpline
307 //purpose  : 
308 //=======================================================================
309 void BndLib_Box2dCurve::PerformBSpline()
310 {
311   if (myOffsetFlag) {
312     PerformOther();
313     return;
314   }
315   //
316   Standard_Integer i, aNbPoles;
317   Standard_Real  aT1, aT2, aTb[2];
318   gp_Pnt2d aP2D;
319   Handle(Geom2d_Geometry) aG;
320   Handle(Geom2d_BSplineCurve) aCBS, aCBSs;
321   //
322   myErrorStatus=0;
323   Bnd_Box2d& aBox2D=myBox;
324   //
325   aCBS=Handle(Geom2d_BSplineCurve)::DownCast(myCurveBase);
326   aT1=aCBS->FirstParameter();
327   aT2=aCBS->LastParameter();
328   //
329   aTb[0]=myT1;
330   if (aTb[0]<aT1) {
331     aTb[0]=aT1;
332   } 
333   aTb[1]=myT2;
334   if (aTb[1]>aT2) {
335     aTb[1]=aT2;
336   }
337
338   if(aTb[1] < aTb[0])
339   {
340     aTb[0]=aT1;
341     aTb[1]=aT2;
342   }
343
344   //
345   if (!(aT1==aTb[0] && aT2==aTb[1])) {
346     aG=aCBS->Copy();
347     //
348     aCBSs=Handle(Geom2d_BSplineCurve)::DownCast(aG);
349     aCBSs->Segment(aTb[0], aTb[1]);
350     aCBS=aCBSs;
351   }
352   //
353   aNbPoles=aCBS->NbPoles();
354   for (i=1; i<=aNbPoles; ++i) {
355     aP2D=aCBS->Pole(i);
356     aBox2D.Add(aP2D);
357   }
358 }
359 //=======================================================================
360 //function : PerformOther
361 //purpose  : 
362 //=======================================================================
363 void BndLib_Box2dCurve::PerformOther()
364 {
365   Standard_Integer j, aNb;
366   Standard_Real aT, dT;
367   gp_Pnt2d aP2D;
368   //
369   aNb=33;
370   dT=(myT2-myT1)/(aNb-1);
371   //
372   aT=myT1;
373   for (j=0; j<aNb; ++j) {
374     aT=j*dT;
375     myCurve->D0(aT, aP2D);
376     myBox.Add(aP2D);
377   }
378   myCurve->D0(myT2, aP2D);
379   myBox.Add(aP2D);
380 }
381 //=======================================================================
382 //function : D0
383 //purpose  : 
384 //=======================================================================
385 void BndLib_Box2dCurve::D0(const Standard_Real aU,
386                             gp_Pnt2d& aP2D)  
387 {
388   gp_Vec2d aV1;
389   //
390   myCurveBase->D1(aU, aP2D, aV1);
391   //
392   if (myOffsetFlag) {
393     Standard_Integer aIndex, aMaxDegree;
394     Standard_Real aA, aB, aR, aRes;
395     //
396     aMaxDegree=9;
397     aIndex = 2;
398     aRes=gp::Resolution();
399     //
400     while (aV1.Magnitude() <= aRes && aIndex <= aMaxDegree) {
401       aV1=myCurveBase->DN(aU, aIndex);
402       ++aIndex;
403     }
404     //
405     aA=aV1.Y();
406     aB=-aV1.X();
407     aR=sqrt(aA*aA+aB*aB);
408     if(aR<=aRes) {
409       myErrorStatus=13;
410       return;
411     } 
412     //
413     aR=myOffsetBase/aR;
414     aA=aA*aR;
415     aB=aB*aR;
416     aP2D.SetCoord(aP2D.X()+aA, aP2D.Y()+aB);
417   }
418   //
419 }
420 //=======================================================================
421 //function : GetInfoBase
422 //purpose  : 
423 //=======================================================================
424 void BndLib_Box2dCurve::GetInfoBase()
425 {
426   Standard_Boolean bIsTypeBase;
427   Standard_Integer  iTrimmed, iOffset;
428   GeomAbs_CurveType aTypeB;
429   Handle(Geom2d_Curve) aC2DB;
430   Handle(Geom2d_TrimmedCurve) aCT2D;
431   Handle(Geom2d_OffsetCurve) aCF2D;
432   //
433   myErrorStatus=0;
434   myTypeBase=GeomAbs_OtherCurve;
435   myOffsetBase=0;
436   //
437   aC2DB=myCurve;
438   bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
439   if (bIsTypeBase) {
440     myTypeBase=aTypeB;
441     myCurveBase=myCurve;
442     return;
443   }
444   //
445   aC2DB=myCurve;
446   while(!bIsTypeBase) {
447     iTrimmed=0;
448     iOffset=0;
449     aCT2D=Handle(Geom2d_TrimmedCurve)::DownCast(aC2DB);
450     if (!aCT2D.IsNull()) {
451       aC2DB=aCT2D->BasisCurve();
452       ++iTrimmed;
453     }
454     //
455     aCF2D=Handle(Geom2d_OffsetCurve)::DownCast(aC2DB);
456     if (!aCF2D.IsNull()) {
457       Standard_Real aOffset;
458       //
459       aOffset=aCF2D->Offset();
460       myOffsetBase=myOffsetBase+aOffset;
461       myOffsetFlag=Standard_True;
462       //
463       aC2DB=aCF2D->BasisCurve();
464       ++iOffset;
465     }
466     //
467     if (!(iTrimmed || iOffset)) {
468       break;
469     }
470     //
471     bIsTypeBase=IsTypeBase(aC2DB, aTypeB);
472     if (bIsTypeBase) {
473       myTypeBase=aTypeB;
474       myCurveBase=aC2DB;
475       return;
476     }
477   }
478   //
479   myErrorStatus=11; // unknown type base
480 }
481 //=======================================================================
482 //function : IsTypeBase
483 //purpose  : 
484 //=======================================================================
485 Standard_Boolean BndLib_Box2dCurve::IsTypeBase
486   (const Handle(Geom2d_Curve)& aC2D,
487    GeomAbs_CurveType& aTypeB)
488 {
489   Standard_Boolean bRet; 
490   Handle(Standard_Type) aType;
491   //
492   bRet=Standard_True;
493   //
494   aType=aC2D->DynamicType();
495   if (aType==STANDARD_TYPE(Geom2d_Line)) {
496     aTypeB=GeomAbs_Line;
497   }
498   else if (aType==STANDARD_TYPE(Geom2d_Circle)) {
499     aTypeB=GeomAbs_Circle;
500   }
501   else if (aType==STANDARD_TYPE(Geom2d_Ellipse)) {
502     aTypeB=GeomAbs_Ellipse;
503   }
504   else if (aType==STANDARD_TYPE(Geom2d_Parabola)) {
505     aTypeB=GeomAbs_Parabola;
506   }
507   else if (aType==STANDARD_TYPE(Geom2d_Hyperbola)) {
508     aTypeB=GeomAbs_Hyperbola;
509   }
510   else if (aType==STANDARD_TYPE(Geom2d_BezierCurve)) {
511     aTypeB=GeomAbs_BezierCurve;
512   }
513   else if (aType==STANDARD_TYPE(Geom2d_BSplineCurve)) {
514     aTypeB=GeomAbs_BSplineCurve;
515   }
516   else {
517     aTypeB=GeomAbs_OtherCurve;
518     bRet=!bRet;
519   }
520   return bRet;
521 }
522 //=======================================================================
523 //function : PerformLineConic
524 //purpose  : 
525 //=======================================================================
526 void BndLib_Box2dCurve::PerformLineConic()
527 {
528   Standard_Integer i, iInf[2];
529   Standard_Real  aTb[2];
530   gp_Pnt2d aP2D;
531   //
532   myErrorStatus=0;
533   //
534   Bnd_Box2d& aBox2D=myBox;
535   //
536   iInf[0]=0;
537   iInf[1]=0;
538   aTb[0]=myT1;
539   aTb[1]=myT2;
540   //
541   for (i=0; i<2; ++i) {
542     if (Precision::IsNegativeInfinite(aTb[i])) {
543       D0(aTb[i], aP2D);
544       aBox2D.Add(aP2D);
545       ++iInf[0];
546     }
547     else if (Precision::IsPositiveInfinite(aTb[i])) {
548       D0(aTb[i], aP2D);
549       aBox2D.Add(aP2D);
550       ++iInf[1];
551     }
552     else {
553       D0(aTb[i], aP2D);
554       aBox2D.Add(aP2D);
555     }
556   } 
557   //
558   if (myTypeBase==GeomAbs_Line) {
559     return;
560   }
561   //
562   if (iInf[0] && iInf[1]) {
563     return;
564   }
565   //-------------
566   Handle(Geom2d_Conic) aConic2D;
567   //
568   aConic2D=Handle(Geom2d_Conic)::DownCast(myCurveBase);
569   Compute(aConic2D, myTypeBase, aTb[0], aTb[1], aBox2D);
570   
571 }
572 //=======================================================================
573 //function : Compute
574 //purpose  : 
575 //=======================================================================
576 void BndLib_Box2dCurve::Compute(const Handle(Geom2d_Conic)& aConic2D,
577                                 const GeomAbs_CurveType aType,
578                                 const Standard_Real aT1,
579                                 const Standard_Real aT2,
580                                 Bnd_Box2d& aBox2D)
581 {
582   Standard_Integer i, aNbT;
583   Standard_Real pT[10], aT, aTwoPI, aT1x, aT2x, dT, aT1z, aT2z, aEps;
584   gp_Pnt2d aP2D;
585   //
586   aNbT=Compute(aConic2D, aType, pT);
587   //
588   if (aType==GeomAbs_Parabola ||  aType==GeomAbs_Hyperbola) {
589     for (i=0; i<aNbT; ++i) {
590       aT=pT[i];
591       if (aT>aT1 && aT<aT2) {
592         D0(aT, aP2D);
593         aBox2D.Add(aP2D);
594       }
595     }
596     return;
597   }
598   //
599   //aType==GeomAbs_Circle ||  aType==GeomAbs_Ellipse
600   aEps=1.e-14;
601   aTwoPI=2.*M_PI;
602   dT=aT2-aT1;
603   //
604   aT1z=aT1;
605   aT2z=aT2;
606   if (aT1z>=aTwoPI) {
607     aT1z=AdjustToPeriod(aT1z, aTwoPI);
608     aT2z=aT1z+dT;
609   }
610   if (fabs(aT1z)<aEps) {
611     aT1z=0.;
612   }
613   //
614   if (fabs(aT2z-aTwoPI)<aEps) {
615     aT2z=aTwoPI;
616   }
617     //
618   for (i=0; i<aNbT; ++i) {
619     aT=pT[i];
620     if (aT>=aT1z && aT<=aT2z) {
621       D0(aT, aP2D);
622       aBox2D.Add(aP2D);
623     }
624   }
625   //
626   aT1x=AdjustToPeriod(aT1, aTwoPI);
627   aT2x=aT1x+dT;
628   //
629   if (aT1x < aTwoPI && aT2x > aTwoPI) {
630     aT1z=aT1x;
631     aT2z=aTwoPI;
632     for (i=0; i<aNbT; ++i) {
633       aT=pT[i];
634       if (aT>=aT1z && aT<=aT2z) {
635         D0(aT, aP2D);
636         aBox2D.Add(aP2D);
637       }
638     }
639     //
640     aT1z=0.;
641     aT2z=aT2x-aTwoPI;
642     for (i=0; i<aNbT; ++i) {
643       aT=pT[i];
644       if (aT>=aT1z && aT<=aT2z) {
645         D0(aT, aP2D);
646         aBox2D.Add(aP2D);
647       }
648     }
649   }
650 }
651 //=======================================================================
652 //function : Compute
653 //purpose  : 
654 //=======================================================================
655 Standard_Integer BndLib_Box2dCurve::Compute
656   (const Handle(Geom2d_Conic)& aConic2D,
657    const GeomAbs_CurveType aType,
658    Standard_Real *pT)
659 {
660   Standard_Integer iRet, i, j;
661   Standard_Real aCosBt, aSinBt, aCosGm, aSinGm;
662   Standard_Real aLx, aLy;
663   //
664   iRet=0;
665   //
666   const gp_Ax22d& aPos=aConic2D->Position();
667   const gp_XY& aXDir=aPos.XDirection().XY();
668   const gp_XY& aYDir=aPos.YDirection().XY();
669   //
670   aCosBt=aXDir.X();
671   aSinBt=aXDir.Y();
672   aCosGm=aYDir.X();
673   aSinGm=aYDir.Y();
674   //
675   if (aType==GeomAbs_Circle ||  aType==GeomAbs_Ellipse) {
676     Standard_Real aR1 = 0.0, aR2 = 0.0, aTwoPI = M_PI+M_PI;
677     Standard_Real aA11 = 0.0, aA12 = 0.0, aA21 = 0.0, aA22 = 0.0;
678     Standard_Real aBx = 0.0, aBy = 0.0, aB = 0.0, aCosFi = 0.0, aSinFi = 0.0, aFi = 0.0;
679     //
680     if(aType==GeomAbs_Ellipse) {
681       Handle(Geom2d_Ellipse) aEL2D;
682       //
683       aEL2D=Handle(Geom2d_Ellipse)::DownCast(aConic2D);
684       aR1=aEL2D->MajorRadius();
685       aR2=aEL2D->MinorRadius();
686     }
687     else if(aType==GeomAbs_Circle) {
688       Handle(Geom2d_Circle) aCR2D;
689       //
690       aCR2D=Handle(Geom2d_Circle)::DownCast(aConic2D);
691       aR1=aCR2D->Radius();
692       aR2=aR1;
693     }
694     //
695     aA11=-aR1*aCosBt;
696     aA12= aR2*aCosGm;
697     aA21=-aR1*aSinBt;
698     aA22= aR2*aSinGm;
699     //
700     for (i=0; i<2; ++i) {
701       aLx=(!i) ? 0. : 1.;
702       aLy=(!i) ? 1. : 0.;
703       aBx=aLx*aA21-aLy*aA11;
704       aBy=aLx*aA22-aLy*aA12;
705       aB=sqrt(aBx*aBx+aBy*aBy);
706       //
707       aCosFi=aBx/aB;
708       aSinFi=aBy/aB;
709       //
710       aFi=acos(aCosFi);
711       if (aSinFi<0.) {
712         aFi=aTwoPI-aFi;
713       }
714       //
715       j=2*i;
716       pT[j]=aTwoPI-aFi;
717       pT[j]=AdjustToPeriod(pT[j], aTwoPI);
718       //
719       pT[j+1]=M_PI-aFi;
720       pT[j+1]=AdjustToPeriod(pT[j+1], aTwoPI);
721     }
722     iRet=4;
723   }//if (aType==GeomAbs_Ellipse) {
724   //
725   else if (aType==GeomAbs_Parabola) {
726     Standard_Real aFc, aEps;
727     Standard_Real aA1, aA2;
728     Handle(Geom2d_Parabola) aPR2D;
729     //
730     aEps=1.e-12;
731     //
732     aPR2D=Handle(Geom2d_Parabola)::DownCast(aConic2D);
733     aFc=aPR2D->Focal();
734     //
735     j=0;
736     for (i=0; i<2; i++) {
737       aLx=(!i) ? 0. : 1.;
738       aLy=(!i) ? 1. : 0.;
739       //
740       aA2=aLx*aSinBt-aLy*aCosBt;
741       if (fabs(aA2)<aEps) {
742         continue;
743       } 
744       //
745       aA1=aLy*aCosGm-aLx*aSinGm;
746       //
747       pT[j]=2.*aFc*aA1/aA2;
748       ++j;
749     }
750     iRet=j;
751   }// else if (aType==GeomAbs_Parabola) {
752   //
753   else if (aType==GeomAbs_Hyperbola) {
754     Standard_Integer k;
755     Standard_Real aR1, aR2; 
756     Standard_Real aEps, aB1, aB2, aB12, aB22, aZ, aD;
757     Handle(Geom2d_Hyperbola) aHP2D;
758     //
759     aEps=1.e-12;
760     //
761     aHP2D=Handle(Geom2d_Hyperbola)::DownCast(aConic2D);
762     aR1=aHP2D->MajorRadius();
763     aR2=aHP2D->MinorRadius();
764     //
765     j=0;
766     for (i=0; i<2; i++) {
767       aLx=(!i) ? 0. : 1.;
768       aLy=(!i) ? 1. : 0.;
769       //
770       aB1=aR1*(aLx*aSinBt-aLy*aCosBt);
771       aB2=aR2*(aLx*aSinGm-aLy*aCosGm);
772       // 
773       if (fabs(aB1)<aEps) {
774         continue;
775       } 
776       //
777       if (fabs(aB2)<aEps) {
778         pT[j]=0.;
779         ++j;
780       } 
781       else {
782         aB12=aB1*aB1;
783         aB22=aB2*aB2;
784         if (!(aB12>aB22)) {
785           continue;
786         }
787         //
788         aD=sqrt(aB12-aB22);
789         //-------------
790         for (k=-1; k<2; k+=2) {
791           aZ=(aB1+k*aD)/aB2;
792           if (fabs(aZ)<1.) {
793             pT[j]=-log((1.+aZ)/(1.-aZ));
794             ++j;
795           }
796         }
797       }
798     }
799     iRet=j;
800   }// else if (aType==GeomAbs_Hyperbola) {
801   //
802   return iRet;
803 }
804 //=======================================================================
805 //function : AdjustToPeriod
806 //purpose  : 
807 //=======================================================================
808 Standard_Real BndLib_Box2dCurve::AdjustToPeriod(const Standard_Real aT,
809                                                 const Standard_Real aPeriod)
810 {
811   Standard_Integer k;
812   Standard_Real aTRet;
813   //
814   aTRet=aT;
815   if (aT<0.) {
816     k=1+(Standard_Integer)(-aT/aPeriod);
817     aTRet=aT+k*aPeriod;
818   }
819   else if (aT>aPeriod) {
820     k=(Standard_Integer)(aT/aPeriod);
821     aTRet=aT-k*aPeriod;
822   }
823   if (aTRet==aPeriod) {
824     aTRet=0.;
825   }
826   return aTRet;
827 }
828 //
829 // myErrorStatus:
830 //
831 // -1 - object is just initialized
832 // 10 - myCurve is Null
833 // 12 - invalid range myT1 >  myT2l
834 // 11 - unknown type of base curve
835 // 13 - offset curve can not be computed
836 //NMTTest
837
838 //=======================================================================
839 //function : Add
840 //purpose  : 
841 //=======================================================================
842 void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
843                              const Standard_Real aTol,
844                              Bnd_Box2d& aBox2D) 
845 {
846   BndLib_Add2dCurve::Add(aC,
847                           aC.FirstParameter(),
848                           aC.LastParameter (),
849                           aTol,
850                           aBox2D);
851 }
852 //=======================================================================
853 //function : Add
854 //purpose  : 
855 //=======================================================================
856 void BndLib_Add2dCurve::Add(const Adaptor2d_Curve2d& aC,
857                              const Standard_Real aU1,
858                              const Standard_Real aU2,
859                              const Standard_Real aTol,
860                              Bnd_Box2d& aBox2D)
861 {
862   Adaptor2d_Curve2d *pC=(Adaptor2d_Curve2d *)&aC;
863   Geom2dAdaptor_Curve *pA=dynamic_cast<Geom2dAdaptor_Curve*>(pC);
864   if (!pA) {
865     Standard_Real U, DU;
866     Standard_Integer N, j;
867     gp_Pnt2d P;
868     N = 33;
869     U  = aU1;
870     DU = (aU2-aU1)/(N-1);
871     for (j=1; j<N; j++) {
872       aC.D0(U,P);
873       U+=DU;
874       aBox2D.Add(P);
875     }
876     aC.D0(aU2,P);
877     aBox2D.Add(P);
878     aBox2D.Enlarge(aTol);
879     return;
880   }
881   //
882   const Handle(Geom2d_Curve)& aC2D=pA->Curve();
883   //
884   BndLib_Add2dCurve::Add(aC2D, aU1, aU2, aTol, aBox2D);
885 }
886 //=======================================================================
887 //function : Add
888 //purpose  : 
889 //=======================================================================
890 void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
891                              const Standard_Real aTol,
892                              Bnd_Box2d& aBox2D)
893 {
894   Standard_Real aT1, aT2;
895   //
896   aT1=aC2D->FirstParameter();
897   aT2=aC2D->LastParameter();
898   //
899   BndLib_Add2dCurve::Add(aC2D, aT1, aT2, aTol, aBox2D);
900 }
901
902 //=======================================================================
903 //function : Add
904 //purpose  : 
905 //=======================================================================
906 void BndLib_Add2dCurve::Add(const Handle(Geom2d_Curve)& aC2D,
907                              const Standard_Real aT1,
908                              const Standard_Real aT2,
909                              const Standard_Real aTol,
910                              Bnd_Box2d& aBox2D)
911 {
912   BndLib_Box2dCurve aBC;
913   //
914   aBC.SetCurve(aC2D);
915   aBC.SetRange(aT1, aT2);
916   //
917   aBC.Perform();
918   //
919   const Bnd_Box2d& aBoxC=aBC.Box();
920   aBox2D.Add(aBoxC);
921   aBox2D.Enlarge(aTol);
922 }