You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

496 lines
13 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkBoundingBox.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkBoundingBox
* @brief Fast, simple class for dealing with 3D bounds
*
* vtkBoundingBox maintains a 3D axis aligned bounding box. It is very light
* weight and many of the member functions are in-lined so it is very fast.
* It is not derived from vtkObject so it can be allocated on the stack.
*
* @sa
* vtkBox
*/
#ifndef vtkBoundingBox_h
#define vtkBoundingBox_h
#include "vtkCommonDataModelModule.h" // For export macro
#include "vtkSystemIncludes.h"
class vtkPoints;
class VTKCOMMONDATAMODEL_EXPORT vtkBoundingBox
{
public:
//@{
/**
* Construct a bounding box with the min point set to
* VTK_DOUBLE_MAX and the max point set to VTK_DOUBLE_MIN.
*/
vtkBoundingBox();
vtkBoundingBox(const double bounds[6]);
vtkBoundingBox(double xMin, double xMax, double yMin, double yMax, double zMin, double zMax);
//@}
/**
* Copy constructor.
*/
vtkBoundingBox(const vtkBoundingBox& bbox);
/**
* Assignment Operator
*/
vtkBoundingBox& operator=(const vtkBoundingBox& bbox);
//@{
/**
* Equality operator.
*/
bool operator==(const vtkBoundingBox& bbox) const;
bool operator!=(const vtkBoundingBox& bbox) const;
//@}
//@{
/**
* Set the bounds explicitly of the box (using the VTK convention for
* representing a bounding box). Returns 1 if the box was changed else 0.
*/
void SetBounds(const double bounds[6]);
void SetBounds(double xMin, double xMax, double yMin, double yMax, double zMin, double zMax);
//@}
//@{
/**
* Compute the bounding box from an array of vtkPoints. It uses a fast
* path when possible. The second signature (with point uses) only considers
* points with ptUses[i] != 0 in the bounds calculation.
*/
static void ComputeBounds(vtkPoints* pts, double bounds[6]);
static void ComputeBounds(vtkPoints* pts, const unsigned char* ptUses, double bounds[6]);
//@}
//@{
/**
* Set the minimum point of the bounding box - if the min point
* is greater than the max point then the max point will also be changed.
*/
void SetMinPoint(double x, double y, double z);
void SetMinPoint(double p[3]);
//@}
//@{
/**
* Set the maximum point of the bounding box - if the max point
* is less than the min point then the min point will also be changed.
*/
void SetMaxPoint(double x, double y, double z);
void SetMaxPoint(double p[3]);
//@}
//@{
/**
* Returns 1 if the bounds have been set and 0 if the box is in its
* initialized state which is an inverted state.
*/
int IsValid() const;
static int IsValid(const double bounds[6]);
//@}
//@{
/**
* Change bounding box so it includes the point p. Note that the bounding
* box may have 0 volume if its bounds were just initialized.
*/
void AddPoint(double p[3]);
void AddPoint(double px, double py, double pz);
//@}
/**
* Change the bounding box to be the union of itself and the specified
* bbox.
*/
void AddBox(const vtkBoundingBox& bbox);
/**
* Adjust the bounding box so it contains the specified bounds (defined by
* the VTK representation (xmin,xmax, ymin,ymax, zmin,zmax).
*/
void AddBounds(const double bounds[]);
/**
* Intersect this box with bbox. The method returns 1 if both boxes are
* valid and they do have overlap else it will return 0. If 0 is returned
* the box has not been modified.
*/
int IntersectBox(const vtkBoundingBox& bbox);
/**
* Returns 1 if the boxes intersect else returns 0.
*/
int Intersects(const vtkBoundingBox& bbox) const;
/**
* Intersect this box with the half space defined by plane. Returns true
* if there is intersection---which implies that the box has been modified
* Returns false otherwise.
*/
bool IntersectPlane(double origin[3], double normal[3]);
/**
* Returns 1 if the min and max points of bbox are contained
* within the bounds of the specified box, else returns 0.
*/
int Contains(const vtkBoundingBox& bbox) const;
//@{
/**
* Get the bounds of the box (defined by VTK style).
*/
void GetBounds(double bounds[6]) const;
void GetBounds(
double& xMin, double& xMax, double& yMin, double& yMax, double& zMin, double& zMax) const;
//@}
/**
* Return the ith bounds of the box (defined by VTK style).
*/
double GetBound(int i) const;
//@{
/**
* Get the minimum point of the bounding box.
*/
const double* GetMinPoint() const VTK_SIZEHINT(3);
void GetMinPoint(double& x, double& y, double& z) const;
void GetMinPoint(double x[3]) const;
//@}
//@{
/**
* Get the maximum point of the bounding box.
*/
const double* GetMaxPoint() const VTK_SIZEHINT(3);
void GetMaxPoint(double& x, double& y, double& z) const;
void GetMaxPoint(double x[3]) const;
//@}
/**
* Get the ith corner of the bounding box. The points are ordered
* with i, then j, then k increasing.
*/
void GetCorner(int corner, double p[3]) const;
//@{
/**
* Returns 1 if the point is contained in the box else 0.
*/
vtkTypeBool ContainsPoint(double p[3]) const;
vtkTypeBool ContainsPoint(double px, double py, double pz) const;
//@}
/**
* Get the center of the bounding box.
*/
void GetCenter(double center[3]) const;
/**
* Get the length of each sode of the box.
*/
void GetLengths(double lengths[3]) const;
/**
* Return the length of the bounding box in the ith direction.
*/
double GetLength(int i) const;
/**
* Return the maximum length of the box.
*/
double GetMaxLength() const;
/**
* Return the length of the diagonal.
* \pre not_empty: this->IsValid()
*/
double GetDiagonalLength() const;
//@{
/**
* Expand the bounding box. Inflate(delta) expands by delta on each side,
* the box will grow by 2*delta in x, y, and z. Inflate(dx,dy,dz) expands
* by the given amounts in each of the x, y, z directions. Finally,
* Inflate() expands the bounds so that it has non-zero volume. Edges that
* are inflated are adjusted 1% of the longest edge. Or if an edge is
* zero length, the bounding box is inflated by 1 unit in that direction.
*/
void Inflate(double delta);
void Inflate(double deltaX, double deltaY, double deltaZ);
void Inflate();
//@}
//@{
/**
* Scale each dimension of the box by some given factor.
* If the box is not valid, it stays unchanged.
* If the scalar factor is negative, bounds are flipped: for example,
* if (xMin,xMax)=(-2,4) and sx=-3, (xMin,xMax) becomes (-12,6).
*/
void Scale(double s[3]);
void Scale(double sx, double sy, double sz);
//@}
//@{
/**
* Scale each dimension of the box by some given factor, with the origin of
* the bounding box the center of the scaling. If the box is not
* valid, it is not changed.
*/
void ScaleAboutCenter(double s);
void ScaleAboutCenter(double s[3]);
void ScaleAboutCenter(double sx, double sy, double sz);
//@}
/**
* Compute the number of divisions in the z-y-z directions given a target
* number of total bins (i.e., product of divisions in the x-y-z
* directions). The computation is done in such a way as to create near
* cuboid bins. Also note that the returned bounds may be different than
* the bounds defined in this class, as the bounds in the z-y-z directions
* can never be <= 0. Note that the total number of divisions
* (divs[0]*divs[1]*divs[2]) should be less than or equal to the target number
* of bins, but it may be slightly larger in certain cases.
*/
vtkIdType ComputeDivisions(vtkIdType totalBins, double bounds[6], int divs[3]) const;
/**
* Returns the box to its initialized state.
*/
void Reset();
protected:
double MinPnt[3], MaxPnt[3];
};
inline void vtkBoundingBox::Reset()
{
this->MinPnt[0] = this->MinPnt[1] = this->MinPnt[2] = VTK_DOUBLE_MAX;
this->MaxPnt[0] = this->MaxPnt[1] = this->MaxPnt[2] = VTK_DOUBLE_MIN;
}
inline void vtkBoundingBox::GetBounds(
double& xMin, double& xMax, double& yMin, double& yMax, double& zMin, double& zMax) const
{
xMin = this->MinPnt[0];
xMax = this->MaxPnt[0];
yMin = this->MinPnt[1];
yMax = this->MaxPnt[1];
zMin = this->MinPnt[2];
zMax = this->MaxPnt[2];
}
inline double vtkBoundingBox::GetBound(int i) const
{
// If i is odd then when are returning a part of the max bounds
// else part of the min bounds is requested. The exact component
// needed is i /2 (or i right shifted by 1
return ((i & 0x1) ? this->MaxPnt[i >> 1] : this->MinPnt[i >> 1]);
}
inline const double* vtkBoundingBox::GetMinPoint() const
{
return this->MinPnt;
}
inline void vtkBoundingBox::GetMinPoint(double x[3]) const
{
x[0] = this->MinPnt[0];
x[1] = this->MinPnt[1];
x[2] = this->MinPnt[2];
}
inline const double* vtkBoundingBox::GetMaxPoint() const
{
return this->MaxPnt;
}
inline void vtkBoundingBox::GetMaxPoint(double x[3]) const
{
x[0] = this->MaxPnt[0];
x[1] = this->MaxPnt[1];
x[2] = this->MaxPnt[2];
}
inline int vtkBoundingBox::IsValid() const
{
return ((this->MinPnt[0] <= this->MaxPnt[0]) && (this->MinPnt[1] <= this->MaxPnt[1]) &&
(this->MinPnt[2] <= this->MaxPnt[2]));
}
inline int vtkBoundingBox::IsValid(const double bounds[6])
{
return (bounds[0] <= bounds[1] && bounds[2] <= bounds[3] && bounds[4] <= bounds[5]);
}
inline double vtkBoundingBox::GetLength(int i) const
{
return this->MaxPnt[i] - this->MinPnt[i];
}
inline void vtkBoundingBox::GetLengths(double lengths[3]) const
{
lengths[0] = this->GetLength(0);
lengths[1] = this->GetLength(1);
lengths[2] = this->GetLength(2);
}
inline void vtkBoundingBox::GetCenter(double center[3]) const
{
center[0] = 0.5 * (this->MaxPnt[0] + this->MinPnt[0]);
center[1] = 0.5 * (this->MaxPnt[1] + this->MinPnt[1]);
center[2] = 0.5 * (this->MaxPnt[2] + this->MinPnt[2]);
}
inline void vtkBoundingBox::SetBounds(const double bounds[6])
{
this->SetBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
}
inline void vtkBoundingBox::GetBounds(double bounds[6]) const
{
this->GetBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
}
inline vtkBoundingBox::vtkBoundingBox()
{
this->Reset();
}
inline vtkBoundingBox::vtkBoundingBox(const double bounds[6])
{
this->Reset();
this->SetBounds(bounds);
}
inline vtkBoundingBox::vtkBoundingBox(
double xMin, double xMax, double yMin, double yMax, double zMin, double zMax)
{
this->Reset();
this->SetBounds(xMin, xMax, yMin, yMax, zMin, zMax);
}
inline vtkBoundingBox::vtkBoundingBox(const vtkBoundingBox& bbox)
{
this->MinPnt[0] = bbox.MinPnt[0];
this->MinPnt[1] = bbox.MinPnt[1];
this->MinPnt[2] = bbox.MinPnt[2];
this->MaxPnt[0] = bbox.MaxPnt[0];
this->MaxPnt[1] = bbox.MaxPnt[1];
this->MaxPnt[2] = bbox.MaxPnt[2];
}
inline vtkBoundingBox& vtkBoundingBox::operator=(const vtkBoundingBox& bbox)
{
this->MinPnt[0] = bbox.MinPnt[0];
this->MinPnt[1] = bbox.MinPnt[1];
this->MinPnt[2] = bbox.MinPnt[2];
this->MaxPnt[0] = bbox.MaxPnt[0];
this->MaxPnt[1] = bbox.MaxPnt[1];
this->MaxPnt[2] = bbox.MaxPnt[2];
return *this;
}
inline bool vtkBoundingBox::operator==(const vtkBoundingBox& bbox) const
{
return ((this->MinPnt[0] == bbox.MinPnt[0]) && (this->MinPnt[1] == bbox.MinPnt[1]) &&
(this->MinPnt[2] == bbox.MinPnt[2]) && (this->MaxPnt[0] == bbox.MaxPnt[0]) &&
(this->MaxPnt[1] == bbox.MaxPnt[1]) && (this->MaxPnt[2] == bbox.MaxPnt[2]));
}
inline bool vtkBoundingBox::operator!=(const vtkBoundingBox& bbox) const
{
return !((*this) == bbox);
}
inline void vtkBoundingBox::SetMinPoint(double p[3])
{
this->SetMinPoint(p[0], p[1], p[2]);
}
inline void vtkBoundingBox::SetMaxPoint(double p[3])
{
this->SetMaxPoint(p[0], p[1], p[2]);
}
inline void vtkBoundingBox::GetMinPoint(double& x, double& y, double& z) const
{
x = this->MinPnt[0];
y = this->MinPnt[1];
z = this->MinPnt[2];
}
inline void vtkBoundingBox::GetMaxPoint(double& x, double& y, double& z) const
{
x = this->MaxPnt[0];
y = this->MaxPnt[1];
z = this->MaxPnt[2];
}
inline vtkTypeBool vtkBoundingBox::ContainsPoint(double px, double py, double pz) const
{
if ((px < this->MinPnt[0]) || (px > this->MaxPnt[0]))
{
return 0;
}
if ((py < this->MinPnt[1]) || (py > this->MaxPnt[1]))
{
return 0;
}
if ((pz < this->MinPnt[2]) || (pz > this->MaxPnt[2]))
{
return 0;
}
return 1;
}
inline vtkTypeBool vtkBoundingBox::ContainsPoint(double p[3]) const
{
return this->ContainsPoint(p[0], p[1], p[2]);
}
inline void vtkBoundingBox::GetCorner(int corner, double p[3]) const
{
if ((corner < 0) || (corner > 7))
{
p[0] = VTK_DOUBLE_MAX;
p[1] = VTK_DOUBLE_MAX;
p[2] = VTK_DOUBLE_MAX;
return; // out of bounds
}
int ix = (corner & 1) ? 1 : 0; // 0,1,0,1,0,1,0,1
int iy = ((corner >> 1) & 1) ? 1 : 0; // 0,0,1,1,0,0,1,1
int iz = (corner >> 2) ? 1 : 0; // 0,0,0,0,1,1,1,1
const double* pts[2] = { this->MinPnt, this->MaxPnt };
p[0] = pts[ix][0];
p[1] = pts[iy][1];
p[2] = pts[iz][2];
}
#endif
// VTK-HeaderTest-Exclude: vtkBoundingBox.h