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