0023178: Intersection of cylinders fails to produce results
[occt.git] / src / Bnd / Bnd_Box.cxx
1 // Created on: 1991-03-08
2 // Created by: Christophe MARION
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Bnd_Box.hxx>
18 #include <gp_Dir.hxx>
19 #include <gp_Lin.hxx>
20 #include <gp_Pln.hxx>
21 #include <gp_Pnt.hxx>
22 #include <gp_Trsf.hxx>
23 #include <Standard_ConstructionError.hxx>
24
25 // set the flag to one
26 #define ClearVoidFlag() ( Flags &= ~VoidMask )
27
28 #include <Standard_Stream.hxx>
29 #include <gp.hxx>
30 // #include <Precision.hxx>
31 #define Bnd_Precision_Infinite 1e+100
32
33 //=======================================================================
34 //function : Bnd_Box
35 //purpose  : 
36 //=======================================================================
37
38 Bnd_Box::Bnd_Box()
39      : Xmin(0.), Xmax(0.), Ymin(0.), Ymax(0.),  Zmin(0.), Zmax(0.), Gap(0.)
40 {
41   SetVoid();
42 }
43
44 //=======================================================================
45 //function : Set
46 //purpose  : 
47 //=======================================================================
48
49 void Bnd_Box::Set(const gp_Pnt& P)
50 {
51   SetVoid();
52   Add(P);
53 }
54
55 //=======================================================================
56 //function : Set
57 //purpose  : 
58 //=======================================================================
59
60 void Bnd_Box::Set(const gp_Pnt& P, const gp_Dir& D)
61 {
62   SetVoid();
63   Add(P,D);
64 }
65
66
67 //=======================================================================
68 //function : Update
69 //purpose  : 
70 //=======================================================================
71
72 void Bnd_Box::Update (const Standard_Real x,
73                       const Standard_Real y, 
74                       const Standard_Real z, 
75                       const Standard_Real X,
76                       const Standard_Real Y, 
77                       const Standard_Real Z)
78 {
79   if (IsVoid())
80   {
81     Xmin = x;
82     Ymin = y;
83     Zmin = z;
84     Xmax = X;
85     Ymax = Y;
86     Zmax = Z;
87     ClearVoidFlag();
88   }
89   else {
90     if (!IsOpenXmin() && (x < Xmin)) Xmin = x;
91     if (!IsOpenXmax() && (X > Xmax)) Xmax = X;
92     if (!IsOpenYmin() && (y < Ymin)) Ymin = y;
93     if (!IsOpenYmax() && (Y > Ymax)) Ymax = Y;
94     if (!IsOpenZmin() && (z < Zmin)) Zmin = z;
95     if (!IsOpenZmax() && (Z > Zmax)) Zmax = Z;
96   }
97 }
98
99 //=======================================================================
100 //function : Update
101 //purpose  : 
102 //=======================================================================
103
104 void Bnd_Box::Update (const Standard_Real X,
105                       const Standard_Real Y,
106                       const Standard_Real Z)
107 {
108   if (IsVoid())
109   {
110     Xmin = X;
111     Ymin = Y;
112     Zmin = Z;
113     Xmax = X;
114     Ymax = Y;
115     Zmax = Z;
116     ClearVoidFlag();
117   }
118   else {
119     if      (!IsOpenXmin() && (X < Xmin)) Xmin = X;
120     else if (!IsOpenXmax() && (X > Xmax)) Xmax = X;
121     if      (!IsOpenYmin() && (Y < Ymin)) Ymin = Y;
122     else if (!IsOpenYmax() && (Y > Ymax)) Ymax = Y;
123     if      (!IsOpenZmin() && (Z < Zmin)) Zmin = Z;
124     else if (!IsOpenZmax() && (Z > Zmax)) Zmax = Z;
125   }
126 }
127
128 //=======================================================================
129 //function : GetGap
130 //purpose  : 
131 //=======================================================================
132
133 Standard_Real Bnd_Box::GetGap () const
134 {
135   return Gap;
136 }
137
138 //=======================================================================
139 //function : SetGap
140 //purpose  : 
141 //=======================================================================
142
143 void Bnd_Box::SetGap (const Standard_Real Tol)
144 {
145   Gap = Tol;
146 }
147
148 //=======================================================================
149 //function : Enlarge
150 //purpose  : 
151 //=======================================================================
152
153 void Bnd_Box::Enlarge (const Standard_Real Tol)
154 {
155   Gap=Max(Gap, Abs(Tol));
156 }
157
158 //=======================================================================
159 //function : Get
160 //purpose  : 
161 //=======================================================================
162
163 void Bnd_Box::Get (Standard_Real& theXmin,
164                    Standard_Real& theYmin,
165                    Standard_Real& theZmin,
166                    Standard_Real& theXmax,
167                    Standard_Real& theYmax,
168                    Standard_Real& theZmax) const
169 {
170   if (IsVoid())
171   {
172     Standard_ConstructionError::Raise ("Bnd_Box is void");
173   }
174
175   if (IsOpenXmin()) theXmin = -Bnd_Precision_Infinite;
176   else              theXmin = Xmin - Gap;
177   if (IsOpenXmax()) theXmax = Bnd_Precision_Infinite;
178   else              theXmax = Xmax + Gap;
179   if (IsOpenYmin()) theYmin = -Bnd_Precision_Infinite;
180   else              theYmin = Ymin - Gap;
181   if (IsOpenYmax()) theYmax = Bnd_Precision_Infinite;
182   else              theYmax = Ymax + Gap;
183   if (IsOpenZmin()) theZmin = -Bnd_Precision_Infinite;
184   else              theZmin = Zmin - Gap;
185   if (IsOpenZmax()) theZmax = Bnd_Precision_Infinite;
186   else              theZmax = Zmax + Gap;
187 }
188
189 //=======================================================================
190 //function : CornerMin
191 //purpose  :
192 //=======================================================================
193
194 gp_Pnt Bnd_Box::CornerMin() const
195 {
196   gp_Pnt aCornerMin;
197   if (IsVoid())
198   {
199     Standard_ConstructionError::Raise ("Bnd_Box is void");
200     return aCornerMin;
201   }
202   if (IsOpenXmin()) aCornerMin.SetX (-Bnd_Precision_Infinite);
203   else              aCornerMin.SetX (Xmin - Gap);
204   if (IsOpenYmin()) aCornerMin.SetY (-Bnd_Precision_Infinite);
205   else              aCornerMin.SetY (Ymin - Gap);
206   if (IsOpenZmin()) aCornerMin.SetZ (-Bnd_Precision_Infinite);
207   else              aCornerMin.SetZ (Zmin - Gap);
208   return aCornerMin;
209 }
210
211 //=======================================================================
212 //function : CornerMax
213 //purpose  :
214 //=======================================================================
215
216 gp_Pnt Bnd_Box::CornerMax() const
217 {
218   gp_Pnt aCornerMax;
219   if (IsVoid())
220   {
221     Standard_ConstructionError::Raise ("Bnd_Box is void");
222     return aCornerMax;
223   }
224   if (IsOpenXmax()) aCornerMax.SetX (Bnd_Precision_Infinite);
225   else              aCornerMax.SetX (Xmax + Gap);
226   if (IsOpenYmin()) aCornerMax.SetY (Bnd_Precision_Infinite);
227   else              aCornerMax.SetY (Ymax + Gap);
228   if (IsOpenZmin()) aCornerMax.SetZ (Bnd_Precision_Infinite);
229   else              aCornerMax.SetZ (Zmax + Gap);
230   return aCornerMax;
231 }
232
233 //=======================================================================
234 //function : IsXThin
235 //purpose  : 
236 //=======================================================================
237
238 Standard_Boolean Bnd_Box::IsXThin (const Standard_Real tol) const
239 {
240   if (IsWhole())       return Standard_False;
241   if (IsVoid())        return Standard_True;
242   if (IsOpenXmin())    return Standard_False;
243   if (IsOpenXmax())    return Standard_False;
244   if (Xmax-Xmin < tol) return Standard_True;
245   return Standard_False;
246 }
247
248 //=======================================================================
249 //function : IsYThin
250 //purpose  : 
251 //=======================================================================
252
253 Standard_Boolean Bnd_Box::IsYThin (const Standard_Real tol) const
254 {
255   if (IsWhole())       return Standard_False;
256   if (IsVoid())        return Standard_True;
257   if (IsOpenYmin())    return Standard_False;
258   if (IsOpenYmax())    return Standard_False;
259   if (Ymax-Ymin < tol) return Standard_True;
260   return Standard_False;
261 }
262
263 //=======================================================================
264 //function : IsZThin
265 //purpose  : 
266 //=======================================================================
267
268 Standard_Boolean Bnd_Box::IsZThin (const Standard_Real tol) const
269 {
270   if (IsWhole())       return Standard_False;
271   if (IsVoid())        return Standard_True;
272   if (IsOpenZmin())    return Standard_False;
273   if (IsOpenZmax())    return Standard_False;
274   if (Zmax-Zmin < tol) return Standard_True;
275   return Standard_False;
276 }
277
278 //=======================================================================
279 //function : IsThin
280 //purpose  : 
281 //=======================================================================
282
283 Standard_Boolean Bnd_Box::IsThin (const Standard_Real tol) const
284 {
285   if (!IsXThin(tol)) return Standard_False;
286   if (!IsYThin(tol)) return Standard_False;
287   if (!IsZThin(tol)) return Standard_False;
288   return Standard_True;
289 }
290
291 //=======================================================================
292 //function : Transformed
293 //purpose  : 
294 //=======================================================================
295
296 Bnd_Box Bnd_Box::Transformed (const gp_Trsf& T) const
297 {
298   gp_TrsfForm F = T.Form();
299   Bnd_Box newb(*this);
300   if ( IsVoid() ) return newb;
301
302   if      (F == gp_Identity) {}
303   else if (F == gp_Translation) {
304     Standard_Real DX,DY,DZ;
305     (T.TranslationPart()).Coord(DX,DY,DZ);
306     if (!IsOpenXmin()) newb.Xmin += DX;
307     if (!IsOpenXmax()) newb.Xmax += DX;
308     if (!IsOpenYmin()) newb.Ymin += DY;
309     if (!IsOpenYmax()) newb.Ymax += DY;
310     if (!IsOpenZmin()) newb.Zmin += DZ;
311     if (!IsOpenZmax()) newb.Zmax += DZ;
312   }
313   else {
314     gp_Pnt P[8];
315     Standard_Boolean Vertex[8];
316     Standard_Integer i;
317     for (i=0;i<8;i++) Vertex[i] = Standard_True;
318     gp_Dir D[6];
319 //    Standard_Integer vertices = 0;
320     Standard_Integer directions = 0;
321
322     if (IsOpenXmin())
323     {
324       directions++;
325       D[directions-1].SetCoord(-1., 0., 0.);
326       Vertex[0] = Vertex[2] = Vertex[4] = Vertex[6] = Standard_False;
327     }
328     if (IsOpenXmax())
329     {
330       directions++;
331       D[directions-1].SetCoord( 1., 0., 0.);
332       Vertex[1] = Vertex[3] = Vertex[5] = Vertex[7] = Standard_False;
333     }
334     if (IsOpenYmin())
335     {
336       directions++;
337       D[directions-1].SetCoord( 0.,-1., 0.);
338       Vertex[0] = Vertex[1] = Vertex[4] = Vertex[5] = Standard_False;
339     }
340     if (IsOpenYmax())
341     {
342       directions++;
343       D[directions-1].SetCoord( 0., 1., 0.);
344       Vertex[2] = Vertex[3] = Vertex[6] = Vertex[7] = Standard_False;
345     }
346     if (IsOpenZmin())
347     {
348       directions++;
349       D[directions-1].SetCoord( 0., 0.,-1.);
350       Vertex[0] = Vertex[1] = Vertex[2] = Vertex[3] = Standard_False;
351     }
352     if (IsOpenZmax())
353     {
354       directions++;
355       D[directions-1].SetCoord( 0., 0., 1.);
356       Vertex[4] = Vertex[5] = Vertex[6] = Vertex[7] = Standard_False;
357     }
358
359     newb.SetVoid();
360     for (i=0;i<directions;i++) {
361       D[i].Transform(T);
362       newb.Add(D[i]);
363     }
364     P[0].SetCoord(Xmin,Ymin,Zmin);
365     P[1].SetCoord(Xmax,Ymin,Zmin);
366     P[2].SetCoord(Xmin,Ymax,Zmin);
367     P[3].SetCoord(Xmax,Ymax,Zmin);
368     P[4].SetCoord(Xmin,Ymin,Zmax);
369     P[5].SetCoord(Xmax,Ymin,Zmax);
370     P[6].SetCoord(Xmin,Ymax,Zmax);
371     P[7].SetCoord(Xmax,Ymax,Zmax);
372     for (i=0;i<8;i++) {
373       if (Vertex[i]) {
374         P[i].Transform(T);
375         newb.Add(P[i]);
376       }
377     }
378     newb.Gap=Gap;
379   }
380   return newb;
381 }
382
383 //=======================================================================
384 //function : Add
385 //purpose  : 
386 //=======================================================================
387
388 void Bnd_Box::Add (const Bnd_Box& Other)
389 {
390   if (IsWhole()) return;
391   else if (Other.IsVoid()) return; 
392   else if (Other.IsWhole()) SetWhole();
393   else if (IsVoid()) (*this) = Other;
394   else
395   {
396     if ( ! IsOpenXmin() )
397     {
398       if (Other.IsOpenXmin()) OpenXmin();
399       else if (Xmin > Other.Xmin) Xmin = Other.Xmin;
400     }
401     if ( ! IsOpenXmax() )
402     {
403       if (Other.IsOpenXmax()) OpenXmax();
404       else if (Xmax < Other.Xmax) Xmax = Other.Xmax;
405     }
406     if ( ! IsOpenYmin() )
407     {
408       if (Other.IsOpenYmin()) OpenYmin();
409       else if (Ymin > Other.Ymin) Ymin = Other.Ymin;
410     }
411     if ( ! IsOpenYmax() )
412     {
413       if (Other.IsOpenYmax()) OpenYmax();
414       else if (Ymax < Other.Ymax) Ymax = Other.Ymax;
415     }
416     if ( ! IsOpenZmin() )
417     {
418       if (Other.IsOpenZmin()) OpenZmin();
419       else if (Zmin > Other.Zmin) Zmin = Other.Zmin;
420     }
421     if ( ! IsOpenZmax() )
422     {
423       if (Other.IsOpenZmax()) OpenZmax();
424       else if (Zmax < Other.Zmax) Zmax = Other.Zmax;
425     }
426     Gap = Max (Gap, Other.Gap);
427   }
428 }
429
430 //=======================================================================
431 //function : Add
432 //purpose  : 
433 //=======================================================================
434
435 void Bnd_Box::Add (const gp_Pnt& P)
436 {
437   Standard_Real X,Y,Z;
438   P.Coord(X,Y,Z);
439   Update(X,Y,Z);
440 }
441
442 //=======================================================================
443 //function : Add
444 //purpose  : 
445 //=======================================================================
446
447 void Bnd_Box::Add (const gp_Pnt& P, const gp_Dir& D)
448 {
449   Add(P);
450   Add(D);
451 }
452
453
454 //=======================================================================
455 //function : Add
456 //purpose  : 
457 //=======================================================================
458
459 void Bnd_Box::Add (const gp_Dir& D)
460 {
461   Standard_Real DX,DY,DZ;
462   D.Coord(DX,DY,DZ);
463
464   if (DX < -RealEpsilon()) 
465     OpenXmin();
466   else if (DX > RealEpsilon()) 
467     OpenXmax();
468
469   if (DY < -RealEpsilon())
470     OpenYmin();
471   else if (DY > RealEpsilon())
472     OpenYmax();
473
474   if (DZ < -RealEpsilon())
475     OpenZmin();
476   else if (DZ > RealEpsilon())
477     OpenZmax();
478 }
479
480 //=======================================================================
481 //function : IsOut
482 //purpose  : 
483 //=======================================================================
484
485 Standard_Boolean Bnd_Box::IsOut (const gp_Pnt& P) const
486 {
487   if        (IsWhole())  return Standard_False;
488   else if   (IsVoid())   return Standard_True;
489   else {
490     Standard_Real X,Y,Z;
491     P.Coord(X,Y,Z);
492     if      (!IsOpenXmin() && (X < (Xmin-Gap))) return Standard_True;
493     else if (!IsOpenXmax() && (X > (Xmax+Gap))) return Standard_True;
494     else if (!IsOpenYmin() && (Y < (Ymin-Gap))) return Standard_True;
495     else if (!IsOpenYmax() && (Y > (Ymax+Gap))) return Standard_True;
496     else if (!IsOpenZmin() && (Z < (Zmin-Gap))) return Standard_True;
497     else if (!IsOpenZmax() && (Z > (Zmax+Gap))) return Standard_True;
498     else return Standard_False;
499   }
500 }
501
502
503 //=======================================================================
504 //function : IsOut
505 //purpose  : 
506 //=======================================================================
507
508 Standard_Boolean Bnd_Box::IsOut (const gp_Pln& P) const
509 {
510   if        (IsWhole())  return Standard_False;
511   else if   (IsVoid())   return Standard_True;
512   else {
513     Standard_Real A,B,C,D;
514     P.Coefficients (A, B ,C ,D);
515     Standard_Real d = A * (Xmin-Gap) + B * (Ymin-Gap) + C * (Zmin-Gap) + D;
516 //    Standard_Boolean plus = d > 0;
517     Standard_Integer plus = d > 0;
518     if (plus != ((A*(Xmin-Gap) + B*(Ymin-Gap) + C*(Zmax+Gap) + D) > 0))
519       return Standard_False;
520     if (plus != ((A*(Xmin-Gap) + B*(Ymax+Gap) + C*(Zmin-Gap) + D) > 0))
521       return Standard_False;
522     if (plus != ((A*(Xmin-Gap) + B*(Ymax+Gap) + C*(Zmax+Gap) + D) > 0))
523       return Standard_False;
524     if (plus != ((A*(Xmax+Gap) + B*(Ymin-Gap) + C*(Zmin-Gap) + D) > 0))
525       return Standard_False;
526     if (plus != ((A*(Xmax+Gap) + B*(Ymin-Gap) + C*(Zmax+Gap) + D) > 0))
527       return Standard_False;
528     if (plus != ((A*(Xmax+Gap) + B*(Ymax+Gap) + C*(Zmin-Gap) + D) > 0))
529       return Standard_False;
530     if (plus != ((A*(Xmax+Gap) + B*(Ymax+Gap) + C*(Zmax+Gap) + D) > 0))
531       return Standard_False;
532     else return Standard_True;
533   }
534 }
535
536 //=======================================================================
537 //function : IsOut
538 //purpose  : 
539 //=======================================================================
540
541 Standard_Boolean Bnd_Box::IsOut (const gp_Lin& L) const
542 {
543   if        (IsWhole())  return Standard_False;
544   else if   (IsVoid())   return Standard_True;
545   else {
546     Standard_Real xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin, zmax;
547     Standard_Real parmin, parmax, par1, par2;
548     Standard_Boolean xToSet, yToSet;
549     Standard_Real myXmin, myYmin, myZmin, myXmax, myYmax, myZmax;
550     Get (myXmin, myYmin, myZmin, myXmax, myYmax, myZmax);
551
552     if (Abs(L.Direction().XYZ().X())>0.) {
553       par1=(myXmin-L.Location().XYZ().X())/L.Direction().XYZ().X();
554       par2=(myXmax-L.Location().XYZ().X())/L.Direction().XYZ().X();
555       parmin=Min(par1, par2);
556       parmax=Max(par1, par2);
557       xToSet=Standard_True;
558     }
559     else {
560       if (L.Location().XYZ().X()<myXmin || myXmax<L.Location().XYZ().X()) {
561         return Standard_True;
562       }
563       xmin=L.Location().XYZ().X();
564       xmax=L.Location().XYZ().X();
565       parmin=-Bnd_Precision_Infinite;
566       parmax=Bnd_Precision_Infinite;
567       xToSet=Standard_False;
568     }
569
570     if (Abs(L.Direction().XYZ().Y())>0.) {
571       par1=(myYmin-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
572       par2=(myYmax-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
573       //=================DET change 06/03/01====================
574       if(parmax < Min(par1,par2) || parmin > Max(par1,par2))
575         return Standard_True;
576       //========================================================
577       parmin=Max(parmin, Min(par1,par2));
578       parmax=Min(parmax, Max(par1,par2));
579       yToSet=Standard_True;
580     }
581     else {
582       if (L.Location().XYZ().Y()<myYmin || myYmax<L.Location().XYZ().Y()) {
583         return Standard_True;
584       }
585       ymin=L.Location().XYZ().Y();
586       ymax=L.Location().XYZ().Y();
587       yToSet=Standard_False;
588     }
589
590     if (Abs(L.Direction().XYZ().Z())>0.) {
591       par1=(myZmin-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
592       par2=(myZmax-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
593       //=================DET change 06/03/01====================
594       if(parmax < Min(par1,par2) || parmin > Max(par1,par2))
595         return Standard_True;
596       //========================================================
597       parmin=Max(parmin, Min(par1,par2));
598       parmax=Min(parmax, Max(par1,par2));
599       par1=L.Location().XYZ().Z()+parmin*L.Direction().XYZ().Z();
600       par2=L.Location().XYZ().Z()+parmax*L.Direction().XYZ().Z();
601       zmin=Min(par1, par2);
602       zmax=Max(par1, par2);
603     }
604     else {
605       if (L.Location().XYZ().Z()<myZmin || myZmax<L.Location().XYZ().Z())
606         return Standard_True;
607       zmin=L.Location().XYZ().Z();
608       zmax=L.Location().XYZ().Z();
609     }
610     if (zmax<myZmin || myZmax<zmin) return Standard_True;
611
612     if (xToSet) {
613       par1=L.Location().XYZ().X()+parmin*L.Direction().XYZ().X();
614       par2=L.Location().XYZ().X()+parmax*L.Direction().XYZ().X();
615       xmin=Min(par1, par2);
616       xmax=Max(par1, par2);
617     }
618     if (xmax<myXmin || myXmax<xmin) return Standard_True;
619
620     if (yToSet) {
621       par1=L.Location().XYZ().Y()+parmin*L.Direction().XYZ().Y();
622       par2=L.Location().XYZ().Y()+parmax*L.Direction().XYZ().Y();
623       ymin=Min(par1, par2);
624       ymax=Max(par1, par2);
625     }
626     if (ymax<myYmin || myYmax<ymin) return Standard_True;
627   }
628   return Standard_False;
629 }
630
631 //=======================================================================
632 //function : IsOut
633 //purpose  : 
634 //=======================================================================
635
636 Standard_Boolean Bnd_Box::IsOut (const Bnd_Box& Other) const
637
638   //modified by NIZNHY-PKV Fri Jul 08 11:03:43 2011f
639   if (!Flags && !Other.Flags) {
640     Standard_Boolean bRet;
641     Standard_Real delta;
642     //
643     delta = Other.Gap + Gap;
644     bRet=((Xmin - Other.Xmax > delta) ||
645           (Other.Xmin - Xmax > delta) ||
646           (Ymin - Other.Ymax > delta) ||
647           (Other.Ymin - Ymax > delta) ||
648           (Zmin - Other.Zmax > delta) ||
649           (Other.Zmin - Zmax > delta));
650     return bRet;
651   }
652   //modified by NIZNHY-PKV Fri Jul 08 11:03:46 2011t
653   if   (IsVoid())         return Standard_True;
654   if   (Other.IsVoid())   return Standard_True;
655   if   (IsWhole())        return Standard_False;
656   if   (Other.IsWhole())  return Standard_False;
657
658   Standard_Real delta = Other.Gap + Gap;
659
660   if (!IsOpenXmin() && !Other.IsOpenXmax())
661     if (Xmin - Other.Xmax > delta) return Standard_True;
662   if (!IsOpenXmax() && !Other.IsOpenXmin())
663     if (Other.Xmin - Xmax > delta) return Standard_True;
664   
665   if (!IsOpenYmin() && !Other.IsOpenYmax())
666     if (Ymin - Other.Ymax > delta) return Standard_True;
667   if (!IsOpenYmax() && !Other.IsOpenYmin())
668     if (Other.Ymin - Ymax > delta) return Standard_True;
669   
670   if (!IsOpenZmin() && !Other.IsOpenZmax())
671     if (Zmin - Other.Zmax > delta) return Standard_True;
672   if (!IsOpenZmax() && !Other.IsOpenZmin())
673     if (Other.Zmin - Zmax > delta) return Standard_True;
674
675   return Standard_False;
676 }
677
678 //=======================================================================
679 //function : IsOut
680 //purpose  : 
681 //=======================================================================
682
683 Standard_Boolean Bnd_Box::IsOut (const Bnd_Box& Other, 
684                                  const gp_Trsf& T) const
685 {
686   return IsOut(Other.Transformed(T));
687 }
688
689 //=======================================================================
690 //function : IsOut
691 //purpose  : 
692 //=======================================================================
693
694 Standard_Boolean Bnd_Box::IsOut (const gp_Trsf& T1,
695                                  const Bnd_Box& Other, 
696                                  const gp_Trsf& T2) const
697 {
698   return Transformed(T1).IsOut(Other.Transformed(T2));
699 }
700
701
702 //=======================================================================
703 //function : IsSegmentOut
704 //purpose  : 
705 //=======================================================================
706
707 static Standard_Boolean IsSegmentOut(Standard_Real x1,Standard_Real y1,
708                                      Standard_Real x2,Standard_Real y2,
709                                      Standard_Real xs1,Standard_Real ys1,
710                                      Standard_Real xs2,Standard_Real ys2)
711 {
712   Standard_Real eps = RealSmall();
713   Standard_Real xsmin = Min (xs1, xs2);
714   Standard_Real xsmax = Max (xs1, xs2);
715   Standard_Real ysmin = Min (ys1, ys2);
716   Standard_Real ysmax = Max (ys1, ys2);
717
718   if (ysmax-ysmin < eps && (y1-ys1 < eps && ys1-y2 < eps) &&
719       ((xsmin-x1 < eps && x1-xsmax < eps) || 
720        (xsmin-x2 < eps && x2-xsmax < eps) || 
721        (x1-xs1 < eps && xs1-x2 < eps)))
722     return Standard_False;
723   if (xsmax-xsmin < eps && (x1-xs1 < eps && xs1-x2 < eps) &&
724       ((ysmin-y1 < eps && y1-ysmax < eps) ||
725        (ysmin-y2 < eps && y2-ysmax < eps) ||
726        (y1-ys1 < eps && ys1-y2 < eps)))
727     return Standard_False;
728
729   if ((xs1 < x1 && xs2 < x1) || (xs1 > x2 && xs2 > x2) ||
730       (ys1 < y1 && ys2 < y1) || (ys1 > y2 && ys2 > y2) )
731     return Standard_True;
732
733   if (Abs(xs2-xs1) > eps)
734   {
735     Standard_Real ya = ( Min(x1, x2) - xs1 ) * ( ys2 - ys1 ) / ( xs2 - xs1 ) + ys1;
736     Standard_Real yb = ( Max(x1, x2) - xs1 ) * ( ys2 - ys1 ) / ( xs2 - xs1 ) + ys1;
737     if ( (ya < y1 && yb < y1) || (ya > y2 && yb > y2) ) return Standard_True;
738   }
739   else if (Abs(ys2-ys1) > eps)
740   {
741     Standard_Real xa = ( Min(y1, y2) - ys1 ) * ( xs2 - xs1 ) / ( ys2 - ys1 ) + xs1;
742     Standard_Real xb = ( Max(y1, y2) - ys1 ) * ( xs2 - xs1 ) / ( ys2 - ys1 ) + xs1;
743     if ( (xa < x1 && xb < x1) || (xa > x2 && xb > x2) ) return Standard_True;
744   }
745   else 
746     return Standard_True;
747
748   return Standard_False;
749 }
750
751 Standard_Boolean Bnd_Box::IsOut(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Dir& D) const
752 {
753
754   if        (IsWhole())  return Standard_False;
755   else if   (IsVoid())   return Standard_True;
756
757   Standard_Real eps = RealSmall();
758   Standard_Real myXmin, myYmin, myZmin, myXmax, myYmax, myZmax;
759   Get (myXmin, myYmin, myZmin, myXmax, myYmax, myZmax);
760
761   if(Abs(D.X()) < eps && Abs(D.Y()) < eps)
762     return IsSegmentOut(myXmin, myYmin, myXmax, myYmax, P1.X(), P1.Y(), P2.X(), P2.Y());
763
764   if(Abs(D.X()) < eps && Abs(D.Z()) < eps)
765     return IsSegmentOut(myXmin, myZmin, myXmax, myZmax, P1.X(), P1.Z(), P2.X(), P2.Z());
766
767   if(Abs(D.Y()) < eps && Abs(D.Z()) < eps)
768     return IsSegmentOut(myYmin, myZmin, myYmax, myZmax, P1.Y(), P1.Z(), P2.Y(), P2.Z());
769
770   if(Abs(D.X()) < eps)
771   {
772     if(!IsSegmentOut(myXmin, myZmin, myXmax, myZmax,
773                      P1.X(),(myYmin-P1.Y())*D.Z()/D.Y()+P1.Z(), 
774                      P2.X(),(myYmin-P2.Y())*D.Z()/D.Y()+P2.Z()))
775       return Standard_False;
776
777     if(!IsSegmentOut(myXmin, myZmin, myXmax, myZmax,
778                      P1.X(),(myYmax-P1.Y())*D.Z()/D.Y()+P1.Z(), 
779                      P2.X(),(myYmax-P2.Y())*D.Z()/D.Y()+P2.Z()))
780       return Standard_False;
781
782     if(!IsSegmentOut(myXmin, myYmin, myXmax, myYmax,
783                      P1.X(),(myZmin-P1.Z())*D.Y()/D.Z()+P1.Y(), 
784                      P2.X(),(myZmin-P2.Z())*D.Y()/D.Z()+P2.Y()))
785       return Standard_False;
786
787     if(!IsSegmentOut(myXmin, myYmin, myXmax, myYmax,
788                      P1.X(),(myZmax-P1.Z())*D.Y()/D.Z()+P1.Y(), 
789                      P2.X(),(myZmax-P2.Z())*D.Y()/D.Z()+P2.Y()))
790       return Standard_False;
791
792     return Standard_True;
793   }//if(D.X() == 0) 
794
795   if(Abs(D.Y()) < eps)
796   {
797     if(!IsSegmentOut(myYmin, myZmin, myYmax, myZmax,
798                      P1.Y(),(myXmin-P1.X())*D.Z()/D.X()+P1.Z(), 
799                      P2.Y(),(myXmin-P2.X())*D.Z()/D.X()+P2.Z()))
800       return Standard_False;
801
802     if(!IsSegmentOut(myYmin, myZmin, myYmax, myZmax,
803                      P1.Y(),(myXmax-P1.X())*D.Z()/D.X()+P1.Z(), 
804                      P2.Y(),(myXmax-P2.X())*D.Z()/D.X()+P2.Z()))
805       return Standard_False;
806
807     if(!IsSegmentOut(myYmin, myXmin, myYmax, myXmax,
808                      P1.Y(),(myZmin-P1.Z())*D.X()/D.Z()+P1.X(), 
809                      P2.Y(),(myZmin-P2.Z())*D.X()/D.Z()+P2.X()))
810       return Standard_False;
811
812     if(!IsSegmentOut(myYmin, myXmin, myYmax, myXmax,
813                      P1.Y(),(myZmax-P1.Z())*D.X()/D.Z()+P1.X(), 
814                      P2.Y(),(myZmax-P2.Z())*D.X()/D.Z()+P2.X()))
815       return Standard_False;
816
817     return Standard_True;
818   }//if(D.Y() == 0) 
819
820   if(Abs(D.Z()) < eps)
821   {
822     if(!IsSegmentOut(myZmin, myXmin, myZmax, myXmax,
823                      P1.Z(),(myYmax-P1.Y())*D.X()/D.Y()+P1.X(), 
824                      P2.Z(),(myYmax-P2.Y())*D.X()/D.Y()+P2.X()))
825       return Standard_False;
826
827     if(!IsSegmentOut(myZmin, myXmin, myZmax, myXmax,
828                      P1.Z(),(myYmin-P1.Y())*D.X()/D.Y()+P1.X(), 
829                      P2.Z(),(myYmin-P2.Y())*D.X()/D.Y()+P2.X()))
830       return Standard_False;
831
832     if(!IsSegmentOut(myZmin, myYmin, myZmax, myYmax,
833                      P1.Z(),(myXmax-P1.X())*D.Y()/D.X()+P1.Y(), 
834                      P2.Z(),(myXmax-P2.X())*D.Y()/D.X()+P2.Y()))
835       return Standard_False;
836
837     if(!IsSegmentOut(myZmin, myYmin, myZmax, myYmax,
838                      P1.Z(),(myXmin-P1.X())*D.Y()/D.X()+P1.Y(), 
839                      P2.Z(),(myXmin-P2.X())*D.Y()/D.X()+P2.Y()))
840       return Standard_False;
841
842     return Standard_True;
843   }//if(D.Z() == 0) 
844
845   if(!IsSegmentOut(myXmin,myZmin,myXmax,myZmax,
846                    (myYmin - P1.Y())/D.Y()*D.X() + P1.X(),
847                    (myYmin - P1.Y())/D.Y()*D.Z() + P1.Z(),
848                    (myYmin - P2.Y())/D.Y()*D.X() + P2.X(),
849                    (myYmin - P2.Y())/D.Y()*D.Z() + P2.Z()))
850     return Standard_False;
851
852   if(!IsSegmentOut(myXmin,myZmin,myXmax,myZmax,
853                    (myYmax - P1.Y())/D.Y()*D.X() + P1.X(),
854                    (myYmax - P1.Y())/D.Y()*D.Z() + P1.Z(),
855                    (myYmax - P2.Y())/D.Y()*D.X() + P2.X(),
856                    (myYmax - P2.Y())/D.Y()*D.Z() + P2.Z()))
857     return Standard_False;
858
859   if(!IsSegmentOut(myXmin,myYmin,myXmax,myYmax,
860                    (myZmin - P1.Z())/D.Z()*D.X() + P1.X(),
861                    (myZmin - P1.Z())/D.Z()*D.Y() + P1.Y(),
862                    (myZmin - P2.Z())/D.Z()*D.X() + P2.X(),
863                    (myZmin - P2.Z())/D.Z()*D.Y() + P2.Y()))
864     return Standard_False;
865
866   if(!IsSegmentOut(myXmin,myYmin,myXmax,myYmax,
867                    (myZmax - P1.Z())/D.Z()*D.X() + P1.X(),
868                    (myZmax - P1.Z())/D.Z()*D.Y() + P1.Y(),
869                    (myZmax - P2.Z())/D.Z()*D.X() + P2.X(),
870                    (myZmax - P2.Z())/D.Z()*D.Y() + P2.Y()))
871     return Standard_False;
872
873   if(!IsSegmentOut(myZmin,myYmin,myZmax,myYmax,
874                    (myXmin - P1.X())/D.X()*D.Z() + P1.Z(),
875                    (myXmin - P1.X())/D.X()*D.Y() + P1.Y(),
876                    (myXmin - P2.X())/D.X()*D.Z() + P2.Z(),
877                    (myXmin - P2.X())/D.X()*D.Y() + P2.Y()))
878     return Standard_False;
879
880   if(!IsSegmentOut(myZmin,myYmin,myZmax,myYmax,
881                    (myXmax - P1.X())/D.X()*D.Z() + P1.Z(),
882                    (myXmax - P1.X())/D.X()*D.Y() + P1.Y(),
883                    (myXmax - P2.X())/D.X()*D.Z() + P2.Z(),
884                    (myXmax - P2.X())/D.X()*D.Y() + P2.Y()))
885     return Standard_False;
886
887   return Standard_True; 
888
889 }
890
891 //=======================================================================
892 //function : Distance
893 //purpose  : computes the minimum distance between two boxes 
894 //=======================================================================
895
896 static Standard_Real DistMini2Box( const Standard_Real r1min, const  Standard_Real r1max,  const Standard_Real r2min, const  Standard_Real r2max)
897 {  Standard_Real   r1, r2;
898
899    r1 = Square(r1min - r2max);
900    r2 = Square(r1max - r2min);
901    return (Min( r1, r2 ));   
902 }
903
904
905
906 Standard_Real Bnd_Box::Distance(const Bnd_Box& Other) const 
907 {  Standard_Real   xminB1, yminB1, zminB1, xmaxB1, ymaxB1, zmaxB1;
908    Standard_Real   xminB2, yminB2, zminB2, xmaxB2, ymaxB2, zmaxB2;
909    Standard_Real   dist_x, dist_y, dist_z, dist_t;
910
911    Get( xminB1, yminB1, zminB1, xmaxB1, ymaxB1, zmaxB1);
912    Other.Get( xminB2, yminB2, zminB2, xmaxB2, ymaxB2, zmaxB2);
913
914    if ( ((xminB1<= xminB2)&&( xminB2 <= xmaxB1)) || ((xminB2<= xminB1)&&( xminB1 <= xmaxB2)) )
915       { dist_x=0; }
916       else { dist_x= DistMini2Box(xminB1, xmaxB1, xminB2, xmaxB2);}
917    if ( ((yminB1<= yminB2)&&( yminB2 <= ymaxB1)) || ((yminB2<= yminB1)&&( yminB1 <= ymaxB2)) )
918       { dist_y=0; }
919       else { dist_y= DistMini2Box(yminB1, ymaxB1, yminB2, ymaxB2);}  
920    if ( ((zminB1<= zminB2)&&( zminB2 <= zmaxB1)) || ((zminB2<= zminB1)&&( zminB1 <= zmaxB2)) )
921       { dist_z=0; }
922       else { dist_z= DistMini2Box(zminB1, zmaxB1, zminB2, zmaxB2);}
923    dist_t = dist_x+ dist_y+ dist_z;
924    return( Sqrt ( dist_t));
925 }
926
927 //=======================================================================
928 //function : Dump
929 //purpose  : 
930 //=======================================================================
931
932 void Bnd_Box::Dump () const
933 {
934   cout << "Box3D : ";
935   if      (IsVoid())  cout << "Void";
936   else if (IsWhole()) cout << "Whole";
937   else {
938     cout << "\n Xmin : ";
939     if (IsOpenXmin()) cout << "Infinite";
940     else              cout << Xmin;
941     cout << "\n Xmax : ";
942     if (IsOpenXmax()) cout << "Infinite";
943     else              cout << Xmax;
944     cout << "\n Ymin : ";
945     if (IsOpenYmin()) cout << "Infinite";
946     else              cout << Ymin;
947     cout << "\n Ymax : ";
948     if (IsOpenYmax()) cout << "Infinite";
949     else              cout << Ymax;
950     cout << "\n Zmin : ";
951     if (IsOpenZmin()) cout << "Infinite";
952     else              cout << Zmin;
953     cout << "\n Zmax : ";
954     if (IsOpenZmax()) cout << "Infinite";
955     else              cout << Zmax;
956   }
957   cout << "\n Gap : " << Gap;
958   cout << "\n";
959 }