Program Listing for File aabb.cc

Return to documentation for file (src/aabb.cc)

/*
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                     *
 * The ACME project                                                    *
 *                                                                     *
 * Copyright (c) 2020, Davide Stocco and Enrico Bertolazzi.            *
 *                                                                     *
 * The ACME project and its components are supplied under the terms of *
 * the open source BSD 2-Clause License. The contents of the ACME      *
 * project and its components may not be copied or disclosed except in *
 * accordance with the terms of the BSD 2-Clause License.              *
 *                                                                     *
 * URL: https://opensource.org/licenses/BSD-2-Clause                   *
 *                                                                     *
 *    Davide Stocco                                                    *
 *    Department of Industrial Engineering                             *
 *    University of Trento                                             *
 *    e-mail: davide.stocco@unitn.it                                   *
 *                                                                     *
 *    Enrico Bertolazzi                                                *
 *    Department of Industrial Engineering                             *
 *    University of Trento                                             *
 *    e-mail: enrico.bertolazzi@unitn.it                               *
 *                                                                     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/


#ifndef DOXYGEN_SHOULD_SKIP_THIS

#include "acme.hh"

namespace acme
{

  /*\
   |               _     _
   |    __ _  __ _| |__ | |_
   |   / _` |/ _` | '_ \| '_ \
   |  | (_| | (_| | |_) | |_) |
   |   \__,_|\__,_|_.__/|_.__/
   |
  \*/

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  aabb::aabb(void)
  {
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  aabb::aabb(
    real    min_x,
    real    min_y,
    real    min_z,
    real    max_x,
    real    max_y,
    real    max_z,
    integer id,
    integer ipos
  )
    : m_min(min_x, min_y, min_z),
      m_max(max_x, max_y, max_z),
      m_id(id),
      m_pos(ipos)
  {
    this->updateMaxMin();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  aabb::aabb(
    point   const & min,
    point   const & max,
    integer         id,
    integer         ipos
  )
    : m_min(min),
      m_max(max),
      m_id(id),
      m_pos(ipos)
  {
    this->updateMaxMin();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  aabb::aabb(
    std::vector<aabb::ptr> const & boxes,
    integer                        id,
    integer                        ipos
  )
    : m_min(NAN_POINT),
      m_max(NAN_POINT),
      m_id(id),
      m_pos(ipos)
  {
    this->merged(boxes);
    this->updateMaxMin();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::clear(void)
  {
    this->m_min = NAN_POINT;
    this->m_max = NAN_POINT;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  bool
  aabb::isApprox(
    aabb const & aabb_in,
    real         tolerance
  )
    const
  {
    return this->m_min.isApprox(aabb_in.m_min, tolerance) &&
           this->m_max.isApprox(aabb_in.m_max, tolerance);
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  bool
  aabb::checkMaxMin(void)
    const
  {
    return this->m_max.x() >= this->m_min.x() &&
           this->m_max.y() >= this->m_min.y() &&
           this->m_max.z() >= this->m_min.z();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  bool
  aabb::updateMaxMin(void)
  {
    bool output = true;
    real point_max_tmp, point_min_tmp;
    for (integer i = 0; i < 3; ++i)
    {
      point_max_tmp = this->m_max[i];
      point_min_tmp = this->m_min[i];
      if (point_max_tmp < point_min_tmp)
      {
        this->m_max[i] = point_min_tmp;
        this->m_min[i] = point_max_tmp;
        output         = false;
      }
    }
    return output;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  point const &
  aabb::min(void)
    const
  {
    return this->m_min;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  point &
  aabb::min(void)
  {
    return this->m_min;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  real const &
  aabb::min(
    integer i
  )
    const
  {
    return this->m_min[i];
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  real &
  aabb::min(
    integer i
  )
  {
    return this->m_min[i];
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::min(
    real x,
    real y,
    real z
  )
  {
    this->m_min.x() = x;
    this->m_min.y() = y;
    this->m_min.z() = z;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  point const &
  aabb::max(void)
    const
  {
    return this->m_max;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  point &
  aabb::max(void)
  {
    return this->m_max;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  real const &
  aabb::max(
    integer i
  )
    const
  {
    return this->m_max[i];
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  real &
  aabb::max(
    integer i
  )
  {
    return this->m_max[i];
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::max(
    real x,
    real y,
    real z
  )
  {
    this->m_max.x() = x;
    this->m_max.y() = y;
    this->m_max.z() = z;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  bool
  aabb::intersects(
    aabb const & aabb_in
  )
    const
  {
    return this->m_min.x() <= aabb_in.m_max.x() && this->m_max.x() >= aabb_in.m_min.x() &&
           this->m_min.y() <= aabb_in.m_max.y() && this->m_max.y() >= aabb_in.m_min.y() &&
           this->m_min.z() <= aabb_in.m_max.z() && this->m_max.z() >= aabb_in.m_min.z();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::merged(
    std::vector<aabb::ptr> const & boxes
  )
  {
    if (boxes.empty())
    {
      this->m_min = point::Constant(real(0.0));
      this->m_max = point::Constant(real(0.0));
    }
    else
    {
      std::vector<aabb::ptr>::const_iterator it = boxes.begin();

      this->m_min = (*it)->m_min;
      this->m_max = (*it)->m_max;

      for (++it; it != boxes.end(); ++it)
      {
        aabb const & cur_box = **it;
        if (cur_box.m_min.x() < this->m_min.x())
          {this->m_min.x() = cur_box.m_min.x();}
        if (cur_box.m_min.y() < this->m_min.y())
          {this->m_min.y() = cur_box.m_min.y();}
        if (cur_box.m_min.z() < this->m_min.z())
          {this->m_min.z() = cur_box.m_min.z();}
        if (cur_box.m_max.x() > this->m_max.x())
          {this->m_max.x() = cur_box.m_max.x();}
        if (cur_box.m_max.y() > this->m_max.y())
          {this->m_max.y() = cur_box.m_max.y();}
        if (cur_box.m_max.z() > this->m_max.z())
          {this->m_max.z() = cur_box.m_max.z();}
      }
    }
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  real
  aabb::centerDistance(
    point const & point_in
  )
    const
  {
    point center((this->m_max + this->m_min) / real(2.0));
    point point_max_centered(this->m_max - center);
    point point_centered(point_in - center);
    real  x_scale = std::abs(real(1.0) / point_max_centered.x());
    real  y_scale = std::abs(real(1.0) / point_max_centered.y());
    real  z_scale = std::abs(real(1.0) / point_max_centered.z());
    real  dx      = std::max(real(0.0), std::abs(point_centered.x()) * x_scale - real(1.0)) / x_scale;
    real  dy      = std::max(real(0.0), std::abs(point_centered.y()) * y_scale - real(1.0)) / y_scale;
    real  dz      = std::max(real(0.0), std::abs(point_centered.z()) * z_scale - real(1.0)) / z_scale;
    return std::sqrt(dx * dx + dy * dy + dz * dz);
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  real
  aabb::exteriorDistance(
    point const & point_in
  )
    const
  {
    real dx = std::max(std::abs(point_in.x() - this->m_min.x()), std::abs(point_in.x() - this->m_max.x()));
    real dy = std::max(std::abs(point_in.y() - this->m_min.y()), std::abs(point_in.y() - this->m_max.y()));
    real dz = std::max(std::abs(point_in.z() - this->m_min.z()), std::abs(point_in.z() - this->m_max.z()));
    return std::sqrt(dx * dx + dy * dy + dz * dz);
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::clamp(
    point const & point0_in,
    point const & point1_in,
    point const & point2_in
  )
  {
    this->m_min.x() = std::min(point0_in.x(), std::min(point1_in.x(), point2_in.x()));
    this->m_min.y() = std::min(point0_in.y(), std::min(point1_in.y(), point2_in.y()));
    this->m_min.z() = std::min(point0_in.z(), std::min(point1_in.z(), point2_in.z()));
    this->m_max.x() = std::max(point0_in.x(), std::max(point1_in.x(), point2_in.x()));
    this->m_max.y() = std::max(point0_in.y(), std::max(point1_in.y(), point2_in.y()));
    this->m_max.z() = std::max(point0_in.z(), std::max(point1_in.z(), point2_in.z()));
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::clamp(
    point const point_in[3]
  )
  {
    this->m_min.x() = std::min(point_in[0].x(), std::min(point_in[1].x(), point_in[2].x()));
    this->m_min.y() = std::min(point_in[0].y(), std::min(point_in[1].y(), point_in[2].y()));
    this->m_min.z() = std::min(point_in[0].z(), std::min(point_in[1].z(), point_in[2].z()));
    this->m_max.x() = std::max(point_in[0].x(), std::max(point_in[1].x(), point_in[2].x()));
    this->m_max.y() = std::max(point_in[0].y(), std::max(point_in[1].y(), point_in[2].y()));
    this->m_max.z() = std::max(point_in[0].z(), std::max(point_in[1].z(), point_in[2].z()));
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  integer const &
  aabb::id(void)
    const
  {
    return this->m_id;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  integer &
  aabb::id(void)
  {
    return this->m_id;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  integer const &
  aabb::pos(void)
    const
  {
    return this->m_pos;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  integer &
  aabb::pos(void)
  {
    return this->m_pos;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  void
  aabb::translate(
    point const & vector_in
  )
  {
    this->m_min = vector_in + this->m_min;
    this->m_max = vector_in + this->m_max;
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  bool
  aabb::isInside(
    point const & point_in,
    real          /*tolerance*/
  )
    const
  {
    return this->m_min.x() <= point_in.x() &&
           this->m_min.y() <= point_in.y() &&
           this->m_min.z() <= point_in.z() &&
           this->m_max.x() >= point_in.x() &&
           this->m_max.y() >= point_in.y() &&
           this->m_max.z() >= point_in.z();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  bool
  aabb::isDegenerated(
    real tolerance
  )
    const
  {
    return this->m_min.isApprox(this->m_max, tolerance) &&
           this->checkMaxMin();
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

} // namespace acme

#endif