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