27f9f489850b1e329b74faa3d31316d601c007e4
[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
18 #include <Bnd_Box.hxx>
19 #include <gp_Dir.hxx>
20 #include <gp_Lin.hxx>
21 #include <gp_Pln.hxx>
22 #include <gp_Pnt.hxx>
23 #include <gp_Trsf.hxx>
24 #include <Standard_ConstructionError.hxx>
25
26 #define VoidMask  0x01
27 #define XminMask  0x02
28 #define XmaxMask  0x04
29 #define YminMask  0x08
30 #define YmaxMask  0x10
31 #define ZminMask  0x20
32 #define ZmaxMask  0x40
33 #define WholeMask 0x7e
34
35 // Standard_True if the flag is one
36 #define VoidFlag()  ( Flags & VoidMask )
37 #define XminFlag()  ( Flags & XminMask )
38 #define XmaxFlag()  ( Flags & XmaxMask )
39 #define YminFlag()  ( Flags & YminMask )
40 #define YmaxFlag()  ( Flags & YmaxMask )
41 #define ZminFlag()  ( Flags & ZminMask )
42 #define ZmaxFlag()  ( Flags & ZmaxMask )
43 #define WholeFlag() ( (Flags & WholeMask) == WholeMask )
44
45 // set the flag to one
46 #define SetVoidFlag()  ( Flags = VoidMask )
47 #define SetXminFlag()  ( Flags |= XminMask )
48 #define SetXmaxFlag()  ( Flags |= XmaxMask )
49 #define SetYminFlag()  ( Flags |= YminMask )
50 #define SetYmaxFlag()  ( Flags |= YmaxMask )
51 #define SetZminFlag()  ( Flags |= ZminMask )
52 #define SetZmaxFlag()  ( Flags |= ZmaxMask )
53 #define SetWholeFlag() ( Flags = WholeMask )
54
55 #define ClearVoidFlag() ( Flags &= ~VoidMask )
56
57 #include <Standard_Stream.hxx>
58 #include <gp.hxx>
59 // #include <Precision.hxx>
60 #define Bnd_Precision_Infinite 1e+100
61
62 //=======================================================================
63 //function : Bnd_Box
64 //purpose  : 
65 //=======================================================================
66
67 Bnd_Box::Bnd_Box()
68      : Xmin(0.), Xmax(0.), Ymin(0.), Ymax(0.),  Zmin(0.), Zmax(0.), Gap(0.)
69 {
70   SetVoid();
71 }
72
73 //=======================================================================
74 //function : SetWhole
75 //purpose  : 
76 //=======================================================================
77
78 void Bnd_Box::SetWhole ()
79 {
80   SetWholeFlag();
81 }
82
83 //=======================================================================
84 //function : SetVoid
85 //purpose  : 
86 //=======================================================================
87
88 void Bnd_Box::SetVoid ()
89 {
90   SetVoidFlag();
91   Gap=0.;
92 }
93
94 //=======================================================================
95 //function : Set
96 //purpose  : 
97 //=======================================================================
98
99 void Bnd_Box::Set(const gp_Pnt& P)
100 {
101   SetVoid();
102   Add(P);
103 }
104
105 //=======================================================================
106 //function : Set
107 //purpose  : 
108 //=======================================================================
109
110 void Bnd_Box::Set(const gp_Pnt& P, const gp_Dir& D)
111 {
112   SetVoid();
113   Add(P,D);
114 }
115
116
117 //=======================================================================
118 //function : Update
119 //purpose  : 
120 //=======================================================================
121
122 void Bnd_Box::Update (const Standard_Real x,
123                       const Standard_Real y, 
124                       const Standard_Real z, 
125                       const Standard_Real X,
126                       const Standard_Real Y, 
127                       const Standard_Real Z)
128 {
129   if (VoidFlag()) {
130     Xmin = x;
131     Ymin = y;
132     Zmin = z;
133     Xmax = X;
134     Ymax = Y;
135     Zmax = Z;
136     ClearVoidFlag();
137   }
138   else {
139     if (!XminFlag() && (x < Xmin)) Xmin = x;
140     if (!XmaxFlag() && (X > Xmax)) Xmax = X;
141     if (!YminFlag() && (y < Ymin)) Ymin = y;
142     if (!YmaxFlag() && (Y > Ymax)) Ymax = Y;
143     if (!ZminFlag() && (z < Zmin)) Zmin = z;
144     if (!ZmaxFlag() && (Z > Zmax)) Zmax = Z;
145   }
146 }
147
148 //=======================================================================
149 //function : Update
150 //purpose  : 
151 //=======================================================================
152
153 void Bnd_Box::Update (const Standard_Real X,
154                       const Standard_Real Y,
155                       const Standard_Real Z)
156 {
157   if (VoidFlag()) {
158     Xmin = X;
159     Ymin = Y;
160     Zmin = Z;
161     Xmax = X;
162     Ymax = Y;
163     Zmax = Z;
164     ClearVoidFlag();
165   }
166   else {
167     if      (!XminFlag() && (X < Xmin)) Xmin = X;
168     else if (!XmaxFlag() && (X > Xmax)) Xmax = X;
169     if      (!YminFlag() && (Y < Ymin)) Ymin = Y;
170     else if (!YmaxFlag() && (Y > Ymax)) Ymax = Y;
171     if      (!ZminFlag() && (Z < Zmin)) Zmin = Z;
172     else if (!ZmaxFlag() && (Z > Zmax)) Zmax = Z;
173   }
174 }
175
176 //=======================================================================
177 //function : GetGap
178 //purpose  : 
179 //=======================================================================
180
181 Standard_Real Bnd_Box::GetGap () const
182 {
183   return Gap;
184 }
185
186 //=======================================================================
187 //function : SetGap
188 //purpose  : 
189 //=======================================================================
190
191 void Bnd_Box::SetGap (const Standard_Real Tol)
192 {
193   Gap = Tol;
194 }
195
196 //=======================================================================
197 //function : Enlarge
198 //purpose  : 
199 //=======================================================================
200
201 void Bnd_Box::Enlarge (const Standard_Real Tol)
202 {
203   Gap=Max(Gap, Abs(Tol));
204 }
205
206 //=======================================================================
207 //function : Get
208 //purpose  : 
209 //=======================================================================
210
211 void Bnd_Box::Get (Standard_Real& theXmin,
212                    Standard_Real& theYmin,
213                    Standard_Real& theZmin,
214                    Standard_Real& theXmax,
215                    Standard_Real& theYmax,
216                    Standard_Real& theZmax) const
217 {
218   if (VoidFlag())
219   {
220     Standard_ConstructionError::Raise ("Bnd_Box is void");
221   }
222
223   if (XminFlag())  theXmin = -Bnd_Precision_Infinite;
224   else             theXmin = Xmin - Gap;
225   if (XmaxFlag())  theXmax = Bnd_Precision_Infinite;
226   else             theXmax = Xmax + Gap;
227   if (YminFlag())  theYmin = -Bnd_Precision_Infinite;
228   else             theYmin = Ymin - Gap;
229   if (YmaxFlag())  theYmax = Bnd_Precision_Infinite;
230   else             theYmax = Ymax + Gap;
231   if (ZminFlag())  theZmin = -Bnd_Precision_Infinite;
232   else             theZmin = Zmin - Gap;
233   if (ZmaxFlag())  theZmax = Bnd_Precision_Infinite;
234   else             theZmax = Zmax + Gap;
235 }
236
237 //=======================================================================
238 //function : CornerMin
239 //purpose  :
240 //=======================================================================
241
242 gp_Pnt Bnd_Box::CornerMin() const
243 {
244   gp_Pnt aCornerMin;
245   if (VoidFlag())
246   {
247     Standard_ConstructionError::Raise ("Bnd_Box is void");
248     return aCornerMin;
249   }
250   if (XminFlag())  aCornerMin.SetX (-Bnd_Precision_Infinite);
251   else             aCornerMin.SetX (Xmin - Gap);
252   if (YminFlag())  aCornerMin.SetY (-Bnd_Precision_Infinite);
253   else             aCornerMin.SetY (Ymin - Gap);
254   if (ZminFlag())  aCornerMin.SetZ (-Bnd_Precision_Infinite);
255   else             aCornerMin.SetZ (Zmin - Gap);
256   return aCornerMin;
257 }
258
259 //=======================================================================
260 //function : CornerMax
261 //purpose  :
262 //=======================================================================
263
264 gp_Pnt Bnd_Box::CornerMax() const
265 {
266   gp_Pnt aCornerMax;
267   if(VoidFlag())
268   {
269     Standard_ConstructionError::Raise ("Bnd_Box is void");
270     return aCornerMax;
271   }
272   if (XmaxFlag())  aCornerMax.SetX (Bnd_Precision_Infinite);
273   else             aCornerMax.SetX (Xmax + Gap);
274   if (YminFlag())  aCornerMax.SetY (Bnd_Precision_Infinite);
275   else             aCornerMax.SetY (Ymax + Gap);
276   if (ZminFlag())  aCornerMax.SetZ (Bnd_Precision_Infinite);
277   else             aCornerMax.SetZ (Zmax + Gap);
278   return aCornerMax;
279 }
280
281 //=======================================================================
282 //function : OpenXmin
283 //purpose  : 
284 //=======================================================================
285
286 void Bnd_Box::OpenXmin ()
287 {
288   SetXminFlag();
289 }
290
291 //=======================================================================
292 //function : OpenXmax
293 //purpose  : 
294 //=======================================================================
295
296 void Bnd_Box::OpenXmax ()
297 {
298   SetXmaxFlag();
299 }
300
301 //=======================================================================
302 //function : OpenYmin
303 //purpose  : 
304 //=======================================================================
305
306 void Bnd_Box::OpenYmin ()
307 {
308   SetYminFlag();
309 }
310
311 //=======================================================================
312 //function : OpenYmax
313 //purpose  : 
314 //=======================================================================
315
316 void Bnd_Box::OpenYmax ()
317 {
318   SetYmaxFlag();
319 }
320
321 //=======================================================================
322 //function : OpenZmin
323 //purpose  : 
324 //=======================================================================
325
326 void Bnd_Box::OpenZmin ()
327 {
328   SetZminFlag();
329 }
330
331 //=======================================================================
332 //function : OpenZmax
333 //purpose  : 
334 //=======================================================================
335
336 void Bnd_Box::OpenZmax ()
337 {
338   SetZmaxFlag();
339 }
340
341 //=======================================================================
342 //function : IsOpenXmin
343 //purpose  : 
344 //=======================================================================
345
346 Standard_Boolean Bnd_Box::IsOpenXmin () const
347 {
348   return XminFlag();
349 }
350
351 //=======================================================================
352 //function : IsOpenXmax
353 //purpose  : 
354 //=======================================================================
355
356 Standard_Boolean Bnd_Box::IsOpenXmax () const
357 {
358   return XmaxFlag();
359 }
360
361 //=======================================================================
362 //function : IsOpenYmin
363 //purpose  : 
364 //=======================================================================
365
366 Standard_Boolean Bnd_Box::IsOpenYmin () const
367 {
368   return YminFlag();
369 }
370
371 //=======================================================================
372 //function : IsOpenYmax
373 //purpose  : 
374 //=======================================================================
375
376 Standard_Boolean Bnd_Box::IsOpenYmax () const
377 {
378   return YmaxFlag();
379 }
380
381 //=======================================================================
382 //function : IsOpenZmin
383 //purpose  : 
384 //=======================================================================
385
386 Standard_Boolean Bnd_Box::IsOpenZmin () const
387 {
388   return ZminFlag();
389 }
390
391 //=======================================================================
392 //function : IsOpenZmax
393 //purpose  : 
394 //=======================================================================
395
396 Standard_Boolean Bnd_Box::IsOpenZmax () const
397 {
398   return ZmaxFlag();
399 }
400
401 //=======================================================================
402 //function : IsWhole
403 //purpose  : 
404 //=======================================================================
405
406 Standard_Boolean Bnd_Box::IsWhole () const
407 {
408   return WholeFlag();
409 }
410
411 //=======================================================================
412 //function : IsVoid
413 //purpose  : 
414 //=======================================================================
415
416 Standard_Boolean Bnd_Box::IsVoid () const
417 {
418   return VoidFlag();
419 }
420
421 //=======================================================================
422 //function : IsXThin
423 //purpose  : 
424 //=======================================================================
425
426 Standard_Boolean Bnd_Box::IsXThin (const Standard_Real tol) const
427 {
428   if (IsWhole())       return Standard_False;
429   if (IsVoid())        return Standard_True;
430   if (XminFlag())      return Standard_False;
431   if (XmaxFlag())      return Standard_False;
432   if (Xmax-Xmin < tol) return Standard_True;
433   return Standard_False;
434 }
435
436 //=======================================================================
437 //function : IsYThin
438 //purpose  : 
439 //=======================================================================
440
441 Standard_Boolean Bnd_Box::IsYThin (const Standard_Real tol) const
442 {
443   if (IsWhole())       return Standard_False;
444   if (IsVoid())        return Standard_True;
445   if (YminFlag())      return Standard_False;
446   if (YmaxFlag())      return Standard_False;
447   if (Ymax-Ymin < tol) return Standard_True;
448   return Standard_False;
449 }
450
451 //=======================================================================
452 //function : IsZThin
453 //purpose  : 
454 //=======================================================================
455
456 Standard_Boolean Bnd_Box::IsZThin (const Standard_Real tol) const
457 {
458   if (IsWhole())       return Standard_False;
459   if (IsVoid())        return Standard_True;
460   if (ZminFlag())      return Standard_False;
461   if (ZmaxFlag())      return Standard_False;
462   if (Zmax-Zmin < tol) return Standard_True;
463   return Standard_False;
464 }
465
466 //=======================================================================
467 //function : IsThin
468 //purpose  : 
469 //=======================================================================
470
471 Standard_Boolean Bnd_Box::IsThin (const Standard_Real tol) const
472 {
473   if (!IsXThin(tol)) return Standard_False;
474   if (!IsYThin(tol)) return Standard_False;
475   if (!IsZThin(tol)) return Standard_False;
476   return Standard_True;
477 }
478
479 //=======================================================================
480 //function : Transformed
481 //purpose  : 
482 //=======================================================================
483
484 Bnd_Box Bnd_Box::Transformed (const gp_Trsf& T) const
485 {
486   gp_TrsfForm F = T.Form();
487   Bnd_Box newb(*this);
488   if ( IsVoid() ) return newb;
489
490   if      (F == gp_Identity) {}
491   else if (F == gp_Translation) {
492     Standard_Real DX,DY,DZ;
493     (T.TranslationPart()).Coord(DX,DY,DZ);
494     if (!XminFlag())  newb.Xmin += DX;
495     if (!XmaxFlag())  newb.Xmax += DX;
496     if (!YminFlag())  newb.Ymin += DY;
497     if (!YmaxFlag())  newb.Ymax += DY;
498     if (!ZminFlag())  newb.Zmin += DZ;
499     if (!ZmaxFlag())  newb.Zmax += DZ;
500   }
501   else {
502     gp_Pnt P[8];
503     Standard_Boolean Vertex[8];
504     Standard_Integer i;
505     for (i=0;i<8;i++) Vertex[i] = Standard_True;
506     gp_Dir D[6];
507 //    Standard_Integer vertices = 0;
508     Standard_Integer directions = 0;
509
510     if (XminFlag()) {
511       directions++;
512       D[directions-1].SetCoord(-1., 0., 0.);
513       Vertex[0] = Vertex[2] = Vertex[4] = Vertex[6] = Standard_False;
514     }
515     if (XmaxFlag()) {
516       directions++;
517       D[directions-1].SetCoord( 1., 0., 0.);
518       Vertex[1] = Vertex[3] = Vertex[5] = Vertex[7] = Standard_False;
519     }
520     if (YminFlag()) {
521       directions++;
522       D[directions-1].SetCoord( 0.,-1., 0.);
523       Vertex[0] = Vertex[1] = Vertex[4] = Vertex[5] = Standard_False;
524     }
525     if (YmaxFlag()) {
526       directions++;
527       D[directions-1].SetCoord( 0., 1., 0.);
528       Vertex[2] = Vertex[3] = Vertex[6] = Vertex[7] = Standard_False;
529     }
530     if (ZminFlag()) {
531       directions++;
532       D[directions-1].SetCoord( 0., 0.,-1.);
533       Vertex[0] = Vertex[1] = Vertex[2] = Vertex[3] = Standard_False;
534     }
535     if (ZmaxFlag()) {
536       directions++;
537       D[directions-1].SetCoord( 0., 0., 1.);
538       Vertex[4] = Vertex[5] = Vertex[6] = Vertex[7] = Standard_False;
539     }
540
541     newb.SetVoid();
542     for (i=0;i<directions;i++) {
543       D[i].Transform(T);
544       newb.Add(D[i]);
545     }
546     P[0].SetCoord(Xmin,Ymin,Zmin);
547     P[1].SetCoord(Xmax,Ymin,Zmin);
548     P[2].SetCoord(Xmin,Ymax,Zmin);
549     P[3].SetCoord(Xmax,Ymax,Zmin);
550     P[4].SetCoord(Xmin,Ymin,Zmax);
551     P[5].SetCoord(Xmax,Ymin,Zmax);
552     P[6].SetCoord(Xmin,Ymax,Zmax);
553     P[7].SetCoord(Xmax,Ymax,Zmax);
554     for (i=0;i<8;i++) {
555       if (Vertex[i]) {
556         P[i].Transform(T);
557         newb.Add(P[i]);
558       }
559     }
560     newb.Gap=Gap;
561   }
562   return newb;
563 }
564
565 //=======================================================================
566 //function : Add
567 //purpose  : 
568 //=======================================================================
569
570 void Bnd_Box::Add (const Bnd_Box& Other)
571 {
572   if (IsWhole()) return;
573   else if (Other.IsVoid()) return; 
574   else if (Other.IsWhole()) SetWhole();
575   else if (IsVoid()) (*this) = Other;
576   else
577   {
578     if ( ! IsOpenXmin() )
579     {
580       if (Other.IsOpenXmin()) OpenXmin();
581       else if (Xmin > Other.Xmin) Xmin = Other.Xmin;
582     }
583     if ( ! IsOpenXmax() )
584     {
585       if (Other.IsOpenXmax()) OpenXmax();
586       else if (Xmax < Other.Xmax) Xmax = Other.Xmax;
587     }
588     if ( ! IsOpenYmin() )
589     {
590       if (Other.IsOpenYmin()) OpenYmin();
591       else if (Ymin > Other.Ymin) Ymin = Other.Ymin;
592     }
593     if ( ! IsOpenYmax() )
594     {
595       if (Other.IsOpenYmax()) OpenYmax();
596       else if (Ymax < Other.Ymax) Ymax = Other.Ymax;
597     }
598     if ( ! IsOpenZmin() )
599     {
600       if (Other.IsOpenZmin()) OpenZmin();
601       else if (Zmin > Other.Zmin) Zmin = Other.Zmin;
602     }
603     if ( ! IsOpenZmax() )
604     {
605       if (Other.IsOpenZmax()) OpenZmax();
606       else if (Zmax < Other.Zmax) Zmax = Other.Zmax;
607     }
608     Gap = Max (Gap, Other.Gap);
609   }
610 }
611
612 //=======================================================================
613 //function : Add
614 //purpose  : 
615 //=======================================================================
616
617 void Bnd_Box::Add (const gp_Pnt& P)
618 {
619   Standard_Real X,Y,Z;
620   P.Coord(X,Y,Z);
621   Update(X,Y,Z);
622 }
623
624 //=======================================================================
625 //function : Add
626 //purpose  : 
627 //=======================================================================
628
629 void Bnd_Box::Add (const gp_Pnt& P, const gp_Dir& D)
630 {
631   Add(P);
632   Add(D);
633 }
634
635
636 //=======================================================================
637 //function : Add
638 //purpose  : 
639 //=======================================================================
640
641 void Bnd_Box::Add (const gp_Dir& D)
642 {
643   Standard_Real DX,DY,DZ;
644   D.Coord(DX,DY,DZ);
645
646   if (DX < -RealEpsilon()) 
647     OpenXmin();
648   else if (DX > RealEpsilon()) 
649     OpenXmax();
650
651   if (DY < -RealEpsilon())
652     OpenYmin();
653   else if (DY > RealEpsilon())
654     OpenYmax();
655
656   if (DZ < -RealEpsilon())
657     OpenZmin();
658   else if (DZ > RealEpsilon())
659     OpenZmax();
660 }
661
662 //=======================================================================
663 //function : IsOut
664 //purpose  : 
665 //=======================================================================
666
667 Standard_Boolean Bnd_Box::IsOut (const gp_Pnt& P) const
668 {
669   if        (IsWhole())  return Standard_False;
670   else if   (IsVoid())   return Standard_True;
671   else {
672     Standard_Real X,Y,Z;
673     P.Coord(X,Y,Z);
674     if      (!XminFlag() && (X < (Xmin-Gap))) return Standard_True;
675     else if (!XmaxFlag() && (X > (Xmax+Gap))) return Standard_True;
676     else if (!YminFlag() && (Y < (Ymin-Gap))) return Standard_True;
677     else if (!YmaxFlag() && (Y > (Ymax+Gap))) return Standard_True;
678     else if (!ZminFlag() && (Z < (Zmin-Gap))) return Standard_True;
679     else if (!ZmaxFlag() && (Z > (Zmax+Gap))) return Standard_True;
680     else return Standard_False;
681   }
682 }
683
684
685 //=======================================================================
686 //function : IsOut
687 //purpose  : 
688 //=======================================================================
689
690 Standard_Boolean Bnd_Box::IsOut (const gp_Pln& P) const
691 {
692   if        (IsWhole())  return Standard_False;
693   else if   (IsVoid())   return Standard_True;
694   else {
695     Standard_Real A,B,C,D;
696     P.Coefficients (A, B ,C ,D);
697     Standard_Real d = A * (Xmin-Gap) + B * (Ymin-Gap) + C * (Zmin-Gap) + D;
698 //    Standard_Boolean plus = d > 0;
699     Standard_Integer plus = d > 0;
700     if (plus != ((A*(Xmin-Gap) + B*(Ymin-Gap) + C*(Zmax+Gap) + D) > 0))
701       return Standard_False;
702     if (plus != ((A*(Xmin-Gap) + B*(Ymax+Gap) + C*(Zmin-Gap) + D) > 0))
703       return Standard_False;
704     if (plus != ((A*(Xmin-Gap) + B*(Ymax+Gap) + C*(Zmax+Gap) + D) > 0))
705       return Standard_False;
706     if (plus != ((A*(Xmax+Gap) + B*(Ymin-Gap) + C*(Zmin-Gap) + D) > 0))
707       return Standard_False;
708     if (plus != ((A*(Xmax+Gap) + B*(Ymin-Gap) + C*(Zmax+Gap) + D) > 0))
709       return Standard_False;
710     if (plus != ((A*(Xmax+Gap) + B*(Ymax+Gap) + C*(Zmin-Gap) + D) > 0))
711       return Standard_False;
712     if (plus != ((A*(Xmax+Gap) + B*(Ymax+Gap) + C*(Zmax+Gap) + D) > 0))
713       return Standard_False;
714     else return Standard_True;
715   }
716 }
717
718 //=======================================================================
719 //function : IsOut
720 //purpose  : 
721 //=======================================================================
722
723 Standard_Boolean Bnd_Box::IsOut (const gp_Lin& L) const
724 {
725   if        (IsWhole())  return Standard_False;
726   else if   (IsVoid())   return Standard_True;
727   else {
728     Standard_Real xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin, zmax;
729     Standard_Real parmin, parmax, par1, par2;
730     Standard_Boolean xToSet, yToSet;
731     Standard_Real myXmin, myYmin, myZmin, myXmax, myYmax, myZmax;
732     Get (myXmin, myYmin, myZmin, myXmax, myYmax, myZmax);
733
734     if (Abs(L.Direction().XYZ().X())>0.) {
735       par1=(myXmin-L.Location().XYZ().X())/L.Direction().XYZ().X();
736       par2=(myXmax-L.Location().XYZ().X())/L.Direction().XYZ().X();
737       parmin=Min(par1, par2);
738       parmax=Max(par1, par2);
739       xToSet=Standard_True;
740     }
741     else {
742       if (L.Location().XYZ().X()<myXmin || myXmax<L.Location().XYZ().X()) {
743         return Standard_True;
744       }
745       xmin=L.Location().XYZ().X();
746       xmax=L.Location().XYZ().X();
747       parmin=-Bnd_Precision_Infinite;
748       parmax=Bnd_Precision_Infinite;
749       xToSet=Standard_False;
750     }
751
752     if (Abs(L.Direction().XYZ().Y())>0.) {
753       par1=(myYmin-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
754       par2=(myYmax-L.Location().XYZ().Y())/L.Direction().XYZ().Y();
755       //=================DET change 06/03/01====================
756       if(parmax < Min(par1,par2) || parmin > Max(par1,par2))
757         return Standard_True;
758       //========================================================
759       parmin=Max(parmin, Min(par1,par2));
760       parmax=Min(parmax, Max(par1,par2));
761       yToSet=Standard_True;
762     }
763     else {
764       if (L.Location().XYZ().Y()<myYmin || myYmax<L.Location().XYZ().Y()) {
765         return Standard_True;
766       }
767       ymin=L.Location().XYZ().Y();
768       ymax=L.Location().XYZ().Y();
769       yToSet=Standard_False;
770     }
771
772     if (Abs(L.Direction().XYZ().Z())>0.) {
773       par1=(myZmin-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
774       par2=(myZmax-L.Location().XYZ().Z())/L.Direction().XYZ().Z();
775       //=================DET change 06/03/01====================
776       if(parmax < Min(par1,par2) || parmin > Max(par1,par2))
777         return Standard_True;
778       //========================================================
779       parmin=Max(parmin, Min(par1,par2));
780       parmax=Min(parmax, Max(par1,par2));
781       par1=L.Location().XYZ().Z()+parmin*L.Direction().XYZ().Z();
782       par2=L.Location().XYZ().Z()+parmax*L.Direction().XYZ().Z();
783       zmin=Min(par1, par2);
784       zmax=Max(par1, par2);
785     }
786     else {
787       if (L.Location().XYZ().Z()<myZmin || myZmax<L.Location().XYZ().Z())
788         return Standard_True;
789       zmin=L.Location().XYZ().Z();
790       zmax=L.Location().XYZ().Z();
791     }
792     if (zmax<myZmin || myZmax<zmin) return Standard_True;
793
794     if (xToSet) {
795       par1=L.Location().XYZ().X()+parmin*L.Direction().XYZ().X();
796       par2=L.Location().XYZ().X()+parmax*L.Direction().XYZ().X();
797       xmin=Min(par1, par2);
798       xmax=Max(par1, par2);
799     }
800     if (xmax<myXmin || myXmax<xmin) return Standard_True;
801
802     if (yToSet) {
803       par1=L.Location().XYZ().Y()+parmin*L.Direction().XYZ().Y();
804       par2=L.Location().XYZ().Y()+parmax*L.Direction().XYZ().Y();
805       ymin=Min(par1, par2);
806       ymax=Max(par1, par2);
807     }
808     if (ymax<myYmin || myYmax<ymin) return Standard_True;
809   }
810   return Standard_False;
811 }
812
813 //=======================================================================
814 //function : IsOut
815 //purpose  : 
816 //=======================================================================
817
818 Standard_Boolean Bnd_Box::IsOut (const Bnd_Box& Other) const
819
820   //modified by NIZNHY-PKV Fri Jul 08 11:03:43 2011f
821   if (!Flags && !Other.Flags) {
822     Standard_Boolean bRet;
823     Standard_Real delta;
824     //
825     delta = Other.Gap + Gap;
826     bRet=((Xmin - Other.Xmax > delta) ||
827           (Other.Xmin - Xmax > delta) ||
828           (Ymin - Other.Ymax > delta) ||
829           (Other.Ymin - Ymax > delta) ||
830           (Zmin - Other.Zmax > delta) ||
831           (Other.Zmin - Zmax > delta));
832     return bRet;
833   }
834   //modified by NIZNHY-PKV Fri Jul 08 11:03:46 2011t
835   if   (IsVoid())         return Standard_True;
836   if   (Other.IsVoid())   return Standard_True;
837   if   (IsWhole())        return Standard_False;
838   if   (Other.IsWhole())  return Standard_False;
839
840   Standard_Real delta = Other.Gap + Gap;
841
842   if (!XminFlag() && !Other.IsOpenXmax())
843     if (Xmin - Other.Xmax > delta) return Standard_True;
844   if (!XmaxFlag() && !Other.IsOpenXmin())
845     if (Other.Xmin - Xmax > delta) return Standard_True;
846   
847   if (!YminFlag() && !Other.IsOpenYmax())
848     if (Ymin - Other.Ymax > delta) return Standard_True;
849   if (!YmaxFlag() && !Other.IsOpenYmin())
850     if (Other.Ymin - Ymax > delta) return Standard_True;
851   
852   if (!ZminFlag() && !Other.IsOpenZmax())
853     if (Zmin - Other.Zmax > delta) return Standard_True;
854   if (!ZmaxFlag() && !Other.IsOpenZmin())
855     if (Other.Zmin - Zmax > delta) return Standard_True;
856
857   return Standard_False;
858 }
859
860 //=======================================================================
861 //function : IsOut
862 //purpose  : 
863 //=======================================================================
864
865 Standard_Boolean Bnd_Box::IsOut (const Bnd_Box& Other, 
866                                  const gp_Trsf& T) const
867 {
868   return IsOut(Other.Transformed(T));
869 }
870
871 //=======================================================================
872 //function : IsOut
873 //purpose  : 
874 //=======================================================================
875
876 Standard_Boolean Bnd_Box::IsOut (const gp_Trsf& T1,
877                                  const Bnd_Box& Other, 
878                                  const gp_Trsf& T2) const
879 {
880   return Transformed(T1).IsOut(Other.Transformed(T2));
881 }
882
883
884 //=======================================================================
885 //function : IsSegmentOut
886 //purpose  : 
887 //=======================================================================
888
889 static Standard_Boolean IsSegmentOut(Standard_Real x1,Standard_Real y1,
890                                      Standard_Real x2,Standard_Real y2,
891                                      Standard_Real xs1,Standard_Real ys1,
892                                      Standard_Real xs2,Standard_Real ys2)
893 {
894   Standard_Real eps = RealSmall();
895   Standard_Real xsmin = Min (xs1, xs2);
896   Standard_Real xsmax = Max (xs1, xs2);
897   Standard_Real ysmin = Min (ys1, ys2);
898   Standard_Real ysmax = Max (ys1, ys2);
899
900   if (ysmax-ysmin < eps && (y1-ys1 < eps && ys1-y2 < eps) &&
901       ((xsmin-x1 < eps && x1-xsmax < eps) || 
902        (xsmin-x2 < eps && x2-xsmax < eps) || 
903        (x1-xs1 < eps && xs1-x2 < eps)))
904     return Standard_False;
905   if (xsmax-xsmin < eps && (x1-xs1 < eps && xs1-x2 < eps) &&
906       ((ysmin-y1 < eps && y1-ysmax < eps) ||
907        (ysmin-y2 < eps && y2-ysmax < eps) ||
908        (y1-ys1 < eps && ys1-y2 < eps)))
909     return Standard_False;
910
911   if ((xs1 < x1 && xs2 < x1) || (xs1 > x2 && xs2 > x2) ||
912       (ys1 < y1 && ys2 < y1) || (ys1 > y2 && ys2 > y2) )
913     return Standard_True;
914
915   if (Abs(xs2-xs1) > eps)
916   {
917     Standard_Real ya = ( Min(x1, x2) - xs1 ) * ( ys2 - ys1 ) / ( xs2 - xs1 ) + ys1;
918     Standard_Real yb = ( Max(x1, x2) - xs1 ) * ( ys2 - ys1 ) / ( xs2 - xs1 ) + ys1;
919     if ( (ya < y1 && yb < y1) || (ya > y2 && yb > y2) ) return Standard_True;
920   }
921   else if (Abs(ys2-ys1) > eps)
922   {
923     Standard_Real xa = ( Min(y1, y2) - ys1 ) * ( xs2 - xs1 ) / ( ys2 - ys1 ) + xs1;
924     Standard_Real xb = ( Max(y1, y2) - ys1 ) * ( xs2 - xs1 ) / ( ys2 - ys1 ) + xs1;
925     if ( (xa < x1 && xb < x1) || (xa > x2 && xb > x2) ) return Standard_True;
926   }
927   else 
928     return Standard_True;
929
930   return Standard_False;
931 }
932
933 Standard_Boolean Bnd_Box::IsOut(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Dir& D) const
934 {
935
936   if        (IsWhole())  return Standard_False;
937   else if   (IsVoid())   return Standard_True;
938
939   Standard_Real eps = RealSmall();
940   Standard_Real myXmin, myYmin, myZmin, myXmax, myYmax, myZmax;
941   Get (myXmin, myYmin, myZmin, myXmax, myYmax, myZmax);
942
943   if(Abs(D.X()) < eps && Abs(D.Y()) < eps)
944     return IsSegmentOut(myXmin, myYmin, myXmax, myYmax, P1.X(), P1.Y(), P2.X(), P2.Y());
945
946   if(Abs(D.X()) < eps && Abs(D.Z()) < eps)
947     return IsSegmentOut(myXmin, myZmin, myXmax, myZmax, P1.X(), P1.Z(), P2.X(), P2.Z());
948
949   if(Abs(D.Y()) < eps && Abs(D.Z()) < eps)
950     return IsSegmentOut(myYmin, myZmin, myYmax, myZmax, P1.Y(), P1.Z(), P2.Y(), P2.Z());
951
952   if(Abs(D.X()) < eps)
953   {
954     if(!IsSegmentOut(myXmin, myZmin, myXmax, myZmax,
955                      P1.X(),(myYmin-P1.Y())*D.Z()/D.Y()+P1.Z(), 
956                      P2.X(),(myYmin-P2.Y())*D.Z()/D.Y()+P2.Z()))
957       return Standard_False;
958
959     if(!IsSegmentOut(myXmin, myZmin, myXmax, myZmax,
960                      P1.X(),(myYmax-P1.Y())*D.Z()/D.Y()+P1.Z(), 
961                      P2.X(),(myYmax-P2.Y())*D.Z()/D.Y()+P2.Z()))
962       return Standard_False;
963
964     if(!IsSegmentOut(myXmin, myYmin, myXmax, myYmax,
965                      P1.X(),(myZmin-P1.Z())*D.Y()/D.Z()+P1.Y(), 
966                      P2.X(),(myZmin-P2.Z())*D.Y()/D.Z()+P2.Y()))
967       return Standard_False;
968
969     if(!IsSegmentOut(myXmin, myYmin, myXmax, myYmax,
970                      P1.X(),(myZmax-P1.Z())*D.Y()/D.Z()+P1.Y(), 
971                      P2.X(),(myZmax-P2.Z())*D.Y()/D.Z()+P2.Y()))
972       return Standard_False;
973
974     return Standard_True;
975   }//if(D.X() == 0) 
976
977   if(Abs(D.Y()) < eps)
978   {
979     if(!IsSegmentOut(myYmin, myZmin, myYmax, myZmax,
980                      P1.Y(),(myXmin-P1.X())*D.Z()/D.X()+P1.Z(), 
981                      P2.Y(),(myXmin-P2.X())*D.Z()/D.X()+P2.Z()))
982       return Standard_False;
983
984     if(!IsSegmentOut(myYmin, myZmin, myYmax, myZmax,
985                      P1.Y(),(myXmax-P1.X())*D.Z()/D.X()+P1.Z(), 
986                      P2.Y(),(myXmax-P2.X())*D.Z()/D.X()+P2.Z()))
987       return Standard_False;
988
989     if(!IsSegmentOut(myYmin, myXmin, myYmax, myXmax,
990                      P1.Y(),(myZmin-P1.Z())*D.X()/D.Z()+P1.X(), 
991                      P2.Y(),(myZmin-P2.Z())*D.X()/D.Z()+P2.X()))
992       return Standard_False;
993
994     if(!IsSegmentOut(myYmin, myXmin, myYmax, myXmax,
995                      P1.Y(),(myZmax-P1.Z())*D.X()/D.Z()+P1.X(), 
996                      P2.Y(),(myZmax-P2.Z())*D.X()/D.Z()+P2.X()))
997       return Standard_False;
998
999     return Standard_True;
1000   }//if(D.Y() == 0) 
1001
1002   if(Abs(D.Z()) < eps)
1003   {
1004     if(!IsSegmentOut(myZmin, myXmin, myZmax, myXmax,
1005                      P1.Z(),(myYmax-P1.Y())*D.X()/D.Y()+P1.X(), 
1006                      P2.Z(),(myYmax-P2.Y())*D.X()/D.Y()+P2.X()))
1007       return Standard_False;
1008
1009     if(!IsSegmentOut(myZmin, myXmin, myZmax, myXmax,
1010                      P1.Z(),(myYmin-P1.Y())*D.X()/D.Y()+P1.X(), 
1011                      P2.Z(),(myYmin-P2.Y())*D.X()/D.Y()+P2.X()))
1012       return Standard_False;
1013
1014     if(!IsSegmentOut(myZmin, myYmin, myZmax, myYmax,
1015                      P1.Z(),(myXmax-P1.X())*D.Y()/D.X()+P1.Y(), 
1016                      P2.Z(),(myXmax-P2.X())*D.Y()/D.X()+P2.Y()))
1017       return Standard_False;
1018
1019     if(!IsSegmentOut(myZmin, myYmin, myZmax, myYmax,
1020                      P1.Z(),(myXmin-P1.X())*D.Y()/D.X()+P1.Y(), 
1021                      P2.Z(),(myXmin-P2.X())*D.Y()/D.X()+P2.Y()))
1022       return Standard_False;
1023
1024     return Standard_True;
1025   }//if(D.Z() == 0) 
1026
1027   if(!IsSegmentOut(myXmin,myZmin,myXmax,myZmax,
1028                    (myYmin - P1.Y())/D.Y()*D.X() + P1.X(),
1029                    (myYmin - P1.Y())/D.Y()*D.Z() + P1.Z(),
1030                    (myYmin - P2.Y())/D.Y()*D.X() + P2.X(),
1031                    (myYmin - P2.Y())/D.Y()*D.Z() + P2.Z()))
1032     return Standard_False;
1033
1034   if(!IsSegmentOut(myXmin,myZmin,myXmax,myZmax,
1035                    (myYmax - P1.Y())/D.Y()*D.X() + P1.X(),
1036                    (myYmax - P1.Y())/D.Y()*D.Z() + P1.Z(),
1037                    (myYmax - P2.Y())/D.Y()*D.X() + P2.X(),
1038                    (myYmax - P2.Y())/D.Y()*D.Z() + P2.Z()))
1039     return Standard_False;
1040
1041   if(!IsSegmentOut(myXmin,myYmin,myXmax,myYmax,
1042                    (myZmin - P1.Z())/D.Z()*D.X() + P1.X(),
1043                    (myZmin - P1.Z())/D.Z()*D.Y() + P1.Y(),
1044                    (myZmin - P2.Z())/D.Z()*D.X() + P2.X(),
1045                    (myZmin - P2.Z())/D.Z()*D.Y() + P2.Y()))
1046     return Standard_False;
1047
1048   if(!IsSegmentOut(myXmin,myYmin,myXmax,myYmax,
1049                    (myZmax - P1.Z())/D.Z()*D.X() + P1.X(),
1050                    (myZmax - P1.Z())/D.Z()*D.Y() + P1.Y(),
1051                    (myZmax - P2.Z())/D.Z()*D.X() + P2.X(),
1052                    (myZmax - P2.Z())/D.Z()*D.Y() + P2.Y()))
1053     return Standard_False;
1054
1055   if(!IsSegmentOut(myZmin,myYmin,myZmax,myYmax,
1056                    (myXmin - P1.X())/D.X()*D.Z() + P1.Z(),
1057                    (myXmin - P1.X())/D.X()*D.Y() + P1.Y(),
1058                    (myXmin - P2.X())/D.X()*D.Z() + P2.Z(),
1059                    (myXmin - P2.X())/D.X()*D.Y() + P2.Y()))
1060     return Standard_False;
1061
1062   if(!IsSegmentOut(myZmin,myYmin,myZmax,myYmax,
1063                    (myXmax - P1.X())/D.X()*D.Z() + P1.Z(),
1064                    (myXmax - P1.X())/D.X()*D.Y() + P1.Y(),
1065                    (myXmax - P2.X())/D.X()*D.Z() + P2.Z(),
1066                    (myXmax - P2.X())/D.X()*D.Y() + P2.Y()))
1067     return Standard_False;
1068
1069   return Standard_True; 
1070
1071 }
1072
1073 //=======================================================================
1074 //function : Distance
1075 //purpose  : computes the minimum distance between two boxes 
1076 //=======================================================================
1077
1078 static Standard_Real DistMini2Box( const Standard_Real r1min, const  Standard_Real r1max,  const Standard_Real r2min, const  Standard_Real r2max)
1079 {  Standard_Real   r1, r2;
1080
1081    r1 = Square(r1min - r2max);
1082    r2 = Square(r1max - r2min);
1083    return (Min( r1, r2 ));   
1084 }
1085
1086
1087
1088 Standard_Real Bnd_Box::Distance(const Bnd_Box& Other) const 
1089 {  Standard_Real   xminB1, yminB1, zminB1, xmaxB1, ymaxB1, zmaxB1;
1090    Standard_Real   xminB2, yminB2, zminB2, xmaxB2, ymaxB2, zmaxB2;
1091    Standard_Real   dist_x, dist_y, dist_z, dist_t;
1092
1093    Get( xminB1, yminB1, zminB1, xmaxB1, ymaxB1, zmaxB1);
1094    Other.Get( xminB2, yminB2, zminB2, xmaxB2, ymaxB2, zmaxB2);
1095
1096    if ( ((xminB1<= xminB2)&&( xminB2 <= xmaxB1)) || ((xminB2<= xminB1)&&( xminB1 <= xmaxB2)) )
1097       { dist_x=0; }
1098       else { dist_x= DistMini2Box(xminB1, xmaxB1, xminB2, xmaxB2);}
1099    if ( ((yminB1<= yminB2)&&( yminB2 <= ymaxB1)) || ((yminB2<= yminB1)&&( yminB1 <= ymaxB2)) )
1100       { dist_y=0; }
1101       else { dist_y= DistMini2Box(yminB1, ymaxB1, yminB2, ymaxB2);}  
1102    if ( ((zminB1<= zminB2)&&( zminB2 <= zmaxB1)) || ((zminB2<= zminB1)&&( zminB1 <= zmaxB2)) )
1103       { dist_z=0; }
1104       else { dist_z= DistMini2Box(zminB1, zmaxB1, zminB2, zmaxB2);}
1105    dist_t = dist_x+ dist_y+ dist_z;
1106    return( Sqrt ( dist_t));
1107 }
1108
1109 //=======================================================================
1110 //function : Dump
1111 //purpose  : 
1112 //=======================================================================
1113
1114 void Bnd_Box::Dump () const
1115 {
1116   cout << "Box3D : ";
1117   if      (IsVoid())  cout << "Void";
1118   else if (IsWhole()) cout << "Whole";
1119   else {
1120     cout << "\n Xmin : ";
1121     if (IsOpenXmin()) cout << "Infinite";
1122     else              cout << Xmin;
1123     cout << "\n Xmax : ";
1124     if (IsOpenXmax()) cout << "Infinite";
1125     else              cout << Xmax;
1126     cout << "\n Ymin : ";
1127     if (IsOpenYmin()) cout << "Infinite";
1128     else              cout << Ymin;
1129     cout << "\n Ymax : ";
1130     if (IsOpenYmax()) cout << "Infinite";
1131     else              cout << Ymax;
1132     cout << "\n Zmin : ";
1133     if (IsOpenZmin()) cout << "Infinite";
1134     else              cout << Zmin;
1135     cout << "\n Zmax : ";
1136     if (IsOpenZmax()) cout << "Infinite";
1137     else              cout << Zmax;
1138   }
1139   cout << "\n Gap : " << Gap;
1140   cout << "\n";
1141 }