1 // Created on: 1991-01-28
2 // Created by: Remi Lequette
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2012 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 #ifndef _Bnd_Box2d_HeaderFile
18 #define _Bnd_Box2d_HeaderFile
19 
20 #include <gp_Lin2d.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Standard.hxx>
23 #include <Standard_DefineAlloc.hxx>
24 #include <Standard_Handle.hxx>
25 
26 #include <Standard_Real.hxx>
27 #include <Standard_Integer.hxx>
28 #include <Standard_Boolean.hxx>
29 class gp_Dir2d;
30 class gp_Trsf2d;
31 
32 
33 //! Describes a bounding box in 2D space.
34 //! A bounding box is parallel to the axes of the coordinates
35 //! system. If it is finite, it is defined by the two intervals:
36 //! -   [ Xmin,Xmax ], and
37 //! -   [ Ymin,Ymax ].
38 //! A bounding box may be infinite (i.e. open) in one or more
39 //! directions. It is said to be:
40 //! -   OpenXmin if it is infinite on the negative side of the   "X Direction";
41 //! -   OpenXmax if it is infinite on the positive side of the   "X Direction";
42 //! -   OpenYmin if it is infinite on the negative side of the   "Y Direction";
43 //! -   OpenYmax if it is infinite on the positive side of the   "Y Direction";
44 //! -   WholeSpace if it is infinite in all four directions. In
45 //! this case, any point of the space is inside the box;
46 //! -   Void if it is empty. In this case, there is no point included in the box.
47 //! A bounding box is defined by four bounds (Xmin, Xmax, Ymin and Ymax) which
48 //! limit the bounding box if it is finite, six flags (OpenXmin, OpenXmax, OpenYmin,
49 //! OpenYmax, WholeSpace and Void) which describe the bounding box if it is infinite or empty, and
50 //! -   a gap, which is included on both sides in any direction when consulting the finite bounds of the box.
51 class Bnd_Box2d
52 {
53 public:
54 
55   DEFINE_STANDARD_ALLOC
56 
57   //! Creates an empty 2D bounding box.
58   //! The constructed box is qualified Void. Its gap is null.
Bnd_Box2d()59   Bnd_Box2d() : Xmin(0.), Xmax(0.), Ymin(0.), Ymax(0.), Gap(0.), Flags (VoidMask) {}
60 
61   //! Sets this bounding box so that it covers the whole 2D
62   //! space, i.e. it is infinite in all directions.
SetWhole()63   void SetWhole() { Flags = WholeMask; }
64 
65   //! Sets this 2D bounding box so that it is empty. All points are outside a void box.
SetVoid()66   void SetVoid()
67   {
68     Flags = VoidMask;
69     Gap   = 0.0;
70   }
71 
72   //! Sets this 2D bounding box so that it bounds
73   //! the point P. This involves first setting this bounding box
74   //! to be void and then adding the point PThe rectangle bounds   the  point <P>.
Set(const gp_Pnt2d & thePnt)75   void Set (const gp_Pnt2d& thePnt)
76   {
77     Flags = VoidMask;
78     Gap   = 0.0;
79     Add (thePnt);
80   }
81 
82   //! Sets this 2D bounding box so that it bounds
83   //! the half-line defined by point P and direction D, i.e. all
84   //! points M defined by M=P+u*D, where u is greater than
85   //! or equal to 0, are inside the bounding area. This involves
86   //! first setting this 2D box to be void and then adding the   half-line.
Set(const gp_Pnt2d & thePnt,const gp_Dir2d & theDir)87   void Set (const gp_Pnt2d& thePnt, const gp_Dir2d& theDir)
88   {
89     Flags = VoidMask;
90     Gap   = 0.0;
91     Add (thePnt, theDir);
92   }
93 
94   //! Enlarges this 2D bounding box, if required, so that it
95   //! contains at least:
96   //! -   interval [ aXmin,aXmax ] in the "X Direction",
97   //! -   interval [ aYmin,aYmax ] in the "Y Direction"
98   Standard_EXPORT void Update (const Standard_Real aXmin, const Standard_Real aYmin, const Standard_Real aXmax, const Standard_Real aYmax);
99 
100   //! Adds a point of coordinates (X,Y) to this bounding box.
101   Standard_EXPORT void Update (const Standard_Real X, const Standard_Real Y);
102 
103   //! Returns the gap of this 2D bounding box.
GetGap() const104   Standard_Real GetGap() const { return Gap; }
105 
106   //! Set the gap of this 2D bounding box to abs(Tol).
SetGap(const Standard_Real Tol)107   void SetGap (const Standard_Real Tol) { Gap = Tol; }
108 
109   //! Enlarges     the  box  with    a  tolerance  value.
110   //! This means that the minimum values of its X and Y
111   //! intervals of definition, when they are finite, are reduced by
112   //! the absolute value of Tol, while the maximum values are
113   //! increased by the same amount.
Enlarge(const Standard_Real theTol)114   void Enlarge (const Standard_Real theTol)
115   {
116     Standard_Real aTol = theTol < 0.0 ? -theTol : theTol;
117     if (Gap < aTol) Gap = aTol;
118   }
119 
120   //! Returns the bounds of this 2D bounding box.
121   //! The gap is included. If this bounding box is infinite (i.e. "open"), returned values
122   //! may be equal to +/- Precision::Infinite().
123   //! if IsVoid()
124   Standard_EXPORT void Get (Standard_Real& aXmin, Standard_Real& aYmin, Standard_Real& aXmax, Standard_Real& aYmax) const;
125 
126   //! The Box will be infinitely long in the Xmin direction.
OpenXmin()127   void OpenXmin() { Flags |= XminMask; }
128 
129   //! The Box will be infinitely long in the Xmax direction.
OpenXmax()130   void OpenXmax() { Flags |= XmaxMask; }
131 
132   //! The Box will be infinitely long in the Ymin direction.
OpenYmin()133   void OpenYmin() { Flags |= YminMask; }
134 
135   //! The Box will be infinitely long in the Ymax direction.
OpenYmax()136   void OpenYmax() { Flags |= YmaxMask; }
137 
138   //! Returns true if this bounding box is open in the Xmin direction.
IsOpenXmin() const139   Standard_Boolean IsOpenXmin() const { return (Flags & XminMask) != 0; }
140 
141   //! Returns true if this bounding box is open in the Xmax direction.
IsOpenXmax() const142   Standard_Boolean IsOpenXmax() const { return (Flags & XmaxMask) != 0; }
143 
144   //! Returns true if this bounding box is open in the Ymin direction.
IsOpenYmin() const145   Standard_Boolean IsOpenYmin() const { return (Flags & YminMask) != 0; }
146 
147   //! Returns true if this bounding box is open in the Ymax direction.
IsOpenYmax() const148   Standard_Boolean IsOpenYmax() const { return (Flags & YmaxMask) != 0; }
149 
150   //! Returns true if this bounding box is infinite in all 4
151   //! directions (Whole Space flag).
IsWhole() const152   Standard_Boolean IsWhole() const { return (Flags & WholeMask) == WholeMask; }
153 
154   //! Returns true if this 2D bounding box is empty (Void flag).
IsVoid() const155   Standard_Boolean IsVoid() const { return (Flags & VoidMask) != 0; }
156 
157   //! Returns a bounding box which is the result of applying the
158   //! transformation T to this bounding box.
159   //! Warning
160   //! Applying a geometric transformation (for example, a
161   //! rotation) to a bounding box generally increases its
162   //! dimensions. This is not optimal for algorithms which use it.
163   Standard_NODISCARD Standard_EXPORT Bnd_Box2d Transformed (const gp_Trsf2d& T) const;
164 
165   //! Adds the 2d box <Other> to <me>.
166   Standard_EXPORT void Add (const Bnd_Box2d& Other);
167 
168   //! Adds the 2d point.
Add(const gp_Pnt2d & thePnt)169   void Add (const gp_Pnt2d& thePnt) { Update (thePnt.X(), thePnt.Y()); }
170 
171   //! Extends bounding box from thePnt in the direction theDir.
Add(const gp_Pnt2d & thePnt,const gp_Dir2d & theDir)172   void Add (const gp_Pnt2d& thePnt, const gp_Dir2d& theDir)
173   {
174     Add (thePnt);
175     Add (theDir);
176   }
177 
178   //! Extends the Box  in the given Direction, i.e. adds
179   //! a half-line. The box may become infinite in 1 or 2
180   //! directions.
181   Standard_EXPORT void Add (const gp_Dir2d& D);
182 
183   //! Returns True if the 2d pnt <P> is out <me>.
184   Standard_EXPORT Standard_Boolean IsOut (const gp_Pnt2d& P) const;
185 
186   //! Returns True if the line doesn't intersect the box.
187   Standard_EXPORT Standard_Boolean IsOut(const gp_Lin2d& theL) const;
188 
189   //! Returns True if the segment doesn't intersect the box.
190   Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt2d& theP0, const gp_Pnt2d& theP1) const;
191 
192   //! Returns True if <Box2d> is out <me>.
193   Standard_EXPORT Standard_Boolean IsOut (const Bnd_Box2d& Other) const;
194 
195   //! Returns True if transformed <Box2d> is out <me>.
IsOut(const Bnd_Box2d & theOther,const gp_Trsf2d & theTrsf) const196   Standard_Boolean IsOut (const Bnd_Box2d& theOther, const gp_Trsf2d& theTrsf) const
197   {
198     return IsOut (theOther.Transformed (theTrsf));
199   }
200 
201   //! Compares  a transformed  bounding with  a    transformed
202   //! bounding. The default implementation is  to make a copy
203   //! of <me> and <Other>, to transform them and to test.
IsOut(const gp_Trsf2d & T1,const Bnd_Box2d & Other,const gp_Trsf2d & T2) const204   Standard_Boolean IsOut (const gp_Trsf2d& T1, const Bnd_Box2d& Other, const gp_Trsf2d& T2) const
205   {
206     return Transformed(T1).IsOut (Other.Transformed(T2));
207   }
208 
209   Standard_EXPORT void Dump() const;
210 
211   //! Computes the squared diagonal of me.
SquareExtent() const212   Standard_Real SquareExtent() const
213   {
214     if (IsVoid()) return 0.0;
215     const Standard_Real aDx = Xmax - Xmin + Gap + Gap;
216     const Standard_Real aDy = Ymax - Ymin + Gap + Gap;
217     return aDx*aDx + aDy*aDy;
218   }
219 
220 protected:
221 
222   //! Bit flags.
223   enum MaskFlags
224   {
225     VoidMask  = 0x01,
226     XminMask  = 0x02,
227     XmaxMask  = 0x04,
228     YminMask  = 0x08,
229     YmaxMask  = 0x10,
230     WholeMask = 0x1e
231   };
232 
233 private:
234 
235   Standard_Real Xmin;
236   Standard_Real Xmax;
237   Standard_Real Ymin;
238   Standard_Real Ymax;
239   Standard_Real Gap;
240   Standard_Integer Flags;
241 
242 };
243 
244 #endif // _Bnd_Box2d_HeaderFile
245