0024002: Overall code and build procedure refactoring -- automatic
[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
41 static 
42   Standard_Integer ComputeBox(const gp_Hypr& aHypr, 
43                               const Standard_Real aT1, 
44                               const Standard_Real aT2, 
45                               Bnd_Box& aBox);
46
47
48 namespace
49 {
50   //! Compute method
51   template<class PointType, class BndBoxType>
52   void Compute (const Standard_Real theP1, const Standard_Real theP2,
53                 const Standard_Real theRa ,const Standard_Real theRb,
54                 const PointType& theXd, const PointType& theYd, const PointType& theO,
55                 BndBoxType& theB)
56   {
57     Standard_Real aTeta1;
58     Standard_Real aTeta2;
59     if(theP2 < theP1)
60     { 
61       aTeta1 = theP2;
62       aTeta2 = theP1;
63     }
64     else
65     {
66       aTeta1 = theP1;
67       aTeta2 = theP2;
68     }
69
70     Standard_Real aDelta = Abs(aTeta2-aTeta1); 
71     if(aDelta > 2. * M_PI)
72     {
73       aTeta1 = 0.;
74       aTeta2 = 2. * M_PI;
75     }
76     else
77     {
78       if(aTeta1 < 0.)
79       {
80         do{ aTeta1 += 2.*M_PI; } while (aTeta1 < 0.);
81       }
82       else if (aTeta1 > 2.*M_PI)
83       {
84         do { aTeta1 -= 2.*M_PI; } while (aTeta1 > 2.*M_PI);
85       }
86       aTeta2 = aTeta1 + aDelta;
87     }
88
89     // One places already both ends
90     Standard_Real aCn1, aSn1 ,aCn2, aSn2;
91     aCn1 = Cos(aTeta1); aSn1 = Sin(aTeta1);
92     aCn2 = Cos(aTeta2); aSn2 = Sin(aTeta2);
93     theB.Add(PointType( theO.Coord() +theRa*aCn1*theXd.Coord() +theRb*aSn1*theYd.Coord()));
94     theB.Add(PointType(theO.Coord() +theRa*aCn2*theXd.Coord() +theRb*aSn2*theYd.Coord()));
95     
96     Standard_Real aRam, aRbm;
97     if (aDelta > M_PI/8.)
98     {
99       // Main radiuses to take into account only 8 points (/cos(Pi/8.))
100       aRam = theRa/0.92387953251128674;
101       aRbm = theRb/0.92387953251128674;
102     }
103     else
104     {
105       // Main radiuses to take into account the arrow
106       Standard_Real aTc = cos(aDelta/2);
107       aRam = theRa/aTc;
108       aRbm = theRb/aTc;
109     }
110     theB.Add(PointType(theO.Coord() + aRam*aCn1*theXd.Coord() + aRbm*aSn1*theYd.Coord()));
111     theB.Add(PointType(theO.Coord() + aRam*aCn2*theXd.Coord() + aRbm*aSn2*theYd.Coord()));
112
113 // cos or sin M_PI/4.
114 #define PI4 0.70710678118654746
115
116 // 8 points of the polygon
117 #define addPoint0 theB.Add(PointType(theO.Coord() +aRam*theXd.Coord()))
118 #define addPoint1 theB.Add(PointType(theO.Coord() +aRam*PI4*theXd.Coord() +aRbm*PI4*theYd.Coord()))
119 #define addPoint2 theB.Add(PointType(theO.Coord() +aRbm*theYd.Coord()))
120 #define addPoint3 theB.Add(PointType(theO.Coord() -aRam*PI4*theXd.Coord() +aRbm*PI4*theYd.Coord()))
121 #define addPoint4 theB.Add(PointType(theO.Coord() -aRam*theXd.Coord() ))
122 #define addPoint5 theB.Add(PointType(theO.Coord() -aRam*PI4*theXd.Coord() -aRbm*PI4*theYd.Coord()))
123 #define addPoint6 theB.Add(PointType(theO.Coord() -aRbm*theYd.Coord()))
124 #define addPoint7 theB.Add(PointType(theO.Coord() +aRam*PI4*theXd.Coord() -aRbm*PI4*theYd.Coord()))
125
126     Standard_Integer aDeb = (Standard_Integer )( aTeta1/(M_PI/4.));
127     Standard_Integer aFin = (Standard_Integer )( aTeta2/(M_PI/4.));
128     aDeb++;
129
130     if (aDeb > aFin) return;
131
132     switch (aDeb)
133     {
134     case 1:
135       {
136         addPoint1;
137         if (aFin <= 1) break;
138       }
139     case 2:
140       {
141         addPoint2;
142         if (aFin <= 2) break;
143       }
144     case 3:
145       {
146         addPoint3;
147         if (aFin <= 3) break;
148       }
149     case 4:
150       {
151         addPoint4;
152         if (aFin <= 4) break;
153       }
154     case 5:
155       {
156         addPoint5;
157         if (aFin <= 5) break;
158       }
159     case 6:
160       {
161         addPoint6;
162         if (aFin <= 6) break;
163       }
164     case 7:
165       {
166         addPoint7;
167         if (aFin <= 7) break;
168       }
169     case 8:
170       {
171         addPoint0;
172         if (aFin <= 8) break;
173       }
174     case 9:
175       {
176         addPoint1;
177         if (aFin <= 9) break;
178       }  
179     case 10:
180       {
181         addPoint2;
182         if (aFin <= 10) break;
183       }
184     case 11:
185       {
186         addPoint3;
187         if (aFin <= 11) break;
188       }  
189     case 12:
190       {
191         addPoint4;
192         if (aFin <= 12) break;
193       }  
194     case 13:
195       {
196         addPoint5;
197         if (aFin <= 13) break;
198       }
199     case 14:
200       {
201         addPoint6;
202         if (aFin <= 14) break;
203       }
204     case 15:
205       {
206         addPoint7;
207         if (aFin <= 15) break;
208       }
209     }
210   }
211 } // end namespace
212
213 static void OpenMin(const gp_Dir& V,Bnd_Box& B) {
214   gp_Dir OX(1.,0.,0.);
215   gp_Dir OY(0.,1.,0.);
216   gp_Dir OZ(0.,0.,1.);
217   if (V.IsParallel(OX,Precision::Angular())) 
218     B.OpenXmin();
219   else if (V.IsParallel(OY,Precision::Angular())) 
220     B.OpenYmin();
221   else if (V.IsParallel(OZ,Precision::Angular())) 
222     B.OpenZmin();
223   else {
224     B.OpenXmin();B.OpenYmin();B.OpenZmin();
225   }
226 }
227
228 static void OpenMax(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.OpenXmax();
234   else if (V.IsParallel(OY,Precision::Angular())) 
235     B.OpenYmax();
236   else if (V.IsParallel(OZ,Precision::Angular())) 
237     B.OpenZmax();
238   else {
239     B.OpenXmax();B.OpenYmax();B.OpenZmax();
240   }
241 }
242
243 static void OpenMinMax(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();B.OpenXmin();
249   }
250   else if (V.IsParallel(OY,Precision::Angular())) {
251     B.OpenYmax();B.OpenYmin();
252   }
253   else if (V.IsParallel(OZ,Precision::Angular())) {
254     B.OpenZmax();B.OpenZmin();
255   }
256   else {
257     B.OpenXmin();B.OpenYmin();B.OpenZmin();
258     B.OpenXmax();B.OpenYmax();B.OpenZmax();
259   }
260 }
261
262 static void OpenMin(const gp_Dir2d& V,Bnd_Box2d& B) {
263   gp_Dir2d OX(1.,0.);
264   gp_Dir2d OY(0.,1.);
265   if (V.IsParallel(OX,Precision::Angular())) 
266     B.OpenXmin();
267   else if (V.IsParallel(OY,Precision::Angular())) 
268     B.OpenYmin();
269   else {
270     B.OpenXmin();B.OpenYmin();
271   }
272 }
273
274 static void OpenMax(const gp_Dir2d& V,Bnd_Box2d& B) {
275   gp_Dir2d OX(1.,0.);
276   gp_Dir2d OY(0.,1.);
277   if (V.IsParallel(OX,Precision::Angular())) 
278     B.OpenXmax();
279   else if (V.IsParallel(OY,Precision::Angular())) 
280     B.OpenYmax();
281   else {
282     B.OpenXmax();B.OpenYmax();
283   }
284 }
285
286 static void OpenMinMax(const gp_Dir2d& V,Bnd_Box2d& B) {
287   gp_Dir2d OX(1.,0.);
288   gp_Dir2d OY(0.,1.);
289   if (V.IsParallel(OX,Precision::Angular())) {
290     B.OpenXmax();B.OpenXmin();
291   }
292   else if (V.IsParallel(OY,Precision::Angular())) {
293     B.OpenYmax();B.OpenYmin();
294   }
295   else {
296     B.OpenXmin();B.OpenYmin();
297     B.OpenXmax();B.OpenYmax();
298   }
299 }
300
301
302 void BndLib::Add( const gp_Lin& L,const Standard_Real P1,
303                  const Standard_Real P2,
304                  const Standard_Real Tol, Bnd_Box& B) {
305
306   if (Precision::IsNegativeInfinite(P1)) {
307     if (Precision::IsNegativeInfinite(P2)) {
308       Standard_Failure::Raise("BndLib::bad parameter");
309     }
310     else if (Precision::IsPositiveInfinite(P2)) {
311       OpenMinMax(L.Direction(),B);
312       B.Add(ElCLib::Value(0.,L));
313     }
314     else {
315       OpenMin(L.Direction(),B);
316       B.Add(ElCLib::Value(P2,L));
317     }
318   }
319   else if (Precision::IsPositiveInfinite(P1)) {
320     if (Precision::IsNegativeInfinite(P2)) {
321       OpenMinMax(L.Direction(),B);
322       B.Add(ElCLib::Value(0.,L));
323     }
324     else if (Precision::IsPositiveInfinite(P2)) {
325       Standard_Failure::Raise("BndLib::bad parameter");
326     }
327     else {
328       OpenMax(L.Direction(),B);
329       B.Add(ElCLib::Value(P2,L));
330     }
331   }
332   else  {
333     B.Add(ElCLib::Value(P1,L));
334     if (Precision::IsNegativeInfinite(P2)) {
335       OpenMin(L.Direction(),B);
336     }
337     else if (Precision::IsPositiveInfinite(P2)){
338       OpenMax(L.Direction(),B);
339     }
340     else {
341       B.Add(ElCLib::Value(P2,L));
342     }
343   }
344   B.Enlarge(Tol);
345 }
346
347 void BndLib::Add( const gp_Lin2d& L,const Standard_Real P1,
348                  const Standard_Real P2,
349                  const Standard_Real Tol, Bnd_Box2d& B) {
350
351   if (Precision::IsNegativeInfinite(P1)) {
352     if (Precision::IsNegativeInfinite(P2)) {
353       Standard_Failure::Raise("BndLib::bad parameter");
354     }
355     else if (Precision::IsPositiveInfinite(P2)) {
356       OpenMinMax(L.Direction(),B);
357       B.Add(ElCLib::Value(0.,L));
358     }
359     else {
360       OpenMin(L.Direction(),B);
361       B.Add(ElCLib::Value(P2,L));
362     }
363   }
364   else if (Precision::IsPositiveInfinite(P1)) {
365     if (Precision::IsNegativeInfinite(P2)) {
366       OpenMinMax(L.Direction(),B);
367       B.Add(ElCLib::Value(0.,L));
368     }
369     else if (Precision::IsPositiveInfinite(P2)) {
370       Standard_Failure::Raise("BndLib::bad parameter");
371     }
372     else {
373       OpenMax(L.Direction(),B);
374       B.Add(ElCLib::Value(P2,L));
375     }
376   }
377   else  {
378     B.Add(ElCLib::Value(P1,L));
379     if (Precision::IsNegativeInfinite(P2)) {
380       OpenMin(L.Direction(),B);
381     }
382     else if (Precision::IsPositiveInfinite(P2)){
383       OpenMax(L.Direction(),B);
384     }
385     else {
386       B.Add(ElCLib::Value(P2,L));
387     }
388   }
389   B.Enlarge(Tol);
390 }
391
392 void BndLib::Add( const gp_Circ& C,const Standard_Real Tol, Bnd_Box& B) {
393
394   Standard_Real R = C.Radius();
395   gp_XYZ O  = C.Location().XYZ();
396   gp_XYZ Xd = C.XAxis().Direction().XYZ();
397   gp_XYZ Yd = C.YAxis().Direction().XYZ();
398   B.Add(gp_Pnt(O -R*Xd -R*Yd));
399   B.Add(gp_Pnt(O -R*Xd +R*Yd));
400   B.Add(gp_Pnt(O +R*Xd -R*Yd));
401   B.Add(gp_Pnt(O +R*Xd +R*Yd));
402   B.Enlarge(Tol);
403 }
404
405 void BndLib::Add( const gp_Circ& C,const Standard_Real P1,
406   const Standard_Real P2,
407   const Standard_Real Tol, Bnd_Box& B) {
408
409   Compute(P1,P2,C.Radius(),C.Radius(),gp_Pnt(C.XAxis().Direction().XYZ()), 
410           gp_Pnt(C.YAxis().Direction().XYZ()),C.Location(),B);
411   B.Enlarge(Tol);
412 }
413
414 void BndLib::Add( const gp_Circ2d& C,const Standard_Real Tol, Bnd_Box2d& B) {
415
416   Standard_Real R = C.Radius();
417   gp_XY O  = C.Location().XY();
418   gp_XY Xd = C.XAxis().Direction().XY();
419   gp_XY Yd = C.YAxis().Direction().XY();
420   B.Add(gp_Pnt2d(O -R*Xd -R*Yd));
421   B.Add(gp_Pnt2d(O -R*Xd +R*Yd));
422   B.Add(gp_Pnt2d(O +R*Xd -R*Yd));
423   B.Add(gp_Pnt2d(O +R*Xd +R*Yd));
424   B.Enlarge(Tol);
425 }
426
427 void BndLib::Add(const gp_Circ2d& C,const Standard_Real P1,
428    const Standard_Real P2,
429    const Standard_Real Tol, Bnd_Box2d& B) {
430
431        Compute(P1,P2,C.Radius(),C.Radius(),gp_Pnt2d(C.XAxis().Direction().XY()),
432          gp_Pnt2d(C.YAxis().Direction().XY()),C.Location(),B);
433   B.Enlarge(Tol);
434 }
435
436 void BndLib::Add( const gp_Elips& C,const Standard_Real Tol, Bnd_Box& B) {
437
438   Standard_Real Ra = C.MajorRadius();
439   Standard_Real Rb = C.MinorRadius();
440   gp_XYZ Xd = C.XAxis().Direction().XYZ();
441   gp_XYZ Yd = C.YAxis().Direction().XYZ();
442   gp_XYZ O  = C.Location().XYZ();
443   B.Add(gp_Pnt(O +Ra*Xd +Rb*Yd));
444   B.Add(gp_Pnt(O -Ra*Xd +Rb*Yd));
445   B.Add(gp_Pnt(O -Ra*Xd -Rb*Yd));
446   B.Add(gp_Pnt(O +Ra*Xd -Rb*Yd));
447   B.Enlarge(Tol);
448 }
449
450 void BndLib::Add( const gp_Elips& C,const Standard_Real P1,
451                  const Standard_Real P2,
452                  const Standard_Real Tol, Bnd_Box& B) {
453
454   Compute(P1,P2,C.MajorRadius(),C.MinorRadius(),gp_Pnt(C.XAxis().Direction().XYZ()), 
455           gp_Pnt(C.YAxis().Direction().XYZ()),C.Location(),B);
456   B.Enlarge(Tol);
457 }
458
459 void BndLib::Add( const gp_Elips2d& C,const Standard_Real Tol, Bnd_Box2d& B) {
460
461   Standard_Real Ra= C.MajorRadius();
462   Standard_Real Rb= C.MinorRadius();
463   gp_XY Xd = C.XAxis().Direction().XY();
464   gp_XY Yd = C.YAxis().Direction().XY();
465   gp_XY O  = C.Location().XY();
466   B.Add(gp_Pnt2d(O +Ra*Xd +Rb*Yd));
467   B.Add(gp_Pnt2d(O -Ra*Xd +Rb*Yd));
468   B.Add(gp_Pnt2d(O -Ra*Xd -Rb*Yd));
469   B.Add(gp_Pnt2d(O +Ra*Xd -Rb*Yd));
470   B.Enlarge(Tol);
471 }
472
473 void BndLib::Add( const gp_Elips2d& C,const Standard_Real P1,
474                  const Standard_Real P2,
475                  const Standard_Real Tol, Bnd_Box2d& B) {
476
477   Compute(P1,P2,C.MajorRadius(),C.MinorRadius(),
478    gp_Pnt2d(C.XAxis().Direction().XY()),
479    gp_Pnt2d(C.YAxis().Direction().XY()),C.Location(),B);
480   B.Enlarge(Tol);
481 }
482
483 void BndLib::Add( const gp_Parab& P,const Standard_Real P1,
484                  const Standard_Real P2,
485                  const Standard_Real Tol, Bnd_Box& B) {
486
487   if (Precision::IsNegativeInfinite(P1)) {
488     if (Precision::IsNegativeInfinite(P2)) {
489       Standard_Failure::Raise("BndLib::bad parameter");
490     }
491     else if (Precision::IsPositiveInfinite(P2)) {
492       B.OpenXmax();B.OpenYmax();B.OpenZmax();
493     }
494     else {
495       B.Add(ElCLib::Value(P2,P));
496     }
497     B.OpenXmin();B.OpenYmin();B.OpenZmin();
498   }
499   else if (Precision::IsPositiveInfinite(P1)) {
500     if (Precision::IsNegativeInfinite(P2)) {
501       B.OpenXmin();B.OpenYmin();B.OpenZmin();
502     }
503     else if (Precision::IsPositiveInfinite(P2)) {
504       Standard_Failure::Raise("BndLib::bad parameter");
505     }
506     else {
507       B.Add(ElCLib::Value(P2,P));
508     }
509     B.OpenXmax();B.OpenYmax();B.OpenZmax();
510   }
511   else  {
512     B.Add(ElCLib::Value(P1,P));
513     if (Precision::IsNegativeInfinite(P2)) {
514       B.OpenXmin();B.OpenYmin();B.OpenZmin();
515     }
516     else if (Precision::IsPositiveInfinite(P2)){
517       B.OpenXmax();B.OpenYmax();B.OpenZmax();
518     }
519     else {
520       B.Add(ElCLib::Value(P2,P));
521       if (P1*P2<0) B.Add(ElCLib::Value(0.,P));
522     }
523   }
524   B.Enlarge(Tol);
525 }
526
527 void BndLib::Add( const gp_Parab2d& P,const Standard_Real P1,
528                  const Standard_Real P2,
529                  const Standard_Real Tol, Bnd_Box2d& B) {
530
531   if (Precision::IsNegativeInfinite(P1)) {
532     if (Precision::IsNegativeInfinite(P2)) {
533       Standard_Failure::Raise("BndLib::bad parameter");
534     }
535     else if (Precision::IsPositiveInfinite(P2)) {
536       B.OpenXmax();B.OpenYmax();
537     }
538     else {
539       B.Add(ElCLib::Value(P2,P));
540     }
541     B.OpenXmin();B.OpenYmin();
542   }
543   else if (Precision::IsPositiveInfinite(P1)) {
544     if (Precision::IsNegativeInfinite(P2)) {
545       B.OpenXmin();B.OpenYmin();
546     }
547     else if (Precision::IsPositiveInfinite(P2)) {
548       Standard_Failure::Raise("BndLib::bad parameter");
549     }
550     else {
551       B.Add(ElCLib::Value(P2,P));
552     }
553     B.OpenXmax();B.OpenYmax();
554   }
555   else  {
556     B.Add(ElCLib::Value(P1,P));
557     if (Precision::IsNegativeInfinite(P2)) {
558       B.OpenXmin();B.OpenYmin();
559     }
560     else if (Precision::IsPositiveInfinite(P2)){
561       B.OpenXmax();B.OpenYmax();
562     }
563     else {
564       B.Add(ElCLib::Value(P2,P));
565       if (P1*P2<0) B.Add(ElCLib::Value(0.,P));
566     }
567   }
568   B.Enlarge(Tol);
569 }
570
571 //=======================================================================
572 //function : Add
573 //purpose  : 
574 //=======================================================================
575 void BndLib::Add(const gp_Hypr& H,
576                  const Standard_Real P1,
577                  const Standard_Real P2,
578                  const Standard_Real Tol, 
579                  Bnd_Box& B) 
580 {
581   if (Precision::IsNegativeInfinite(P1)) {
582     if (Precision::IsNegativeInfinite(P2)) {
583       Standard_Failure::Raise("BndLib::bad parameter");
584     }
585     else if (Precision::IsPositiveInfinite(P2)) {
586       B.OpenXmax();B.OpenYmax();B.OpenZmax();
587     }
588     else {
589       B.Add(ElCLib::Value(P2,H));
590     }
591     B.OpenXmin();B.OpenYmin();B.OpenZmin();
592   }
593   else if (Precision::IsPositiveInfinite(P1)) {
594     if (Precision::IsNegativeInfinite(P2)) {
595       B.OpenXmin();B.OpenYmin();B.OpenZmin();
596     }
597     else if (Precision::IsPositiveInfinite(P2)) {
598       Standard_Failure::Raise("BndLib::bad parameter");
599     }
600     else {
601       B.Add(ElCLib::Value(P2,H));
602     }
603     B.OpenXmax();B.OpenYmax();B.OpenZmax();
604   }
605   else  {
606     B.Add(ElCLib::Value(P1,H));
607     if (Precision::IsNegativeInfinite(P2)) {
608       B.OpenXmin();B.OpenYmin();B.OpenZmin();
609     }
610     else if (Precision::IsPositiveInfinite(P2)){
611       B.OpenXmax();B.OpenYmax();B.OpenZmax();
612     }
613     else {
614       ComputeBox(H, P1, P2, B);
615     }
616   }
617   B.Enlarge(Tol);
618 }
619
620 void BndLib::Add(const gp_Hypr2d& H,const Standard_Real P1,
621                  const Standard_Real P2,
622                  const Standard_Real Tol, Bnd_Box2d& B) {
623   
624   if (Precision::IsNegativeInfinite(P1)) {
625     if (Precision::IsNegativeInfinite(P2)) {
626       Standard_Failure::Raise("BndLib::bad parameter");
627     }
628     else if (Precision::IsPositiveInfinite(P2)) {
629       B.OpenXmax();B.OpenYmax();
630     }
631     else {
632       B.Add(ElCLib::Value(P2,H));
633     }
634     B.OpenXmin();B.OpenYmin();
635   }
636   else if (Precision::IsPositiveInfinite(P1)) {
637     if (Precision::IsNegativeInfinite(P2)) {
638       B.OpenXmin();B.OpenYmin();
639     }
640     else if (Precision::IsPositiveInfinite(P2)) {
641       Standard_Failure::Raise("BndLib::bad parameter");
642     }
643     else {
644       B.Add(ElCLib::Value(P2,H));
645     }
646     B.OpenXmax();B.OpenYmax();
647   }
648   else  {
649     B.Add(ElCLib::Value(P1,H));
650     if (Precision::IsNegativeInfinite(P2)) {
651       B.OpenXmin();B.OpenYmin();
652     }
653     else if (Precision::IsPositiveInfinite(P2)){
654       B.OpenXmax();B.OpenYmax();
655     }
656     else {
657       B.Add(ElCLib::Value(P2,H));
658       if (P1*P2<0) B.Add(ElCLib::Value(0.,H));
659     }
660   }
661   B.Enlarge(Tol);
662 }
663
664 void BndLib::Add( const gp_Cylinder& S,const Standard_Real UMin,
665                  const Standard_Real UMax,const Standard_Real VMin,
666                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
667
668   if (Precision::IsNegativeInfinite(VMin)) {
669     if (Precision::IsNegativeInfinite(VMax)) {
670       Standard_Failure::Raise("BndLib::bad parameter");
671     }
672     else if (Precision::IsPositiveInfinite(VMax)) {
673        OpenMinMax(S.Axis().Direction(),B);
674     }
675     else {
676       Compute(UMin,UMax,S.Radius(),S.Radius(),
677        gp_Pnt(S.XAxis().Direction().XYZ()),
678        gp_Pnt(S.YAxis().Direction().XYZ()),
679        gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
680       OpenMin(S.Axis().Direction(),B);
681     }
682   }
683   else if (Precision::IsPositiveInfinite(VMin)) {
684     if (Precision::IsNegativeInfinite(VMax)) {
685       OpenMinMax(S.Axis().Direction(),B);
686     }
687     else if (Precision::IsPositiveInfinite(VMax)) {
688       Standard_Failure::Raise("BndLib::bad parameter");
689     }
690     else {
691       Compute(UMin,UMax,S.Radius(),S.Radius(),
692        gp_Pnt(S.XAxis().Direction().XYZ()),
693        gp_Pnt(S.YAxis().Direction().XYZ()),
694        gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
695       OpenMax(S.Axis().Direction(),B);
696     }
697
698   }
699   else {
700     Compute(UMin,UMax,S.Radius(),S.Radius(),
701      gp_Pnt(S.XAxis().Direction().XYZ()),
702      gp_Pnt(S.YAxis().Direction().XYZ()),
703      gp_Pnt(S.Location().XYZ() + VMin*S.Axis().Direction().XYZ()),B);
704     if (Precision::IsNegativeInfinite(VMax)) {
705       OpenMin(S.Axis().Direction(),B);
706     }
707     else if (Precision::IsPositiveInfinite(VMax)) {
708       OpenMax(S.Axis().Direction(),B); 
709     }
710     else {
711       Compute(UMin,UMax,S.Radius(),S.Radius(),
712        gp_Pnt(S.XAxis().Direction().XYZ()),
713        gp_Pnt(S.YAxis().Direction().XYZ()),
714        gp_Pnt(S.Location().XYZ() + VMax*S.Axis().Direction().XYZ()),B);
715     }
716   }
717
718   B.Enlarge(Tol);
719
720 }
721
722 void BndLib::Add( const gp_Cylinder& S,const Standard_Real VMin,
723                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
724
725   BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
726 }
727
728 void BndLib::Add(const gp_Cone& S,const Standard_Real UMin,
729                  const Standard_Real UMax,const Standard_Real VMin,
730                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
731
732   Standard_Real R = S.RefRadius();
733   Standard_Real A = S.SemiAngle();
734   if (Precision::IsNegativeInfinite(VMin)) {
735     if (Precision::IsNegativeInfinite(VMax)) {
736       Standard_Failure::Raise("BndLib::bad parameter");
737     }
738     else if (Precision::IsPositiveInfinite(VMax)) {
739       gp_Dir D(Cos(A)*S.Axis().Direction());
740       OpenMinMax(D,B); 
741     }
742     else {
743       Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
744        gp_Pnt(S.XAxis().Direction().XYZ()),
745        gp_Pnt(S.YAxis().Direction().XYZ()),
746        gp_Pnt(S.Location().XYZ() + 
747        VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
748       gp_Dir D(Cos(A)*S.Axis().Direction());
749       OpenMin(D,B);     
750     }
751
752   }
753   else if (Precision::IsPositiveInfinite(VMin)) {
754     if (Precision::IsNegativeInfinite(VMax)) {
755       gp_Dir D(Cos(A)*S.Axis().Direction());
756       OpenMinMax(D,B);
757     }
758     else if (Precision::IsPositiveInfinite(VMax)) {
759       Standard_Failure::Raise("BndLib::bad parameter");
760     }
761     else {
762       Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
763        gp_Pnt(S.XAxis().Direction().XYZ()),
764        gp_Pnt(S.YAxis().Direction().XYZ()),
765        gp_Pnt(S.Location().XYZ() + 
766        VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
767       gp_Dir D(Cos(A)*S.Axis().Direction());
768       OpenMax(D,B);
769     }
770
771   }
772   else {
773     Compute(UMin,UMax,R+VMin*Sin(A),R+VMin*Sin(A),
774      gp_Pnt(S.XAxis().Direction().XYZ()),
775      gp_Pnt(S.YAxis().Direction().XYZ()),
776      gp_Pnt(S.Location().XYZ() + 
777      VMin*Cos(A)*S.Axis().Direction().XYZ()),B);
778     if (Precision::IsNegativeInfinite(VMax)) {
779       gp_Dir D(Cos(A)*S.Axis().Direction());
780       OpenMin(D,B);
781     }
782     else if (Precision::IsPositiveInfinite(VMax)) {
783       gp_Dir D(Cos(A)*S.Axis().Direction());
784       OpenMax(D,B);
785     }
786     else {
787       Compute(UMin,UMax,R+VMax*Sin(A),R+VMax*Sin(A),
788        gp_Pnt(S.XAxis().Direction().XYZ()),
789        gp_Pnt(S.YAxis().Direction().XYZ()),
790        gp_Pnt(S.Location().XYZ() + 
791        VMax*Cos(A)*S.Axis().Direction().XYZ()),B);
792     }
793   }
794
795
796   B.Enlarge(Tol);
797 }
798
799 void BndLib::Add( const gp_Cone& S,const Standard_Real VMin,
800                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
801
802   BndLib::Add(S,0.,2.*M_PI,VMin,VMax,Tol,B);
803 }
804
805 void BndLib::Add(const gp_Sphere& S,const Standard_Real UMin,
806                  const Standard_Real UMax,const Standard_Real VMin,
807                  const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
808
809 #if 0
810  Standard_Real Fi1;
811  Standard_Real Fi2;
812  if (VMax<VMin) {
813    Fi1 = VMax;
814    Fi2 = VMin;
815  }
816  else {
817    Fi1 = VMin;
818    Fi2 = VMax;
819  }
820  
821  if (-Fi1>Precision::Angular()) {
822    if (-Fi2>Precision::Angular()) {
823      Compute(UMin,UMax,S.Radius(),S.Radius(),
824         gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
825         S.Location(),B);
826      Compute(UMin,UMax,S.Radius(),S.Radius(),
827         gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
828      gp_Pnt(S.Location().XYZ()- S.Radius()*S.Position().Axis().Direction().XYZ()),B);
829    }
830    else {
831      Compute(UMin,UMax,S.Radius(),S.Radius(),
832      gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
833      gp_Pnt(S.Location().XYZ()+ S.Radius()*S.Position().Axis().Direction().XYZ()),B);
834      Compute(UMin,UMax,S.Radius(),S.Radius(),
835      gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
836      gp_Pnt(S.Location().XYZ()- S.Radius()*S.Position().Axis().Direction().XYZ()),B);
837    }
838  }
839  else {
840    Compute(UMin,UMax,S.Radius(),S.Radius(),
841       gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
842       S.Location(),B);
843    Compute(UMin,UMax,S.Radius(),S.Radius(),
844    gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),
845    gp_Pnt(S.Location().XYZ() +S.Radius()*S.Position().Axis().Direction().XYZ()),B);
846  } 
847  B.Enlarge(Tol);
848 #else
849  Standard_Real u,v,du,dv;
850  Standard_Integer iu,iv;
851  du = (UMax-UMin)/10;
852  dv = (VMax-VMin)/10;
853  Standard_Real COSV[11];
854  Standard_Real SINV[11];
855  for(iv=0,v=VMin;iv<=10;iv++) { 
856    COSV[iv]=cos(v);
857    SINV[iv]=sin(v);   
858    v+=dv;
859  }
860  for(u=UMin,iu=0; iu<=10 ; iu++) { 
861    Standard_Real Radiuscosu=S.Radius()*cos(u);
862    Standard_Real Radiussinu=S.Radius()*sin(u);
863    for(v=VMin,iv=0; iv<=10 ; iv++) { 
864      Standard_Real sinv=SINV[iv];
865      Standard_Real cosv=COSV[iv];
866      gp_XYZ M;
867      M.SetLinearForm (cosv*Radiuscosu, S.Position().XDirection().XYZ(),
868         cosv*Radiussinu, S.Position().YDirection().XYZ(),
869         S.Radius()*sinv,     S.Position().Direction().XYZ() ,
870         S.Position().Location().XYZ()  );
871      //-- static int t=0;
872      //-- cout<<"point p"<<++t<<" "<<M.X()<<" "<<M.Y()<<" "<<M.Z()<<endl;
873      B.Add(gp_Pnt(M));
874      v+=dv;
875    }
876    u+=du;
877  }
878  
879  Standard_Real Maxduv = Max(du,dv)*0.5;
880  Standard_Real Fleche = S.Radius() * (1 - cos(Maxduv));
881  B.Enlarge(Fleche);
882  B.Enlarge(10*Tol);
883 #endif
884 }
885
886 void BndLib::Add( const gp_Sphere& S,const Standard_Real Tol, Bnd_Box& B) {
887
888   Standard_Real R = S.Radius();
889   gp_XYZ O = S.Location().XYZ();
890   gp_XYZ Xd = S.XAxis().Direction().XYZ();
891   gp_XYZ Yd = S.YAxis().Direction().XYZ();
892   gp_XYZ Zd = S.Position().Axis().Direction().XYZ();
893   B.Add(gp_Pnt(O -R*Xd -R*Yd+ R*Zd)); 
894   B.Add(gp_Pnt(O -R*Xd +R*Yd+ R*Zd)); 
895   B.Add(gp_Pnt(O +R*Xd -R*Yd+ R*Zd)); 
896   B.Add(gp_Pnt(O +R*Xd +R*Yd+ R*Zd)); 
897   B.Add(gp_Pnt(O +R*Xd -R*Yd- R*Zd)); 
898   B.Add(gp_Pnt(O -R*Xd -R*Yd- R*Zd)); 
899   B.Add(gp_Pnt(O +R*Xd +R*Yd- R*Zd)); 
900   B.Add(gp_Pnt(O -R*Xd +R*Yd- R*Zd)); 
901   B.Enlarge(Tol);
902 }
903
904 void BndLib::Add(const gp_Torus& S,const Standard_Real UMin,
905    const Standard_Real UMax,const Standard_Real VMin,
906    const Standard_Real VMax,const Standard_Real Tol, Bnd_Box& B) {
907
908   Standard_Integer Fi1;
909   Standard_Integer Fi2;
910   if (VMax<VMin) {
911     Fi1 = (Standard_Integer )( VMax/(M_PI/4.));
912     Fi2 = (Standard_Integer )( VMin/(M_PI/4.));
913   }
914   else {
915     Fi1 = (Standard_Integer )( VMin/(M_PI/4.));
916     Fi2 = (Standard_Integer )( VMax/(M_PI/4.));
917   }
918   Fi2++;
919   
920   Standard_Real Ra = S.MajorRadius();
921   Standard_Real Ri = S.MinorRadius();
922
923   if (Fi2<Fi1) return;
924
925 #define SC 0.71
926 #define addP0    (Compute(UMin,UMax,Ra+Ri,Ra+Ri,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),S.Location(),B))
927 #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))
928 #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))
929 #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))
930 #define addP4    (Compute(UMin,UMax,Ra-Ri,Ra-Ri,gp_Pnt(S.XAxis().Direction().XYZ()),gp_Pnt(S.YAxis().Direction().XYZ()),S.Location(),B))
931 #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))
932 #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))
933 #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))
934   
935   switch (Fi1) {
936   case 0 : 
937     {
938       addP0;
939       if (Fi2 <= 0) break;
940     }
941   case 1 : 
942     {
943       addP1;
944       if (Fi2 <= 1) break;
945     }
946   case 2 :  
947     {
948       addP2;
949       if (Fi2 <= 2) break;
950     }
951   case 3 :  
952     {
953       addP3;
954       if (Fi2 <= 3) break;
955     }
956   case 4 :  
957     {
958       addP4;
959       if (Fi2 <= 4) break;
960     }
961   case 5 :  
962     {
963       addP5;
964       if (Fi2 <= 5) break;
965     }
966   case 6 :  
967     {
968       addP6;
969       if (Fi2 <= 6) break;
970     }
971   case 7 :  
972     {
973       addP7;
974       if (Fi2 <= 7) break;
975     }
976   case 8 :  
977   default :
978     {
979       addP0;
980       switch (Fi2) {
981       case 15 :  
982         addP7;
983       case 14 :  
984         addP6;
985       case 13 :  
986         addP5;
987       case 12 :  
988         addP4;
989       case 11 :  
990         addP3;
991       case 10 :  
992         addP2;
993       case 9 : 
994         addP1;
995       case 8 : 
996         break;
997       }    
998     }
999   }    
1000   B.Enlarge(Tol);
1001 }
1002
1003
1004 void BndLib::Add( const gp_Torus& S,const Standard_Real Tol, Bnd_Box& B) {
1005
1006   Standard_Real RMa = S.MajorRadius();
1007   Standard_Real Rmi = S.MinorRadius(); 
1008   gp_XYZ O = S.Location().XYZ();
1009   gp_XYZ Xd = S.XAxis().Direction().XYZ();
1010   gp_XYZ Yd = S.YAxis().Direction().XYZ();
1011   gp_XYZ Zd = S.Axis().Direction().XYZ();
1012   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd -(RMa+Rmi)*Yd+ Rmi*Zd)); 
1013   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd -(RMa+Rmi)*Yd- Rmi*Zd)); 
1014   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd -(RMa+Rmi)*Yd+ Rmi*Zd)); 
1015   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd -(RMa+Rmi)*Yd- Rmi*Zd)); 
1016   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd +(RMa+Rmi)*Yd+ Rmi*Zd)); 
1017   B.Add(gp_Pnt(O -(RMa+Rmi)*Xd +(RMa+Rmi)*Yd- Rmi*Zd)); 
1018   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd +(RMa+Rmi)*Yd+ Rmi*Zd)); 
1019   B.Add(gp_Pnt(O +(RMa+Rmi)*Xd +(RMa+Rmi)*Yd- Rmi*Zd)); 
1020   B.Enlarge(Tol);
1021 }
1022 //=======================================================================
1023 //function : ComputeBox
1024 //purpose  : 
1025 //=======================================================================
1026 Standard_Integer ComputeBox(const gp_Hypr& aHypr, 
1027                             const Standard_Real aT1, 
1028                             const Standard_Real aT2, 
1029                             Bnd_Box& aBox)
1030 {
1031   Standard_Integer i, iErr;
1032   Standard_Real aRmaj, aRmin, aA, aB, aABP, aBAM, aT3, aCf, aEps;
1033   gp_Pnt aP1, aP2, aP3, aP0;
1034   //
1035   //
1036   aP1=ElCLib::Value(aT1, aHypr);
1037   aP2=ElCLib::Value(aT2, aHypr);
1038   //
1039   aBox.Add(aP1);
1040   aBox.Add(aP2);
1041   //
1042   if (aT1*aT2<0.) {
1043     aP0=ElCLib::Value(0., aHypr);
1044     aBox.Add(aP0);
1045   }
1046   //
1047   aEps=Epsilon(1.);
1048   iErr=1;
1049   //
1050   const gp_Ax2& aPos=aHypr.Position();
1051   const gp_XYZ& aXDir = aPos.XDirection().XYZ();
1052   const gp_XYZ& aYDir = aPos.YDirection().XYZ();
1053   aRmaj=aHypr.MajorRadius();
1054   aRmin=aHypr.MinorRadius();
1055   //
1056   aT3=0;
1057   for (i=1; i<=3; ++i) {
1058     aA=aRmin*aYDir.Coord(i);
1059     aB=aRmaj*aXDir.Coord(i);
1060     //
1061     aABP=aA+aB;
1062     aBAM=aB-aA;
1063     //
1064     aABP=fabs(aABP);
1065     aBAM=fabs(aBAM);
1066     //
1067     if (aABP<aEps || aBAM<aEps) {
1068       continue;
1069     }
1070     //
1071     aCf=aBAM/aABP;
1072     aT3=log(sqrt(aCf));
1073     //
1074     if (aT3<aT1 || aT3>aT2) {
1075       continue;
1076     }
1077     iErr=0;
1078     break;
1079   }
1080   //
1081   if (iErr) {
1082     return iErr;
1083   }
1084   //
1085   aP3=ElCLib::Value(aT3, aHypr);
1086   aBox.Add(aP3);
1087   //
1088   return iErr;
1089 }