mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-09 15:43:07 -06:00
420 lines
13 KiB
C++
420 lines
13 KiB
C++
//##################################################################################################
|
|
//
|
|
// Custom Visualization Core library
|
|
// Copyright (C) 2011-2013 Ceetron AS
|
|
//
|
|
// This library may be used under the terms of either the GNU General Public License or
|
|
// the GNU Lesser General Public License as follows:
|
|
//
|
|
// GNU General Public License Usage
|
|
// This library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
|
// for more details.
|
|
//
|
|
// GNU Lesser General Public License Usage
|
|
// This library is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation; either version 2.1 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
|
// for more details.
|
|
//
|
|
//##################################################################################################
|
|
|
|
|
|
#include "cvfBase.h"
|
|
#include "cvfBoundingBox.h"
|
|
#include "cvfString.h"
|
|
|
|
#include <limits>
|
|
|
|
namespace cvf {
|
|
|
|
|
|
|
|
//==================================================================================================
|
|
///
|
|
/// \class cvf::BoundingBox
|
|
/// \ingroup Geometry
|
|
///
|
|
/// The BoundingBox class implements an axis-aligned bounding box.
|
|
///
|
|
//==================================================================================================
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
BoundingBox::BoundingBox()
|
|
{
|
|
reset();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
BoundingBox::BoundingBox(const Vec3d& min, const Vec3d& max)
|
|
: m_min(min), m_max(max)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
BoundingBox::BoundingBox(const Vec3f& min, const Vec3f& max)
|
|
: m_min(min), m_max(max)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
BoundingBox::BoundingBox(const BoundingBox& other)
|
|
: m_min(other.m_min),
|
|
m_max(other.m_max)
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
BoundingBox& BoundingBox::operator=(const BoundingBox& rhs)
|
|
{
|
|
m_min = rhs.m_min;
|
|
m_max = rhs.m_max;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Initialize bounding box
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::reset()
|
|
{
|
|
const double maxDouble = std::numeric_limits<double>::max();
|
|
|
|
m_max.set(-maxDouble, -maxDouble, -maxDouble);
|
|
m_min.set( maxDouble, maxDouble, maxDouble);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Returns false if no input has been given
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool BoundingBox::isValid() const
|
|
{
|
|
if (m_min.x() <= m_max.x() &&
|
|
m_min.y() <= m_max.y() &&
|
|
m_min.z() <= m_max.z())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::add(const Vec3d& point)
|
|
{
|
|
if (point.x() < m_min.x()) m_min.x() = point.x();
|
|
if (point.y() < m_min.y()) m_min.y() = point.y();
|
|
if (point.z() < m_min.z()) m_min.z() = point.z();
|
|
|
|
if (point.x() > m_max.x()) m_max.x() = point.x();
|
|
if (point.y() > m_max.y()) m_max.y() = point.y();
|
|
if (point.z() > m_max.z()) m_max.z() = point.z();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::add(const Vec3f& point)
|
|
{
|
|
if (point.x() < m_min.x()) m_min.x() = point.x();
|
|
if (point.y() < m_min.y()) m_min.y() = point.y();
|
|
if (point.z() < m_min.z()) m_min.z() = point.z();
|
|
|
|
if (point.x() > m_max.x()) m_max.x() = point.x();
|
|
if (point.y() > m_max.y()) m_max.y() = point.y();
|
|
if (point.z() > m_max.z()) m_max.z() = point.z();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::add(const Vec3dArray& points)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < points.size(); i++)
|
|
{
|
|
add(points[i]);
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::add(const Vec3fArray& points)
|
|
{
|
|
size_t i;
|
|
for (i = 0; i < points.size(); i++)
|
|
{
|
|
add(points[i]);
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::add(const BoundingBox& bb)
|
|
{
|
|
if (bb.isValid())
|
|
{
|
|
add(bb.min());
|
|
add(bb.max());
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Computes center of the bounding box
|
|
//--------------------------------------------------------------------------------------------------
|
|
Vec3d BoundingBox::center() const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
|
|
return (m_min + m_max) / 2.0;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Computes the total size of the bounding box
|
|
//--------------------------------------------------------------------------------------------------
|
|
Vec3d BoundingBox::extent() const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
|
|
return (m_max - m_min);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Compute radius as half the length of the box's diagonal
|
|
//--------------------------------------------------------------------------------------------------
|
|
double BoundingBox::radius() const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
|
|
return extent().length() / 2.0;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const Vec3d& BoundingBox::min() const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
|
|
return m_min;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
const Vec3d& BoundingBox::max() const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
|
|
return m_max;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Check if the bounding box contains the specified point
|
|
///
|
|
/// Note that a point on the box's surface is classified as being contained
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool BoundingBox::contains(const Vec3d& point) const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
|
|
if (point.x() >= m_min.x() && point.x() <= m_max.x() &&
|
|
point.y() >= m_min.y() && point.y() <= m_max.y() &&
|
|
point.z() >= m_min.z() && point.z() <= m_max.z())
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
bool BoundingBox::intersects(const BoundingBox& box) const
|
|
{
|
|
CVF_TIGHT_ASSERT(isValid());
|
|
CVF_TIGHT_ASSERT(box.isValid());
|
|
|
|
if (m_max.x() < box.m_min.x() || m_min.x() > box.m_max.x()) return false;
|
|
if (m_max.y() < box.m_min.y() || m_min.y() > box.m_max.y()) return false;
|
|
if (m_max.z() < box.m_min.z() || m_min.z() > box.m_max.z()) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Get corner points of box
|
|
///
|
|
/// \param corners Array of Vec3d. Must be allocated 8 vectors long.
|
|
///
|
|
/// <PRE>
|
|
/// 7---------6
|
|
/// /| /| |z
|
|
/// / | / | | / y
|
|
/// 4---------5 | |/
|
|
/// | 3------|--2 *---x
|
|
/// | / | /
|
|
/// |/ |/
|
|
/// 0---------1 </PRE>
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::cornerVertices(Vec3d corners[8]) const
|
|
{
|
|
corners[0].set(m_min.x(), m_min.y(), m_min.z());
|
|
corners[1].set(m_max.x(), m_min.y(), m_min.z());
|
|
corners[2].set(m_max.x(), m_max.y(), m_min.z());
|
|
corners[3].set(m_min.x(), m_max.y(), m_min.z());
|
|
corners[4].set(m_min.x(), m_min.y(), m_max.z());
|
|
corners[5].set(m_max.x(), m_min.y(), m_max.z());
|
|
corners[6].set(m_max.x(), m_max.y(), m_max.z());
|
|
corners[7].set(m_min.x(), m_max.y(), m_max.z());
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Expands the bounding box by the given amount in all three directions
|
|
///
|
|
/// If a bounding box is expanded by 2, the bounding box's size will increase by 2 in each direction
|
|
/// \sa extent()
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::expand(double amount)
|
|
{
|
|
double half = amount/2;
|
|
m_min.x() -= half;
|
|
m_min.y() -= half;
|
|
m_min.z() -= half;
|
|
m_max.x() += half;
|
|
m_max.y() += half;
|
|
m_max.z() += half;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Transform the min and max coordinate with the given transformation matrix
|
|
//--------------------------------------------------------------------------------------------------
|
|
void BoundingBox::transform(const Mat4d& matrix)
|
|
{
|
|
// Check if box is invalid, and don't transform if so
|
|
if (!isValid()) return;
|
|
|
|
BoundingBox newBox;
|
|
newBox.reset();
|
|
|
|
Vec3d node;
|
|
|
|
node.set(m_min.x(), m_min.y(), m_min.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_max.x(), m_min.y(), m_min.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_max.x(), m_max.y(), m_min.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_min.x(), m_max.y(), m_min.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_min.x(), m_min.y(), m_max.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_max.x(), m_min.y(), m_max.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_max.x(), m_max.y(), m_max.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
node.set(m_min.x(), m_max.y(), m_max.z());
|
|
node.transformPoint(matrix);
|
|
newBox.add(node);
|
|
|
|
*this = newBox;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
/// Returns this BoundingBox transformed with the given transformation matrix
|
|
//--------------------------------------------------------------------------------------------------
|
|
const BoundingBox BoundingBox::getTransformed(const Mat4d& matrix) const
|
|
{
|
|
BoundingBox box(*this);
|
|
box.transform(matrix);
|
|
|
|
return box;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
String BoundingBox::debugString() const
|
|
{
|
|
String str = "BoundingBox:";
|
|
str += " min: x=" + String::number(m_min.x()) + " y=" + String::number(m_min.y()) + " z=" + String::number(m_min.z());
|
|
str += " max: x=" + String::number(m_max.x()) + " y=" + String::number(m_max.y()) + " z=" + String::number(m_max.z());
|
|
return str;
|
|
}
|
|
|
|
|
|
} // namespace cvf
|
|
|