0030270: Modeling Algorithms - BRepBndLib should provide an option for skipping infin...
[occt.git] / src / BndLib / BndLib.cxx
1 // Copyright (c) 1995-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 <Bnd_Box.hxx>
17 #include <Bnd_Box2d.hxx>
18 #include <BndLib.hxx>
19 #include <ElCLib.hxx>
20 #include <gp_Circ.hxx>
21 #include <gp_Circ2d.hxx>
22 #include <gp_Cone.hxx>
23 #include <gp_Cylinder.hxx>
24 #include <gp_Elips.hxx>
25 #include <gp_Elips2d.hxx>
26 #include <gp_Hypr.hxx>
27 #include <gp_Hypr2d.hxx>
28 #include <gp_Lin.hxx>
29 #include <gp_Lin2d.hxx>
30 #include <gp_Parab.hxx>
31 #include <gp_Parab2d.hxx>
32 #include <gp_Pnt.hxx>
33 #include <gp_Pnt2d.hxx>
34 #include <gp_Sphere.hxx>
35 #include <gp_Torus.hxx>
36 #include <gp_XY.hxx>
37 #include <gp_XYZ.hxx>
38 #include <Precision.hxx>
39 #include <Standard_Failure.hxx>
40 #include <ElSLib.hxx>
41
42 static 
43   Standard_Integer ComputeBox(const gp_Hypr& aHypr, 
44                               const Standard_Real aT1, 
45                               const Standard_Real aT2, 
46                               Bnd_Box& aBox);
47
48
49 namespace
50 {
51   //! Compute method
52   template<class PointType, class BndBoxType>
53   void Compute (const Standard_Real theP1, const Standard_Real theP2,
54                 const Standard_Real theRa ,const Standard_Real theRb,
55                 const PointType& theXd, const PointType& theYd, const PointType& theO,
56                 BndBoxType& theB)
57   {
58     Standard_Real aTeta1;
59     Standard_Real aTeta2;
60     if(theP2 < theP1)
61     { 
62       aTeta1 = theP2;
63       aTeta2 = theP1;
64     }
65     else
66     {
67       aTeta1 = theP1;
68       aTeta2 = theP2;
69     }
70
71     Standard_Real aDelta = Abs(aTeta2-aTeta1); 
72     if(aDelta > 2. * M_PI)
73     {
74       aTeta1 = 0.;
75       aTeta2 = 2. * M_PI;
76     }
77     else
78     {
79       if(aTeta1 < 0.)
80       {
81         do{ aTeta1 += 2.*M_PI; } while (aTeta1 < 0.);
82       }
83       else if (aTeta1 > 2.*M_PI)
84       {
85         do { aTeta1 -= 2.*M_PI; } while (aTeta1 > 2.*M_PI);
86       }
87       aTeta2 = aTeta1 + aDelta;
88     }
89
90     // One places already both ends
91     Standard_Real aCn1, aSn1 ,aCn2, aSn2;
92     aCn1 = Cos(aTeta1); aSn1 = Sin(aTeta1);
93     aCn2 = Cos(aTeta2); aSn2 = Sin(aTeta2);
94     theB.Add(PointType( theO.Coord() +theRa*aCn1*theXd.Coord() +theRb*aSn1*theYd.Coord()));
95     theB.Add(PointType(theO.Coord() +theRa*aCn2*theXd.Coord() +theRb*aSn2*theYd.Coord()));
96     
97     Standard_Real aRam, aRbm;
98     if (aDelta > M_PI/8.)
99     {
100       // Main radiuses to take into account only 8 points (/cos(Pi/8.))
101       aRam = theRa/0.92387953251128674;
102       aRbm = theRb/0.92387953251128674;
103     }
104     else
105     {
106       // Main radiuses to take into account the arrow
107       Standard_Real aTc = cos(aDelta/2);
108       aRam = theRa/aTc;
109       aRbm = theRb/aTc;
110     }
111     theB.Add(PointType(theO.Coord() + aRam*aCn1*theXd.Coord() + aRbm*aSn1*theYd.Coord()));
112     theB.Add(PointType(theO.Coord() + aRam*aCn2*theXd.Coord() + aRbm*aSn2*theYd.Coord()));
113
114 // cos or sin M_PI/4.
115 #define PI4 0.70710678118654746
116
117 // 8 points of the polygon
118 #define addPoint0 theB.Add(PointType(theO.Coord() +aRam*theXd.Coord()))
119 #define addPoint1 theB.Add(PointType(theO.Coord() +aRam*PI4*theXd.Coord() +aRbm*PI4*theYd.Coord()))
120 #define addPoint2 theB.Add(PointType(theO.Coord() +aRbm*theYd.Coord()))
121 #define addPoint3 theB.Add(PointType(theO.Coord() -aRam*PI4*theXd.Coord() +aRbm*PI4*theYd.Coord()))
122 #define addPoint4 theB.Add(PointType(theO.Coord() -aRam*theXd.Coord() ))
123 #define addPoint5 theB.Add(PointType(theO.Coord() -aRam*PI4*theXd.Coord() -aRbm*PI4*theYd.Coord()))
124 #define addPoint6 theB.Add(PointType(theO.Coord() -aRbm*theYd.Coord()))
125 #define addPoint7 theB.Add(PointType(theO.Coord() +aRam*PI4*theXd.Coord() -aRbm*PI4*theYd.Coord()))
126
127     Standard_Integer aDeb = (Standard_Integer )( aTeta1/(M_PI/4.));
128     Standard_Integer aFin = (Standard_Integer )( aTeta2/(M_PI/4.));
129     aDeb++;
130
131     if (aDeb > aFin) return;
132
133     switch (aDeb)
134     {
135     case 1:
136       {
137         addPoint1;
138         if (aFin <= 1) break;
139       }
140       Standard_FALLTHROUGH
141     case 2:
142       {
143         addPoint2;
144         if (aFin <= 2) break;
145       }
146       Standard_FALLTHROUGH
147     case 3:
148       {
149         addPoint3;
150         if (aFin <= 3) break;
151       }
152       Standard_FALLTHROUGH
153     case 4:
154       {
155         addPoint4;
156         if (aFin <= 4) break;
157       }
158       Standard_FALLTHROUGH
159     case 5:
160       {
161         addPoint5;
162         if (aFin <= 5) break;
163       }
164       Standard_FALLTHROUGH
165     case 6:
166       {
167         addPoint6;
168         if (aFin <= 6) break;
169       }
170       Standard_FALLTHROUGH
171     case 7:
172       {
173         addPoint7;
174         if (aFin <= 7) break;
175       }
176       Standard_FALLTHROUGH
177     case 8:
178       {
179         addPoint0;
180         if (aFin <= 8) break;
181       }
182       Standard_FALLTHROUGH
183     case 9:
184       {
185         addPoint1;
186         if (aFin <= 9) break;
187       }  
188       Standard_FALLTHROUGH
189     case 10:
190       {
191         addPoint2;
192         if (aFin <= 10) break;
193       }
194       Standard_FALLTHROUGH
195     case 11:
196       {
197         addPoint3;
198         if (aFin <= 11) break;
199       }  
200       Standard_FALLTHROUGH
201     case 12:
202       {
203         addPoint4;
204         if (aFin <= 12) break;
205       }  
206       Standard_FALLTHROUGH
207     case 13:
208       {
209         addPoint5;
210         if (aFin <= 13) break;
211       }
212       Standard_FALLTHROUGH
213     case 14:
214       {
215         addPoint6;
216         if (aFin <= 14) break;
217       }
218       Standard_FALLTHROUGH
219     case 15:
220       {
221         addPoint7;
222         if (aFin <= 15) break;
223       }
224     }
225   }
226 } // end namespace
227
228 static void OpenMin(const gp_Dir& V,Bnd_Box& B) {
229   gp_Dir OX(1.,0.,0.);
230   gp_Dir OY(0.,1.,0.);
231   gp_Dir OZ(0.,0.,1.);
232   if (V.IsParallel(OX,Precision::Angular())) 
233     B.OpenXmin();
234   else if (V.IsParallel(OY,Precision::Angular())) 
235     B.OpenYmin();
236   else if (V.IsParallel(OZ,Precision::Angular())) 
237     B.OpenZmin();
238   else {
239     B.OpenXmin();B.OpenYmin();B.OpenZmin();
240   }
241 }
242
243 static void OpenMax(const gp_Dir& V,Bnd_Box& B) {
244   gp_Dir OX(1.,0.,0.);
245   gp_Dir OY(0.,1.,0.);
246   gp_Dir OZ(0.,0.,1.);
247   if (V.IsParallel(OX,Precision::Angular())) 
248     B.OpenXmax();
249   else if (V.IsParallel(OY,Precision::Angular())) 
250     B.OpenYmax();
251   else if (V.IsParallel(OZ,Precision::Angular())) 
252     B.OpenZmax();
253   else {
254     B.OpenXmax();B.OpenYmax();B.OpenZmax();
255   }
256 }
257
258 static void OpenMinMax(const gp_Dir& V,Bnd_Box& B) {
259   gp_Dir OX(1.,0.,0.);
260   gp_Dir OY(0.,1.,0.);
261   gp_Dir OZ(0.,0.,1.);
262   if (V.IsParallel(OX,Precision::Angular())) {
263     B.OpenXmax();B.OpenXmin();
264   }
265   else if (V.IsParallel(OY,Precision::Angular())) {
266     B.OpenYmax();B.OpenYmin();
267   }
268   else if (V.IsParallel(OZ,Precision::Angular())) {
269     B.OpenZmax();B.OpenZmin();
270   }
271   else {
272     B.OpenXmin();B.OpenYmin();B.OpenZmin();
273     B.OpenXmax();B.OpenYmax();B.OpenZmax();
274   }
275 }
276
277 static void OpenMin(const gp_Dir2d& V,Bnd_Box2d& B) {
278   gp_Dir2d OX(1.,0.);
279   gp_Dir2d OY(0.,1.);
280   if (V.IsParallel(OX,Precision::Angular())) 
281     B.OpenXmin();
282   else if (V.IsParallel(OY,Precision::Angular())) 
283     B.OpenYmin();
284   else {
285     B.OpenXmin();B.OpenYmin();
286   }
287 }
288
289 static void OpenMax(const gp_Dir2d& V,Bnd_Box2d& B) {
290   gp_Dir2d OX(1.,0.);
291   gp_Dir2d OY(0.,1.);
292   if (V.IsParallel(OX,Precision::Angular())) 
293     B.OpenXmax();
294   else if (V.IsParallel(OY,Precision::Angular())) 
295     B.OpenYmax();
296   else {
297     B.OpenXmax();B.OpenYmax();
298   }
299 }
300
301 static void OpenMinMax(const gp_Dir2d& V,Bnd_Box2d& B) {
302   gp_Dir2d OX(1.,0.);
303   gp_Dir2d OY(0.,1.);
304   if (V.IsParallel(OX,Precision::Angular())) {
305     B.OpenXmax();B.OpenXmin();
306   }
307   else if (V.IsParallel(OY,Precision::Angular())) {
308     B.OpenYmax();B.OpenYmin();
309   }
310   else {
311     B.OpenXmin();B.OpenYmin();
312     B.OpenXmax();B.OpenYmax();
313   }
314 }
315
316
317 void BndLib::Add( const gp_Lin& L,const Standard_Real P1,
318                  const Standard_Real P2,
319                  const Standard_Real Tol, Bnd_Box& B) {
320
321   if (Precision::IsNegativeInfinite(P1)) {
322     if (Precision::IsNegativeInfinite(P2)) {
323       throw Standard_Failure("BndLib::bad parameter");
324     }
325     else if (Precision::IsPositiveInfinite(P2)) {
326       OpenMinMax(L.Direction(),B);
327       B.Add(ElCLib::Value(0.,L));
328     }
329     else {
330       OpenMin(L.Direction(),B);
331       B.Add(ElCLib::Value(P2,L));
332     }
333   }
334   else if (Precision::IsPositiveInfinite(P1)) {
335     if (Precision::IsNegativeInfinite(P2)) {
336       OpenMinMax(L.Direction(),B);
337       B.Add(ElCLib::Value(0.,L));
338     }
339     else if (Precision::IsPositiveInfinite(P2)) {
340       throw Standard_Failure("BndLib::bad parameter");
341     }
342     else {
343       OpenMax(L.Direction(),B);
344       B.Add(ElCLib::Value(P2,L));
345     }
346   }
347   else  {
348     B.Add(ElCLib::Value(P1,L));
349     if (Precision::IsNegativeInfinite(P2)) {
350       OpenMin(L.Direction(),B);
351     }
352     else if (Precision::IsPositiveInfinite(P2)){
353       OpenMax(L.Direction(),B);
354     }
355     else {
356       B.Add(ElCLib::Value(P2,L));
357     }
358   }
359   B.Enlarge(Tol);
360 }
361
362 void BndLib::Add( const gp_Lin2d& L,const Standard_Real P1,
363                  const Standard_Real P2,
364                  const Standard_Real Tol, Bnd_Box2d& B) {
365
366   if (Precision::IsNegativeInfinite(P1)) {
367     if (Precision::IsNegativeInfinite(P2)) {
368       throw Standard_Failure("BndLib::bad parameter");
369     }
370     else if (Precision::IsPositiveInfinite(P2)) {
371       OpenMinMax(L.Direction(),B);
372       B.Add(ElCLib::Value(0.,L));
373     }
374     else {
375       OpenMin(L.Direction(),B);
376       B.Add(ElCLib::Value(P2,L));
377     }
378   }
379   else if (Precision::IsPositiveInfinite(P1)) {
380     if (Precision::IsNegativeInfinite(P2)) {
381       OpenMinMax(L.Direction(),B);
382       B.Add(ElCLib::Value(0.,L));
383     }
384     else if (Precision::IsPositiveInfinite(P2)) {
385       throw Standard_Failure("BndLib::bad parameter");
386     }
387     else {
388       OpenMax(L.Direction(),B);
389       B.Add(ElCLib::Value(P2,L));
390     }
391   }
392   else  {
393     B.Add(ElCLib::Value(P1,L));
394     if (Precision::IsNegativeInfinite(P2)) {
395       OpenMin(L.Direction(),B);
396     }
397     else if (Precision::IsPositiveInfinite(P2)){
398       OpenMax(L.Direction(),B);
399     }
400     else {
401       B.Add(ElCLib::Value(P2,L));
402     }
403   }
404   B.Enlarge(Tol);
405 }
406
407 void BndLib::Add( const gp_Circ& C, const Standard_Real Tol, Bnd_Box& B) 
408 {
409   Standard_Real U1 = 0., U2 = 2.*M_PI;
410   Add(C, U1, U2, Tol, B);
411 }
412
413 void BndLib::Add(const gp_Circ& C,
414                  const Standard_Real U1,
415                  const Standard_Real U2,
416                  const Standard_Real Tol, 
417                  Bnd_Box& B) 
418 {
419   Standard_Real period = 2.*M_PI - Epsilon(2.*M_PI);
420
421   Standard_Real utrim1 = U1, utrim2 = U2;
422   if(U2 - U1 > period)
423   {
424     utrim1 = 0.;
425     utrim2 = 2.*M_PI;
426   }
427   else
428   {
429     Standard_Real tol = Epsilon(1.);
430     ElCLib::AdjustPeriodic(0., 2.*M_PI,
431                            tol,
432                            utrim1, utrim2);
433   }
434   Standard_Real R = C.Radius();
435   gp_XYZ O  = C.Location().XYZ();
436   gp_XYZ Xd = C.XAxis().Direction().XYZ();
437   gp_XYZ Yd = C.YAxis().Direction().XYZ();
438   const gp_Ax2& pos = C.Position();
439   //
440   Standard_Real tt;
441   Standard_Real xmin, xmax, txmin, txmax;
442   if(Abs(Xd.X()) > gp::Resolution())
443   {
444     txmin = ATan(Yd.X() / Xd.X());
445     txmin = ElCLib::InPeriod(txmin, 0., 2.*M_PI);
446   }
447   else
448   {
449     txmin = M_PI/ 2.;
450   }
451   txmax = txmin <= M_PI? txmin + M_PI : txmin - M_PI;
452   xmin = R * Cos(txmin) * Xd.X() + R * Sin(txmin) * Yd.X() + O.X();
453   xmax = R * Cos(txmax) * Xd.X() + R * Sin(txmax) * Yd.X() + O.X();
454   if(xmin > xmax)
455   {
456     tt = xmin;
457     xmin = xmax;
458     xmax = tt;
459     tt = txmin;
460     txmin = txmax;
461     txmax = tt;
462   }
463   //
464   Standard_Real ymin, ymax, tymin, tymax;
465   if(Abs(Xd.Y()) > gp::Resolution())
466   {
467     tymin = ATan(Yd.Y() / Xd.Y());
468     tymin = ElCLib::InPeriod(tymin, 0., 2.*M_PI);
469   }
470   else
471   {
472     tymin = M_PI/ 2.;
473   }
474   tymax = tymin <= M_PI? tymin + M_PI : tymin - M_PI;
475   ymin = R * Cos(tymin) * Xd.Y() + R * Sin(tymin) * Yd.Y() + O.Y();
476   ymax = R * Cos(tymax) * Xd.Y() + R * Sin(tymax) * Yd.Y() + O.Y();
477   if(ymin > ymax)
478   {
479     tt = ymin;
480     ymin = ymax;
481     ymax = tt;
482     tt = tymin;
483     tymin = tymax;
484     tymax = tt;
485   }
486   //
487   Standard_Real zmin, zmax, tzmin, tzmax;
488   if(Abs(Xd.Z()) > gp::Resolution())
489   {
490     tzmin = ATan(Yd.Z() / Xd.Z());
491     tzmin = ElCLib::InPeriod(tzmin, 0., 2.*M_PI);
492   }
493   else
494   {
495     tzmin = M_PI/ 2.;
496   }
497   tzmax = tzmin <= M_PI? tzmin + M_PI : tzmin - M_PI;
498   zmin = R * Cos(tzmin) * Xd.Z() + R * Sin(tzmin) * Yd.Z() + O.Z();
499   zmax = R * Cos(tzmax) * Xd.Z() + R * Sin(tzmax) * Yd.Z() + O.Z();
500   if(zmin > zmax)
501   {
502     tt = zmin;
503     zmin = zmax;
504     zmax = tt;
505     tt = tzmin;
506     tzmin = tzmax;
507     tzmax = tt;
508   }
509   //
510   if(utrim2 - utrim1 >= period)
511   {
512     B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
513   }
514   else
515   {
516     gp_Pnt P = ElCLib::CircleValue(utrim1, pos, R);
517     B.Add(P);
518     P = ElCLib::CircleValue(utrim2, pos, R);
519     B.Add(P);
520     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
521     B.FinitePart().Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
522     Standard_Real gap = B.GetGap();
523     Xmin += gap;
524     Ymin += gap;
525     Zmin += gap;
526     Xmax -= gap;
527     Ymax -= gap;
528     Zmax -= gap;
529     //
530     txmin = ElCLib::InPeriod(txmin, utrim1, utrim1 + 2. * M_PI);
531     if(txmin >= utrim1 && txmin <= utrim2)
532     {
533       Xmin = Min(xmin, Xmin);
534     }
535     txmax = ElCLib::InPeriod(txmax, utrim1, utrim1 + 2. * M_PI);
536     if(txmax >= utrim1 && txmax <= utrim2)
537     {
538       Xmax = Max(xmax, Xmax);
539    }
540     //
541     tymin = ElCLib::InPeriod(tymin, utrim1, utrim1 + 2. * M_PI);
542     if(tymin >= utrim1 && tymin <= utrim2)
543     {
544       Ymin = Min(ymin, Ymin);
545     }
546     tymax = ElCLib::InPeriod(tymax, utrim1, utrim1 + 2. * M_PI);
547     if(tymax >= utrim1 && tymax <= utrim2)
548     {
549       Ymax = Max(ymax, Ymax);
550     }
551     //
552     tzmin = ElCLib::InPeriod(tzmin, utrim1, utrim1 + 2. * M_PI);
553     if(tzmin >= utrim1 && tzmin <= utrim2)
554     {
555       Zmin = Min(zmin, Zmin);
556     }
557     tzmax = ElCLib::InPeriod(tzmax, utrim1, utrim1 + 2. * M_PI);
558     if(tzmax >= utrim1 && tzmax <= utrim2)
559     {
560       Zmax = Max(zmax, Zmax);
561     }
562     //
563     B.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
564   }
565   //
566   B.Enlarge(Tol);
567 }
568
569 void BndLib::Add( const gp_Circ2d& C,const Standard_Real Tol, Bnd_Box2d& B) {
570
571   Standard_Real R = C.Radius();
572   gp_XY O  = C.Location().XY();
573   gp_XY Xd = C.XAxis().Direction().XY();
574   gp_XY Yd = C.YAxis().Direction().XY();
575   B.Add(gp_Pnt2d(O -R*Xd -R*Yd));
576   B.Add(gp_Pnt2d(O -R*Xd +R*Yd));
577   B.Add(gp_Pnt2d(O +R*Xd -R*Yd));
578   B.Add(gp_Pnt2d(O +R*Xd +R*Yd));
579   B.Enlarge(Tol);
580 }
581
582 void BndLib::Add(const gp_Circ2d& C,const Standard_Real P1,
583    const Standard_Real P2,
584    const Standard_Real Tol, Bnd_Box2d& B) {
585
586        Compute(P1,P2,C.Radius(),C.Radius(),gp_Pnt2d(C.XAxis().Direction().XY()),
587          gp_Pnt2d(C.YAxis().Direction().XY()),C.Location(),B);
588   B.Enlarge(Tol);
589 }
590
591 void BndLib::Add(const gp_Elips& C, const Standard_Real Tol, Bnd_Box& B) 
592 {
593   Standard_Real U1 = 0., U2 = 2.*M_PI;
594   Add(C, U1, U2, Tol, B);
595 }
596
597 void BndLib::Add(const gp_Elips& C,
598                  const Standard_Real U1,
599                  const Standard_Real U2,
600                  const Standard_Real Tol, 
601                  Bnd_Box& B) 
602 {
603   Standard_Real period = 2.*M_PI - Epsilon(2.*M_PI);
604
605   Standard_Real utrim1 = U1, utrim2 = U2;
606   if(U2 - U1 > period)
607   {
608     utrim1 = 0.;
609     utrim2 = 2.*M_PI;
610   }
611   else
612   {
613     Standard_Real tol = Epsilon(1.);
614     ElCLib::AdjustPeriodic(0., 2.*M_PI,
615                            tol,
616                            utrim1, utrim2);
617   }
618   Standard_Real MajR = C.MajorRadius();
619   Standard_Real MinR = C.MinorRadius();
620   gp_XYZ O  = C.Location().XYZ();
621   gp_XYZ Xd = C.XAxis().Direction().XYZ();
622   gp_XYZ Yd = C.YAxis().Direction().XYZ();
623   const gp_Ax2& pos = C.Position();
624   //
625   Standard_Real tt;
626   Standard_Real xmin, xmax, txmin, txmax;
627   if(Abs(Xd.X()) > gp::Resolution())
628   {
629     txmin = ATan((MinR*Yd.X()) / (MajR*Xd.X()));
630     txmin = ElCLib::InPeriod(txmin, 0., 2.*M_PI);
631   }
632   else
633   {
634     txmin = M_PI/ 2.;
635   }
636   txmax = txmin <= M_PI? txmin + M_PI : txmin - M_PI;
637   xmin = MajR * Cos(txmin) * Xd.X() + MinR * Sin(txmin) * Yd.X() + O.X();
638   xmax = MajR * Cos(txmax) * Xd.X() + MinR * Sin(txmax) * Yd.X() + O.X();
639   if(xmin > xmax)
640   {
641     tt = xmin;
642     xmin = xmax;
643     xmax = tt;
644     tt = txmin;
645     txmin = txmax;
646     txmax = tt;
647   }
648   //
649   Standard_Real ymin, ymax, tymin, tymax;
650   if(Abs(Xd.Y()) > gp::Resolution())
651   {
652     tymin = ATan((MinR*Yd.Y()) / (MajR*Xd.Y()));
653     tymin = ElCLib::InPeriod(tymin, 0., 2.*M_PI);
654   }
655   else
656   {
657     tymin = M_PI/ 2.;
658   }
659   tymax = tymin <= M_PI? tymin + M_PI : tymin - M_PI;
660   ymin = MajR * Cos(tymin) * Xd.Y() + MinR * Sin(tymin) * Yd.Y() + O.Y();
661   ymax = MajR * Cos(tymax) * Xd.Y() + MinR * Sin(tymax) * Yd.Y() + O.Y();
662   if(ymin > ymax)
663   {
664     tt = ymin;
665     ymin = ymax;
666     ymax = tt;
667     tt = tymin;
668     tymin = tymax;
669     tymax = tt;
670   }
671   //
672   Standard_Real zmin, zmax, tzmin, tzmax;
673   if(Abs(Xd.Z()) > gp::Resolution())
674   {
675     tzmin = ATan((MinR*Yd.Z()) / (MajR*Xd.Z()));
676     tzmin = ElCLib::InPeriod(tzmin, 0., 2.*M_PI);
677   }
678   else
679   {
680     tzmin = M_PI/ 2.;
681   }
682   tzmax = tzmin <= M_PI? tzmin + M_PI : tzmin - M_PI;
683   zmin = MajR * Cos(tzmin) * Xd.Z() + MinR * Sin(tzmin) * Yd.Z() + O.Z();
684   zmax = MajR * Cos(tzmax) * Xd.Z() + MinR * Sin(tzmax) * Yd.Z() + O.Z();
685   if(zmin > zmax)
686   {
687     tt = zmin;
688     zmin = zmax;
689     zmax = tt;
690     tt = tzmin;
691     tzmin = tzmax;
692     tzmax = tt;
693   }
694   //
695   if(utrim2 - utrim1 >= period)
696   {
697     B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
698   }
699   else
700   {
701     gp_Pnt P = ElCLib::EllipseValue(utrim1, pos, MajR, MinR);
702     B.Add(P);
703     P = ElCLib::EllipseValue(utrim2, pos, MajR, MinR);
704     B.Add(P);
705     Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
706     B.FinitePart().Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
707     Standard_Real gap = B.GetGap();
708     Xmin += gap;
709     Ymin += gap;
710     Zmin += gap;
711     Xmax -= gap;
712     Ymax -= gap;
713     Zmax -= gap;
714     //
715     txmin = ElCLib::InPeriod(txmin, utrim1, utrim1 + 2. * M_PI);
716     if(txmin >= utrim1 && txmin <= utrim2)
717     {
718       Xmin = Min(xmin, Xmin);
719     }
720     txmax = ElCLib::InPeriod(txmax, utrim1, utrim1 + 2. * M_PI);
721     if(txmax >= utrim1 && txmax <= utrim2)
722     {
723       Xmax = Max(xmax, Xmax);
724     }
725     //
726     tymin = ElCLib::InPeriod(tymin, utrim1, utrim1 + 2. * M_PI);
727     if(tymin >= utrim1 && tymin <= utrim2)
728     {
729       Ymin = Min(ymin, Ymin);
730     }
731     tymax = ElCLib::InPeriod(tymax, utrim1, utrim1 + 2. * M_PI);
732     if(tymax >= utrim1 && tymax <= utrim2)
733     {
734       Ymax = Max(ymax, Ymax);
735     }
736     //
737     tzmin = ElCLib::InPeriod(tzmin, utrim1, utrim1 + 2. * M_PI);
738     if(tzmin >= utrim1 && tzmin <= utrim2)
739     {
740       Zmin = Min(zmin, Zmin);
741     }
742     tzmax = ElCLib::InPeriod(tzmax, utrim1, utrim1 + 2. * M_PI);
743     if(tzmax >= utrim1 && tzmax <= utrim2)
744     {
745       Zmax = Max(zmax, Zmax);
746     }
747     //
748     B.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
749   }
750   //
751   B.Enlarge(Tol);
752 }
753
754 void BndLib::Add( const gp_Elips2d& C,const Standard_Real Tol, Bnd_Box2d& B) {
755
756   Standard_Real Ra= C.MajorRadius();
757   Standard_Real Rb= C.MinorRadius();
758   gp_XY Xd = C.XAxis().Direction().XY();
759   gp_XY Yd = C.YAxis().Direction().XY();
760   gp_XY O  = C.Location().XY();
761   B.Add(gp_Pnt2d(O +Ra*Xd +Rb*Yd));
762   B.Add(gp_Pnt2d(O -Ra*Xd +Rb*Yd));
763   B.Add(gp_Pnt2d(O -Ra*Xd -Rb*Yd));
764   B.Add(gp_Pnt2d(O +Ra*Xd -Rb*Yd));
765   B.Enlarge(Tol);
766 }
767
768 void BndLib::Add( const gp_Elips2d& C,const Standard_Real P1,
769                  const Standard_Real P2,
770                  const Standard_Real Tol, Bnd_Box2d& B) {
771
772   Compute(P1,P2,C.MajorRadius(),C.MinorRadius(),
773    gp_Pnt2d(C.XAxis().Direction().XY()),
774    gp_Pnt2d(C.YAxis().Direction().XY()),C.Location(),B);
775   B.Enlarge(Tol);
776 }
777
778 void BndLib::Add( const gp_Parab& P,const Standard_Real P1,
779                  const Standard_Real P2,
780                  const Standard_Real Tol, Bnd_Box& B) {
781
782   if (Precision::IsNegativeInfinite(P1)) {
783     if (Precision::IsNegativeInfinite(P2)) {
784       throw Standard_Failure("BndLib::bad parameter");
785     }
786     else if (Precision::IsPositiveInfinite(P2)) {
787       B.OpenXmax();B.OpenYmax();B.OpenZmax();
788     }
789     else {
790       B.Add(ElCLib::Value(P2,P));
791     }
792     B.OpenXmin();B.OpenYmin();B.OpenZmin();
793   }
794   else if (Precision::IsPositiveInfinite(P1)) {
795     if (Precision::IsNegativeInfinite(P2)) {
796       B.OpenXmin();B.OpenYmin();B.OpenZmin();
797     }
798     else if (Precision::IsPositiveInfinite(P2)) {
799       throw Standard_Failure("BndLib::bad parameter");
800     }
801     else {
802       B.Add(ElCLib::Value(P2,P));
803     }
804     B.OpenXmax();B.OpenYmax();B.OpenZmax();
805   }
806   else  {
807     B.Add(ElCLib::Value(P1,P));
808     if (Precision::IsNegativeInfinite(P2)) {
809       B.OpenXmin();B.OpenYmin();B.OpenZmin();
810     }
811     else if (Precision::IsPositiveInfinite(P2)){
812       B.OpenXmax();B.OpenYmax();B.OpenZmax();
813     }
814     else {
815       B.Add(ElCLib::Value(P2,P));
816       if (P1*P2<0) B.Add(ElCLib::Value(0.,P));
817     }
818   }
819   B.Enlarge(Tol);
820 }
821
822 void BndLib::Add( const gp_Parab2d& P,const Standard_Real P1,
823                  const Standard_Real P2,
824                  const Standard_Real Tol, Bnd_Box2d& B) {
825
826   if (Precision::IsNegativeInfinite(P1)) {
827     if (Precision::IsNegativeInfinite(P2)) {
828       throw Standard_Failure("BndLib::bad parameter");
829     }
830     else if (Precision::IsPositiveInfinite(P2)) {
831       B.OpenXmax();B.OpenYmax();
832     }
833     else {
834       B.Add(ElCLib::Value(P2,P));
835     }
836     B.OpenXmin();B.OpenYmin();
837   }
838   else if (Precision::IsPositiveInfinite(P1)) {
839     if (Precision::IsNegativeInfinite(P2)) {
840       B.OpenXmin();B.OpenYmin();
841     }
842     else if (Precision::IsPositiveInfinite(P2)) {
843       throw Standard_Failure("BndLib::bad parameter");
844     }
845     else {
846       B.Add(ElCLib::Value(P2,P));
847     }
848     B.OpenXmax();B.OpenYmax();
849   }
850   else  {
851     B.Add(ElCLib::Value(P1,P));
852     if (Precision::IsNegativeInfinite(P2)) {
853       B.OpenXmin();B.OpenYmin();
854     }
855     else if (Precision::IsPositiveInfinite(P2)){
856       B.OpenXmax();B.OpenYmax();
857     }
858     else {
859       B.Add(ElCLib::Value(P2,P));
860       if (P1*P2<0) B.Add(ElCLib::Value(0.,P));
861     }
862   }
863   B.Enlarge(Tol);
864 }
865
866 //=======================================================================
867 //function : Add
868 //purpose  : 
869 //=======================================================================
870 void BndLib::Add(const gp_Hypr& H,
871                  const Standard_Real P1,
872                  const Standard_Real P2,
873                  const Standard_Real Tol, 
874                  Bnd_Box& B) 
875 {
876   if (Precision::IsNegativeInfinite(P1)) {
877     if (Precision::IsNegativeInfinite(P2)) {
878       throw Standard_Failure("BndLib::bad parameter");
879     }
880     else if (Precision::IsPositiveInfinite(P2)) {
881       B.OpenXmax();B.OpenYmax();B.OpenZmax();
882     }
883     else {
884       B.Add(ElCLib::Value(P2,H));
885     }
886     B.OpenXmin();B.OpenYmin();B.OpenZmin();
887   }
888   else if (Precision::IsPositiveInfinite(P1)) {
889     if (Precision::IsNegativeInfinite(P2)) {
890       B.OpenXmin();B.OpenYmin();B.OpenZmin();
891     }
892     else if (Precision::IsPositiveInfinite(P2)) {
893       throw Standard_Failure("BndLib::bad parameter");
894     }
895     else {
896       B.Add(ElCLib::Value(P2,H));
897     }
898     B.OpenXmax();B.OpenYmax();B.OpenZmax();
899   }
900   else  {
901     B.Add(ElCLib::Value(P1,H));
902     if (Precision::IsNegativeInfinite(P2)) {
903       B.OpenXmin();B.OpenYmin();B.OpenZmin();
904     }
905     else if (Precision::IsPositiveInfinite(P2)){
906       B.OpenXmax();B.OpenYmax();B.OpenZmax();
907     }
908     else {
909       ComputeBox(H, P1, P2, B);
910     }
911   }
912   B.Enlarge(Tol);
913 }
914
915 void BndLib::Add(const gp_Hypr2d& H,const Standard_Real P1,
916                  const Standard_Real P2,
917                  const Standard_Real Tol, Bnd_Box2d& B) {
918   
919   if (Precision::IsNegativeInfinite(P1)) {
920     if (Precision::IsNegativeInfinite(P2)) {
921       throw Standard_Failure("BndLib::bad parameter");
922     }
923     else if (Precision::IsPositiveInfinite(P2)) {
924       B.OpenXmax();B.OpenYmax();
925     }
926     else {
927       B.Add(ElCLib::Value(P2,H));
928     }
929     B.OpenXmin();B.OpenYmin();
930   }
931   else if (Precision::IsPositiveInfinite(P1)) {
932     if (Precision::IsNegativeInfinite(P2)) {
933       B.OpenXmin();B.OpenYmin();
934     }
935     else if (Precision::IsPositiveInfinite(P2)) {
936       throw Standard_Failure("BndLib::bad parameter");
937     }
938     else {
939       B.Add(ElCLib::Value(P2,H));
940     }
941     B.OpenXmax();B.OpenYmax();
942   }
943   else  {
944     B.Add(ElCLib::Value(P1,H));
945     if (Precision::IsNegativeInfinite(P2)) {
946       B.OpenXmin();B.OpenYmin();
947     }
948     else if (Precision::IsPositiveInfinite(P2)){
949       B.OpenXmax();B.OpenYmax();
950     }
951     else {
952       B.Add(ElCLib::Value(P2,H));
953       if (P1*P2<0) B.Add(ElCLib::Value(0.,H));
954     }
955   }
956   B.Enlarge(Tol);
957 }
958
959 static void ComputeCyl(const gp_Cylinder& Cyl, 
960                        const Standard_Real UMin, const Standard_Real UMax, 
961                        const Standard_Real VMin, const Standard_Real VMax, 
962                        Bnd_Box& B)
963 {
964   gp_Circ aC = ElSLib::CylinderVIso(Cyl.Position(), Cyl.Radius(), VMin);
965   BndLib::Add(aC, UMin, UMax, 0., B);
966   //
967   gp_Vec aT = (VMax - VMin) * Cyl.Axis().Direction();
968   aC.Translate(aT);
969   BndLib::Add(aC, UMin, UMax, 0., B);
970 }
971
972 void BndLib::Add( const gp_Cylinder& S,const Standard_Real UMin,
973                  const Standard_Real UMax,const Standard_Real VMin,
974                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B)
975 {
976   if (Precision::IsNegativeInfinite(VMin))
977   {
978     if (Precision::IsNegativeInfinite(VMax))
979     {
980       throw Standard_Failure("BndLib::bad parameter");
981     }
982     else if (Precision::IsPositiveInfinite(VMax))
983     {
984       OpenMinMax(S.Axis().Direction(),B);
985     }
986     else
987     {
988       ComputeCyl(S, UMin, UMax, 0., VMax,B);
989       OpenMin(S.Axis().Direction(),B);
990     }
991   }
992   else if (Precision::IsPositiveInfinite(VMin)) 
993   {
994     if (Precision::IsNegativeInfinite(VMax)) 
995     {
996       OpenMinMax(S.Axis().Direction(),B);
997     }
998     else if (Precision::IsPositiveInfinite(VMax))
999     {
1000       throw Standard_Failure("BndLib::bad parameter");
1001     }
1002     else
1003     {
1004       ComputeCyl(S, UMin, UMax, 0., VMax, B);
1005       OpenMax(S.Axis().Direction(),B);
1006     }
1007   }
1008   else
1009   {
1010     if (Precision::IsNegativeInfinite(VMax))
1011     {
1012       ComputeCyl(S, UMin, UMax, VMin, 0., B);
1013       OpenMin(S.Axis().Direction(),B);
1014     }
1015     else if (Precision::IsPositiveInfinite(VMax)) 
1016     {
1017       ComputeCyl(S, UMin, UMax, VMin, 0., B);
1018       OpenMax(S.Axis().Direction(),B); 
1019     }
1020     else 
1021     {
1022       ComputeCyl(S, UMin, UMax, VMin, VMax, B);
1023     }
1024   }
1025
1026   B.Enlarge(Tol);
1027
1028 }
1029
1030 void BndLib::Add( const gp_Cylinder& S,const Standard_Real VMin,
1031                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
1032
1033   BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
1034 }
1035
1036 static void ComputeCone (const gp_Cone& Cone, 
1037                          const Standard_Real UMin, const Standard_Real UMax, 
1038                          const Standard_Real VMin, const Standard_Real VMax, 
1039                          Bnd_Box& B)
1040 {
1041   const gp_Ax3& aPos = Cone.Position();
1042   Standard_Real R = Cone.RefRadius();
1043   Standard_Real sang = Cone.SemiAngle();
1044   gp_Circ aC = ElSLib::ConeVIso(aPos, R, sang, VMin);
1045   if(aC.Radius() > Precision::Confusion())
1046   {
1047     BndLib::Add(aC, UMin, UMax, 0., B);
1048   }
1049   else
1050   {
1051     B.Add(aC.Location());
1052   }
1053   //
1054   aC = ElSLib::ConeVIso(aPos, R, sang, VMax);
1055   if(aC.Radius() > Precision::Confusion())
1056   {
1057     BndLib::Add(aC, UMin, UMax, 0., B);
1058   }
1059   else
1060   {
1061     B.Add(aC.Location());
1062   }
1063 }
1064
1065 void BndLib::Add(const gp_Cone& S,const Standard_Real UMin,
1066                  const Standard_Real UMax,const Standard_Real VMin,
1067                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
1068
1069   Standard_Real A = S.SemiAngle();
1070   if (Precision::IsNegativeInfinite(VMin)) 
1071   {
1072     if (Precision::IsNegativeInfinite(VMax)) 
1073     {
1074       throw Standard_Failure("BndLib::bad parameter");
1075     }
1076     else if (Precision::IsPositiveInfinite(VMax)) 
1077     {
1078       gp_Dir D(Cos(A)*S.Axis().Direction());
1079       OpenMinMax(D,B); 
1080     }
1081     else 
1082     {
1083       ComputeCone(S, UMin, UMax, 0., VMax, B);
1084       gp_Dir D(Cos(A)*S.Axis().Direction());
1085       OpenMin(D,B);     
1086     }
1087
1088   }
1089   else if (Precision::IsPositiveInfinite(VMin)) 
1090   {
1091     if (Precision::IsNegativeInfinite(VMax))
1092     {
1093       gp_Dir D(Cos(A)*S.Axis().Direction());
1094       OpenMinMax(D,B);
1095     }
1096     else if (Precision::IsPositiveInfinite(VMax)) 
1097     {
1098       throw Standard_Failure("BndLib::bad parameter");
1099     }
1100     else 
1101     {
1102       ComputeCone(S, UMin, UMax, 0., VMax, B);
1103       gp_Dir D(Cos(A)*S.Axis().Direction());
1104       OpenMax(D,B);
1105     }
1106   }
1107   else 
1108   {
1109     if (Precision::IsNegativeInfinite(VMax)) 
1110     {
1111       ComputeCone(S, UMin, UMax, VMin, 0., B);
1112       gp_Dir D(Cos(A)*S.Axis().Direction());
1113       OpenMin(D,B);
1114     }
1115     else if (Precision::IsPositiveInfinite(VMax)) 
1116     {
1117       ComputeCone(S, UMin, UMax, VMin, 0., B);
1118       gp_Dir D(Cos(A)*S.Axis().Direction());
1119       OpenMax(D,B);
1120     }
1121     else 
1122     {
1123       ComputeCone(S, UMin, UMax, VMin, VMax, B);
1124     }
1125   }
1126
1127   B.Enlarge(Tol);
1128 }
1129
1130 void BndLib::Add( const gp_Cone& S,const Standard_Real VMin,
1131                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
1132
1133   BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
1134 }
1135
1136 static void ComputeSphere (const gp_Sphere& Sphere, 
1137                            const Standard_Real UMin, const Standard_Real UMax, 
1138                            const Standard_Real VMin, const Standard_Real VMax, 
1139                            Bnd_Box& B)
1140 {
1141   gp_Pnt P = Sphere.Location();
1142   Standard_Real R = Sphere.Radius();
1143   Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
1144   xmin = P.X() - R;
1145   xmax = P.X() + R;
1146   ymin = P.Y() - R;
1147   ymax = P.Y() + R;
1148   zmin = P.Z() - R;
1149   zmax = P.Z() + R;
1150   
1151   Standard_Real uper = 2. * M_PI - Precision::PConfusion();
1152   Standard_Real vper = M_PI - Precision::PConfusion();
1153   if (UMax - UMin >= uper && VMax - VMin >= vper)
1154   {
1155     // a whole sphere
1156     B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
1157   }
1158   else
1159   {
1160     Standard_Real u, v;
1161     Standard_Real umax = UMin + 2. * M_PI;
1162     const gp_Ax3& Pos = Sphere.Position();
1163     gp_Pnt PExt = P;
1164     PExt.SetX(xmin);
1165     ElSLib::SphereParameters(Pos, R, PExt, u, v);
1166     u = ElCLib::InPeriod(u, UMin, umax);
1167     if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
1168     {
1169       B.Add(PExt);
1170     }
1171     //
1172     PExt.SetX(xmax);
1173     ElSLib::SphereParameters(Pos, R, PExt, u, v);
1174     u = ElCLib::InPeriod(u, UMin, umax);
1175     if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
1176     {
1177       B.Add(PExt);
1178     }
1179     PExt.SetX(P.X());
1180     //
1181     PExt.SetY(ymin);
1182     ElSLib::SphereParameters(Pos, R, PExt, u, v);
1183     u = ElCLib::InPeriod(u, UMin, umax);
1184     if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
1185     {
1186       B.Add(PExt);
1187     }
1188     //
1189     PExt.SetY(ymax);
1190     ElSLib::SphereParameters(Pos, R, PExt, u, v);
1191     u = ElCLib::InPeriod(u, UMin, umax);
1192     if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
1193     {
1194       B.Add(PExt);
1195     }
1196     PExt.SetY(P.Y());
1197     //
1198     PExt.SetZ(zmin);
1199     ElSLib::SphereParameters(Pos, R, PExt, u, v);
1200     u = ElCLib::InPeriod(u, UMin, umax);
1201     if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
1202     {
1203       B.Add(PExt);
1204     }
1205     //
1206     PExt.SetZ(zmax);
1207     ElSLib::SphereParameters(Pos, R, PExt, u, v);
1208     u = ElCLib::InPeriod(u, UMin, umax);
1209     if(u >= UMin && u <= UMax && v >= VMin && v <= VMax)
1210     {
1211       B.Add(PExt);
1212     }
1213     //
1214     // Add boundaries of patch
1215     // UMin, UMax
1216     gp_Circ aC = ElSLib::SphereUIso(Pos, R, UMin);
1217     BndLib::Add(aC, VMin, VMax, 0., B);
1218     aC = ElSLib::SphereUIso(Pos, R, UMax);
1219     BndLib::Add(aC, VMin, VMax, 0., B);
1220     // VMin, VMax
1221     aC = ElSLib::SphereVIso(Pos, R, VMin);
1222     BndLib::Add(aC, UMin, UMax, 0., B);
1223     aC = ElSLib::SphereVIso(Pos, R, VMax);
1224     BndLib::Add(aC, UMin, UMax, 0., B);
1225   }
1226 }
1227
1228 void BndLib::Add(const gp_Sphere& S,const Standard_Real UMin,
1229                  const Standard_Real UMax,const Standard_Real VMin,
1230                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) 
1231 {
1232   ComputeSphere(S, UMin, UMax, VMin, VMax, B);
1233   B.Enlarge(Tol);
1234 }
1235
1236 void BndLib::Add( const gp_Sphere& S,const Standard_Real Tol, Bnd_Box& B) 
1237 {
1238   gp_Pnt P = S.Location();
1239   Standard_Real R = S.Radius();
1240   Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
1241   xmin = P.X() - R;
1242   xmax = P.X() + R;
1243   ymin = P.Y() - R;
1244   ymax = P.Y() + R;
1245   zmin = P.Z() - R;
1246   zmax = P.Z() + R;
1247   B.Update(xmin, ymin, zmin, xmax, ymax, zmax);
1248   B.Enlarge(Tol);
1249 }
1250
1251 void BndLib::Add(const gp_Torus& S,const Standard_Real UMin,
1252    const Standard_Real UMax,const Standard_Real VMin,
1253    const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
1254
1255   Standard_Integer Fi1;
1256   Standard_Integer Fi2;
1257   if (VMax<VMin) {
1258     Fi1 = (Standard_Integer )( VMax/(M_PI/4.));
1259     Fi2 = (Standard_Integer )( VMin/(M_PI/4.));
1260   }
1261   else {
1262     Fi1 = (Standard_Integer )( VMin/(M_PI/4.));
1263     Fi2 = (Standard_Integer )( VMax/(M_PI/4.));
1264   }
1265   Fi2++;
1266   
1267   Standard_Real Ra = S.MajorRadius();
1268   Standard_Real Ri = S.MinorRadius();
1269
1270   if (Fi2<Fi1) return;
1271
1272 #define SC 0.71
1273 #define addP0    (Compute(UMin,UMax,Ra+Ri,Ra+Ri,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),S.Location(),B))
1274 #define addP1    (Compute(UMin,UMax,Ra+Ri*SC,Ra+Ri*SC,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),gp_Pnt(S.Location().XYZ()+(Ri*SC)*S.Axis().Direction().XYZ()),B))
1275 #define addP2    (Compute(UMin,UMax,Ra,Ra,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),gp_Pnt(S.Location().XYZ()+Ri*S.Axis().Direction().XYZ()),B))
1276 #define addP3    (Compute(UMin,UMax,Ra-Ri*SC,Ra-Ri*SC,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),gp_Pnt(S.Location().XYZ()+(Ri*SC)*S.Axis().Direction().XYZ()),B))
1277 #define addP4    (Compute(UMin,UMax,Ra-Ri,Ra-Ri,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),S.Location(),B))
1278 #define addP5    (Compute(UMin,UMax,Ra-Ri*SC,Ra-Ri*SC,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),gp_Pnt(S.Location().XYZ()-(Ri*SC)*S.Axis().Direction().XYZ()),B))
1279 #define addP6    (Compute(UMin,UMax,Ra,Ra,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),gp_Pnt(S.Location().XYZ()-Ri*S.Axis().Direction().XYZ()),B))
1280 #define addP7    (Compute(UMin,UMax,Ra+Ri*SC,Ra+Ri*SC,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),gp_Pnt(S.Location().XYZ()-(Ri*SC)*S.Axis().Direction().XYZ()),B))
1281   
1282   switch (Fi1) {
1283   case 0 : 
1284     {
1285       addP0;
1286       if (Fi2 <= 0) break;
1287     }
1288     Standard_FALLTHROUGH
1289   case 1 : 
1290     {
1291       addP1;
1292       if (Fi2 <= 1) break;
1293     }
1294     Standard_FALLTHROUGH
1295   case 2 :  
1296     {
1297       addP2;
1298       if (Fi2 <= 2) break;
1299     }
1300     Standard_FALLTHROUGH
1301   case 3 :  
1302     {
1303       addP3;
1304       if (Fi2 <= 3) break;
1305     }
1306     Standard_FALLTHROUGH
1307   case 4 :  
1308     {
1309       addP4;
1310       if (Fi2 <= 4) break;
1311     }
1312     Standard_FALLTHROUGH
1313   case 5 :  
1314     {
1315       addP5;
1316       if (Fi2 <= 5) break;
1317     }
1318     Standard_FALLTHROUGH
1319   case 6 :  
1320     {
1321       addP6;
1322       if (Fi2 <= 6) break;
1323     }
1324     Standard_FALLTHROUGH
1325   case 7 :  
1326     {
1327       addP7;
1328       if (Fi2 <= 7) break;
1329     }
1330     Standard_FALLTHROUGH
1331   case 8 :  
1332   default :
1333     {
1334       addP0;
1335       switch (Fi2) {
1336       case 15 :  
1337         addP7;
1338         Standard_FALLTHROUGH
1339       case 14 :  
1340         addP6;
1341         Standard_FALLTHROUGH
1342       case 13 :  
1343         addP5;
1344         Standard_FALLTHROUGH
1345       case 12 :  
1346         addP4;
1347         Standard_FALLTHROUGH
1348       case 11 :  
1349         addP3;
1350         Standard_FALLTHROUGH
1351       case 10 :  
1352         addP2;
1353         Standard_FALLTHROUGH
1354       case 9 : 
1355         addP1;
1356         Standard_FALLTHROUGH
1357       case 8 : 
1358         break;
1359       }    
1360     }
1361   }    
1362   B.Enlarge(Tol);
1363 }
1364
1365
1366 void BndLib::Add( const gp_Torus& S,const Standard_Real Tol, Bnd_Box& B) {
1367
1368   Standard_Real RMa = S.MajorRadius();
1369   Standard_Real Rmi = S.MinorRadius(); 
1370   gp_XYZ O = S.Location().XYZ();
1371   gp_XYZ Xd = S.XAxis().Direction().XYZ();
1372   gp_XYZ Yd = S.YAxis().Direction().XYZ();
1373   gp_XYZ Zd = S.Axis().Direction().XYZ();
1374   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd -(RMa+Rmi)*Yd+ Rmi*Zd)); 
1375   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd -(RMa+Rmi)*Yd- Rmi*Zd)); 
1376   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd -(RMa+Rmi)*Yd+ Rmi*Zd)); 
1377   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd -(RMa+Rmi)*Yd- Rmi*Zd)); 
1378   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd +(RMa+Rmi)*Yd+ Rmi*Zd)); 
1379   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd +(RMa+Rmi)*Yd- Rmi*Zd)); 
1380   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd +(RMa+Rmi)*Yd+ Rmi*Zd)); 
1381   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd +(RMa+Rmi)*Yd- Rmi*Zd)); 
1382   B.Enlarge(Tol);
1383 }
1384 //=======================================================================
1385 //function : ComputeBox
1386 //purpose  : 
1387 //=======================================================================
1388 Standard_Integer ComputeBox(const gp_Hypr& aHypr, 
1389                             const Standard_Real aT1, 
1390                             const Standard_Real aT2, 
1391                             Bnd_Box& aBox)
1392 {
1393   Standard_Integer i, iErr;
1394   Standard_Real aRmaj, aRmin, aA, aB, aABP, aBAM, aT3, aCf, aEps;
1395   gp_Pnt aP1, aP2, aP3, aP0;
1396   //
1397   //
1398   aP1=ElCLib::Value(aT1, aHypr);
1399   aP2=ElCLib::Value(aT2, aHypr);
1400   //
1401   aBox.Add(aP1);
1402   aBox.Add(aP2);
1403   //
1404   if (aT1*aT2<0.) {
1405     aP0=ElCLib::Value(0., aHypr);
1406     aBox.Add(aP0);
1407   }
1408   //
1409   aEps=Epsilon(1.);
1410   iErr=1;
1411   //
1412   const gp_Ax2& aPos=aHypr.Position();
1413   const gp_XYZ& aXDir = aPos.XDirection().XYZ();
1414   const gp_XYZ& aYDir = aPos.YDirection().XYZ();
1415   aRmaj=aHypr.MajorRadius();
1416   aRmin=aHypr.MinorRadius();
1417   //
1418   aT3=0;
1419   for (i=1; i<=3; ++i) {
1420     aA=aRmin*aYDir.Coord(i);
1421     aB=aRmaj*aXDir.Coord(i);
1422     //
1423     aABP=aA+aB;
1424     aBAM=aB-aA;
1425     //
1426     aABP=fabs(aABP);
1427     aBAM=fabs(aBAM);
1428     //
1429     if (aABP<aEps || aBAM<aEps) {
1430       continue;
1431     }
1432     //
1433     aCf=aBAM/aABP;
1434     aT3=log(sqrt(aCf));
1435     //
1436     if (aT3<aT1 || aT3>aT2) {
1437       continue;
1438     }
1439     iErr=0;
1440     break;
1441   }
1442   //
1443   if (iErr) {
1444     return iErr;
1445   }
1446   //
1447   aP3=ElCLib::Value(aT3, aHypr);
1448   aBox.Add(aP3);
1449   //
1450   return iErr;
1451 }