Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-26 09:02:28

0001 // Created on: 1991-01-28
0002 // Created by: Remi Lequette
0003 // Copyright (c) 1991-1999 Matra Datavision
0004 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0005 //
0006 // This file is part of Open CASCADE Technology software library.
0007 //
0008 // This library is free software; you can redistribute it and/or modify it under
0009 // the terms of the GNU Lesser General Public License version 2.1 as published
0010 // by the Free Software Foundation, with special exception defined in the file
0011 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0012 // distribution for complete text of the license and disclaimer of any warranty.
0013 //
0014 // Alternatively, this file may be used under the terms of Open CASCADE
0015 // commercial license or contractual agreement.
0016 
0017 #ifndef _Bnd_Box_HeaderFile
0018 #define _Bnd_Box_HeaderFile
0019 
0020 #include <Standard.hxx>
0021 #include <Standard_DefineAlloc.hxx>
0022 #include <Standard_Handle.hxx>
0023 
0024 #include <gp_Pnt.hxx>
0025 
0026 #include <algorithm>
0027 #include <cmath>
0028 #include <optional>
0029 
0030 class gp_Pnt;
0031 class gp_Dir;
0032 class gp_Trsf;
0033 class gp_Lin;
0034 class gp_Pln;
0035 
0036 //! Describes a bounding box in 3D space.
0037 //! A bounding box is parallel to the axes of the coordinates
0038 //! system. If it is finite, it is defined by the three intervals:
0039 //! -   [ Xmin,Xmax ],
0040 //! -   [ Ymin,Ymax ],
0041 //! -   [ Zmin,Zmax ].
0042 //! A bounding box may be infinite (i.e. open) in one or more
0043 //! directions. It is said to be:
0044 //! -   OpenXmin if it is infinite on the negative side of the   "X Direction";
0045 //! -   OpenXmax if it is infinite on the positive side of the "X Direction";
0046 //! -   OpenYmin if it is infinite on the negative side of the   "Y Direction";
0047 //! -   OpenYmax if it is infinite on the positive side of the "Y Direction";
0048 //! -   OpenZmin if it is infinite on the negative side of the   "Z Direction";
0049 //! -   OpenZmax if it is infinite on the positive side of the "Z Direction";
0050 //! -   WholeSpace if it is infinite in all six directions. In this
0051 //! case, any point of the space is inside the box;
0052 //! -   Void if it is empty. In this case, there is no point included in the box.
0053 //! A bounding box is defined by:
0054 //! -   six bounds (Xmin, Xmax, Ymin, Ymax, Zmin and
0055 //! Zmax) which limit the bounding box if it is finite,
0056 //! -   eight flags (OpenXmin, OpenXmax, OpenYmin,
0057 //! OpenYmax, OpenZmin, OpenZmax,
0058 //! WholeSpace and Void) which describe the
0059 //! bounding box if it is infinite or empty, and
0060 //! -   a gap, which is included on both sides in any direction
0061 //! when consulting the finite bounds of the box.
0062 class Bnd_Box
0063 {
0064 public:
0065   DEFINE_STANDARD_ALLOC
0066 
0067   //! Structure containing the box limits (Xmin, Xmax, Ymin, Ymax, Zmin, Zmax).
0068   //! The values include the gap and account for open directions.
0069   struct Limits
0070   {
0071     double Xmin; //!< Minimum X coordinate
0072     double Xmax; //!< Maximum X coordinate
0073     double Ymin; //!< Minimum Y coordinate
0074     double Ymax; //!< Maximum Y coordinate
0075     double Zmin; //!< Minimum Z coordinate
0076     double Zmax; //!< Maximum Z coordinate
0077   };
0078 
0079   //! Creates an empty Box.
0080   //! The constructed box is qualified Void. Its gap is null.
0081   constexpr Bnd_Box() noexcept = default;
0082 
0083   //! Creates a bounding box, it contains:
0084   //! -   minimum/maximum point of bounding box,
0085   //! The constructed box is qualified Void. Its gap is null.
0086   constexpr Bnd_Box(const gp_Pnt& theMin, const gp_Pnt& theMax)
0087       : Xmin(theMin.X()),
0088         Xmax(theMax.X()),
0089         Ymin(theMin.Y()),
0090         Ymax(theMax.Y()),
0091         Zmin(theMin.Z()),
0092         Zmax(theMax.Z()),
0093         Gap(0.0),
0094         Flags(0)
0095   {
0096   }
0097 
0098   //! Sets this bounding box so that it covers the whole of 3D space.
0099   //! It is infinitely long in all directions.
0100   void SetWhole() noexcept { Flags = WholeMask; }
0101 
0102   //! Sets this bounding box so that it is empty. All points are outside a void box.
0103   void SetVoid() noexcept
0104   {
0105     Xmin  = RealLast();
0106     Xmax  = -RealLast();
0107     Ymin  = RealLast();
0108     Ymax  = -RealLast();
0109     Zmin  = RealLast();
0110     Zmax  = -RealLast();
0111     Gap   = 0.0;
0112     Flags = VoidMask;
0113   }
0114 
0115   //! Sets this bounding box so that it bounds
0116   //! -   the point P. This involves first setting this bounding box
0117   //! to be void and then adding the point P.
0118   Standard_EXPORT void Set(const gp_Pnt& P);
0119 
0120   //! Sets this bounding box so that it bounds
0121   //! the half-line defined by point P and direction D, i.e. all
0122   //! points M defined by M=P+u*D, where u is greater than
0123   //! or equal to 0, are inside the bounding volume. This
0124   //! involves first setting this box to be void and then adding the half-line.
0125   Standard_EXPORT void Set(const gp_Pnt& P, const gp_Dir& D);
0126 
0127   //! Enlarges this bounding box, if required, so that it
0128   //! contains at least:
0129   //! -   interval [ aXmin,aXmax ] in the "X Direction",
0130   //! -   interval [ aYmin,aYmax ] in the "Y Direction",
0131   //! -   interval [ aZmin,aZmax ] in the "Z Direction";
0132   Standard_EXPORT void Update(const double aXmin,
0133                               const double aYmin,
0134                               const double aZmin,
0135                               const double aXmax,
0136                               const double aYmax,
0137                               const double aZmax);
0138 
0139   //! Adds a point of coordinates (X,Y,Z) to this bounding box.
0140   Standard_EXPORT void Update(const double X, const double Y, const double Z);
0141 
0142   //! Returns the gap of this bounding box.
0143   [[nodiscard]] constexpr double GetGap() const noexcept { return Gap; }
0144 
0145   //! Set the gap of this bounding box to abs(Tol).
0146   void SetGap(const double Tol) noexcept { Gap = std::abs(Tol); }
0147 
0148   //! Enlarges the box with a tolerance value.
0149   //! (minvalues-std::abs(<tol>) and maxvalues+std::abs(<tol>))
0150   //! This means that the minimum values of its X, Y and Z
0151   //! intervals of definition, when they are finite, are reduced by
0152   //! the absolute value of Tol, while the maximum values are
0153   //! increased by the same amount.
0154   void Enlarge(const double Tol) noexcept { Gap = (std::max)(Gap, std::abs(Tol)); }
0155 
0156   //! Returns the bounds of this bounding box. The gap is included.
0157   //! If this bounding box is infinite (i.e. "open"), returned values
0158   //! may be equal to +/- Precision::Infinite().
0159   //! Standard_ConstructionError exception will be thrown if the box is void.
0160   //! if IsVoid()
0161   Standard_EXPORT void Get(double& theXmin,
0162                            double& theYmin,
0163                            double& theZmin,
0164                            double& theXmax,
0165                            double& theYmax,
0166                            double& theZmax) const;
0167 
0168   //! Returns the bounds of this bounding box as a Limits structure.
0169   //! The gap is included. If this bounding box is infinite (i.e. "open"),
0170   //! returned values may be equal to +/- Precision::Infinite().
0171   //! If the box is void, returns raw internal values.
0172   //! Can be used with C++17 structured bindings:
0173   //! @code
0174   //!   auto [xmin, xmax, ymin, ymax, zmin, zmax] = aBox.Get();
0175   //! @endcode
0176   [[nodiscard]] Standard_EXPORT Limits Get() const;
0177 
0178   //! Returns the Xmin value (IsOpenXmin() ? -Precision::Infinite() : Xmin - GetGap()).
0179   [[nodiscard]] Standard_EXPORT double GetXMin() const;
0180 
0181   //! Returns the Xmax value (IsOpenXmax() ? Precision::Infinite() : Xmax + GetGap()).
0182   [[nodiscard]] Standard_EXPORT double GetXMax() const;
0183 
0184   //! Returns the Ymin value (IsOpenYmin() ? -Precision::Infinite() : Ymin - GetGap()).
0185   [[nodiscard]] Standard_EXPORT double GetYMin() const;
0186 
0187   //! Returns the Ymax value (IsOpenYmax() ? Precision::Infinite() : Ymax + GetGap()).
0188   [[nodiscard]] Standard_EXPORT double GetYMax() const;
0189 
0190   //! Returns the Zmin value (IsOpenZmin() ? -Precision::Infinite() : Zmin - GetGap()).
0191   [[nodiscard]] Standard_EXPORT double GetZMin() const;
0192 
0193   //! Returns the Zmax value (IsOpenZmax() ? Precision::Infinite() : Zmax + GetGap()).
0194   [[nodiscard]] Standard_EXPORT double GetZMax() const;
0195 
0196   //! Returns the lower corner of this bounding box. The gap is included.
0197   //! If this bounding box is infinite (i.e. "open"), returned values
0198   //! may be equal to +/- Precision::Infinite().
0199   //! Standard_ConstructionError exception will be thrown if the box is void.
0200   //! if IsVoid()
0201   [[nodiscard]] Standard_EXPORT gp_Pnt CornerMin() const;
0202 
0203   //! Returns the upper corner of this bounding box. The gap is included.
0204   //! If this bounding box is infinite (i.e. "open"), returned values
0205   //! may be equal to +/- Precision::Infinite().
0206   //! Standard_ConstructionError exception will be thrown if the box is void.
0207   //! if IsVoid()
0208   [[nodiscard]] Standard_EXPORT gp_Pnt CornerMax() const;
0209 
0210   //! Returns the center of this bounding box. The gap is included.
0211   //! If this bounding box is infinite (i.e. "open"), returned values
0212   //! may be equal to +/- Precision::Infinite().
0213   //! Returns std::nullopt if the box is void.
0214   [[nodiscard]] Standard_EXPORT std::optional<gp_Pnt> Center() const;
0215 
0216   //! The Box will be infinitely long in the Xmin
0217   //! direction.
0218   void OpenXmin() noexcept { Flags |= XminMask; }
0219 
0220   //! The Box will be infinitely long in the Xmax
0221   //! direction.
0222   void OpenXmax() noexcept { Flags |= XmaxMask; }
0223 
0224   //! The Box will be infinitely long in the Ymin
0225   //! direction.
0226   void OpenYmin() noexcept { Flags |= YminMask; }
0227 
0228   //! The Box will be infinitely long in the Ymax
0229   //! direction.
0230   void OpenYmax() noexcept { Flags |= YmaxMask; }
0231 
0232   //! The Box will be infinitely long in the Zmin
0233   //! direction.
0234   void OpenZmin() noexcept { Flags |= ZminMask; }
0235 
0236   //! The Box will be infinitely long in the Zmax
0237   //! direction.
0238   void OpenZmax() noexcept { Flags |= ZmaxMask; }
0239 
0240   //! Returns true if this bounding box has at least one open direction.
0241   [[nodiscard]] bool IsOpen() const noexcept { return (Flags & WholeMask) != 0; }
0242 
0243   //! Returns true if this bounding box is open in the Xmin direction.
0244   [[nodiscard]] bool IsOpenXmin() const noexcept { return (Flags & XminMask) != 0; }
0245 
0246   //! Returns true if this bounding box is open in the Xmax direction.
0247   [[nodiscard]] bool IsOpenXmax() const noexcept { return (Flags & XmaxMask) != 0; }
0248 
0249   //! Returns true if this bounding box is open in the Ymin direction.
0250   [[nodiscard]] bool IsOpenYmin() const noexcept { return (Flags & YminMask) != 0; }
0251 
0252   //! Returns true if this bounding box is open in the Ymax direction.
0253   [[nodiscard]] bool IsOpenYmax() const noexcept { return (Flags & YmaxMask) != 0; }
0254 
0255   //! Returns true if this bounding box is open in the Zmin direction.
0256   [[nodiscard]] bool IsOpenZmin() const noexcept { return (Flags & ZminMask) != 0; }
0257 
0258   //! Returns true if this bounding box is open in the Zmax direction.
0259   [[nodiscard]] bool IsOpenZmax() const noexcept { return (Flags & ZmaxMask) != 0; }
0260 
0261   //! Returns true if this bounding box is infinite in all 6 directions (WholeSpace flag).
0262   [[nodiscard]] bool IsWhole() const noexcept { return (Flags & WholeMask) == WholeMask; }
0263 
0264   //! Returns true if this bounding box is empty (Void flag).
0265   [[nodiscard]] bool IsVoid() const noexcept { return (Flags & VoidMask) != 0; }
0266 
0267   //! true if xmax-xmin < tol.
0268   [[nodiscard]] Standard_EXPORT bool IsXThin(const double tol) const;
0269 
0270   //! true if ymax-ymin < tol.
0271   [[nodiscard]] Standard_EXPORT bool IsYThin(const double tol) const;
0272 
0273   //! true if zmax-zmin < tol.
0274   [[nodiscard]] Standard_EXPORT bool IsZThin(const double tol) const;
0275 
0276   //! Returns true if IsXThin, IsYThin and IsZThin are all true,
0277   //! i.e. if the box is thin in all three dimensions.
0278   [[nodiscard]] Standard_EXPORT bool IsThin(const double tol) const;
0279 
0280   //! Returns a bounding box which is the result of applying the
0281   //! transformation T to this bounding box.
0282   //! Warning
0283   //! Applying a geometric transformation (for example, a
0284   //! rotation) to a bounding box generally increases its
0285   //! dimensions. This is not optimal for algorithms which use it.
0286   [[nodiscard]] Standard_EXPORT Bnd_Box Transformed(const gp_Trsf& T) const;
0287 
0288   //! Adds the box <Other> to <me>.
0289   Standard_EXPORT void Add(const Bnd_Box& Other);
0290 
0291   //! Adds a Pnt to the box.
0292   Standard_EXPORT void Add(const gp_Pnt& P);
0293 
0294   //! Extends <me> from the Pnt <P> in the direction <D>.
0295   Standard_EXPORT void Add(const gp_Pnt& P, const gp_Dir& D);
0296 
0297   //! Extends the Box in the given Direction, i.e. adds
0298   //! an half-line. The box may become infinite in
0299   //! 1,2 or 3 directions.
0300   Standard_EXPORT void Add(const gp_Dir& D);
0301 
0302   //! Returns True if the Pnt is out the box.
0303   [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Pnt& P) const;
0304 
0305   //! Returns False if the line intersects the box.
0306   [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Lin& L) const;
0307 
0308   //! Returns False if the plane intersects the box.
0309   [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Pln& P) const;
0310 
0311   //! Returns False if the <Box> intersects or is inside <me>.
0312   [[nodiscard]] Standard_EXPORT bool IsOut(const Bnd_Box& Other) const;
0313 
0314   //! Returns False if the transformed <Box> intersects
0315   //! or is inside <me>.
0316   [[nodiscard]] Standard_EXPORT bool IsOut(const Bnd_Box& Other, const gp_Trsf& T) const;
0317 
0318   //! Returns False if the transformed <Box> intersects
0319   //! or is inside the transformed box <me>.
0320   [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Trsf& T1,
0321                                            const Bnd_Box& Other,
0322                                            const gp_Trsf& T2) const;
0323 
0324   //! Returns False if the flat band lying between two parallel
0325   //! lines represented by their reference points <P1>, <P2> and
0326   //! direction <D> intersects the box.
0327   [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Pnt& P1,
0328                                            const gp_Pnt& P2,
0329                                            const gp_Dir& D) const;
0330 
0331   //! Returns True if the point is inside or on the boundary of this box.
0332   [[nodiscard]] bool Contains(const gp_Pnt& theP) const { return !IsOut(theP); }
0333 
0334   //! Returns True if the other box intersects or is inside this box.
0335   [[nodiscard]] bool Intersects(const Bnd_Box& theOther) const { return !IsOut(theOther); }
0336 
0337   //! Computes the minimum distance between two boxes.
0338   [[nodiscard]] Standard_EXPORT double Distance(const Bnd_Box& Other) const;
0339 
0340   Standard_EXPORT void Dump() const;
0341 
0342   //! Computes the squared diagonal of me.
0343   [[nodiscard]] double SquareExtent() const noexcept
0344   {
0345     if (IsVoid())
0346     {
0347       return 0.0;
0348     }
0349 
0350     const double aDx = Xmax - Xmin + Gap + Gap;
0351     const double aDy = Ymax - Ymin + Gap + Gap;
0352     const double aDz = Zmax - Zmin + Gap + Gap;
0353     return aDx * aDx + aDy * aDy + aDz * aDz;
0354   }
0355 
0356   //! Returns a finite part of an infinite bounding box (returns self if this is already finite
0357   //! box). This can be a Void box in case if its sides has been defined as infinite (Open) without
0358   //! adding any finite points. WARNING! This method relies on Open flags, the infinite points added
0359   //! using Add() method will be returned as is.
0360   [[nodiscard]] Bnd_Box FinitePart() const noexcept
0361   {
0362     if (!HasFinitePart())
0363     {
0364       return Bnd_Box();
0365     }
0366 
0367     Bnd_Box aBox;
0368     aBox.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
0369     aBox.SetGap(Gap);
0370     return aBox;
0371   }
0372 
0373   //! Returns TRUE if this box has finite part.
0374   [[nodiscard]] bool HasFinitePart() const noexcept { return !IsVoid() && Xmax >= Xmin; }
0375 
0376   //! Dumps the content of me into the stream
0377   Standard_EXPORT void DumpJson(Standard_OStream& theOStream, int theDepth = -1) const;
0378 
0379   //! Inits the content of me from the stream
0380   Standard_EXPORT bool InitFromJson(const Standard_SStream& theSStream, int& theStreamPos);
0381 
0382 protected:
0383   //! Bit flags.
0384   enum MaskFlags
0385   {
0386     VoidMask  = 0x01,
0387     XminMask  = 0x02,
0388     XmaxMask  = 0x04,
0389     YminMask  = 0x08,
0390     YmaxMask  = 0x10,
0391     ZminMask  = 0x20,
0392     ZmaxMask  = 0x40,
0393     WholeMask = 0x7e
0394   };
0395 
0396 private:
0397   double Xmin  = RealLast();
0398   double Xmax  = -RealLast();
0399   double Ymin  = RealLast();
0400   double Ymax  = -RealLast();
0401   double Zmin  = RealLast();
0402   double Zmax  = -RealLast();
0403   double Gap   = 0.0;
0404   int    Flags = VoidMask;
0405 };
0406 
0407 #endif // _Bnd_Box_HeaderFile