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