//====================================================================================================================== // // This file is part of waLBerla. waLBerla 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. // // waLBerla 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 // for more details. // // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // //! \file GenericAABB.impl.h //! \ingroup core //! \author Christian Godenschwager <christian.godenschwager@fau.de> // //====================================================================================================================== namespace walberla { namespace math { /** * \brief Builds a default GenericAABB * * \post minCorner = maxCorner = (0,0,0) */ template< typename T > GenericAABB< T >::GenericAABB() : minCorner_( value_type(0), value_type(0), value_type(0) ), maxCorner_( value_type(0), value_type(0), value_type(0) ) { WALBERLA_ASSERT( checkInvariant() ); WALBERLA_ASSERT( empty() ); } /** * \brief Copy constructor for GenericAABBs of different value_type * * \tparam U value_type of other GenericAABB * * \param other other GenericAABB */ template< typename T > template< typename U > inline GenericAABB< T >::GenericAABB( const GenericAABB< U > & other ) : minCorner_( other.minCorner() ), maxCorner_( other.maxCorner() ) { WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a GenericAABB from two arbitrary points * * \param corner0 first corner spanning the AABB * \param corner1 second corner spanning the AABB */ template< typename T > GenericAABB< T >::GenericAABB( const vector_type & corner0, const vector_type & corner1 ) { for( uint_t i = 0; i < 3; ++i ) { if( corner0[i] < corner1[i] ) { minCorner_[i] = corner0[i]; maxCorner_[i] = corner1[i]; } else { minCorner_[i] = corner1[i]; maxCorner_[i] = corner0[i]; } } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a GenericAABB from two arbitrary points given with their coordinates * * \param x0 x-coordinate of the first corner spanning the AABB * \param y0 y-coordinate of the first corner spanning the AABB * \param z0 z-coordinate of the first corner spanning the AABB * \param x1 x-coordinate of the second corner spanning the AABB * \param y1 y-coordinate of the second corner spanning the AABB * \param z1 z-coordinate of the second corner spanning the AABB */ template< typename T > GenericAABB< T >::GenericAABB( const value_type x0, const value_type y0, const value_type z0, const value_type x1, const value_type y1, const value_type z1 ) { if( x0 < x1 ) { minCorner_[0] = x0; maxCorner_[0] = x1; } else { minCorner_[0] = x1; maxCorner_[0] = x0; } if( y0 < y1 ) { minCorner_[1] = y0; maxCorner_[1] = y1; } else { minCorner_[1] = y1; maxCorner_[1] = y0; } if( z0 < z1 ) { minCorner_[2] = z0; maxCorner_[2] = z1; } else { minCorner_[2] = z1; maxCorner_[2] = z0; } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a default GenericAABB by merging a Sequence of points or GenericAABBs * * \tparam InputIterator ForwardIterator. Must dereference to Vector3< T > or GenericAABB< T >. * * \param first first element of sequence [first, last) * \param last final element of sequence [first, last) * * \post first == last => minCorner = maxCorner = (0,0,0) */ template< typename T > template< typename InputIterator > GenericAABB< T >::GenericAABB( InputIterator first, InputIterator last ) : minCorner_( std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::max() ), maxCorner_( -std::numeric_limits<value_type>::max(), -std::numeric_limits<value_type>::max(), -std::numeric_limits<value_type>::max() ) { if( first != last ) { merge( first, last ); } else { init(); } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a GenericAABB from a min- and a maxCorner * * \param theMinCorner corner with minimal values * \param theMaxCorner corner with maximal values * * \pre theMinCorner.x <= theMaxCorner.x && theMinCorner.y <= theMaxCorner.y && theMinCorner.z <= theMaxCorner.z */ template< typename T > GenericAABB< T >::GenericAABB( const vector_type & theMinCorner, const vector_type & theMaxCorner, MinMaxCornerGivenT ) : minCorner_( theMinCorner ), maxCorner_( theMaxCorner ) { WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a GenericAABB as an intersection of two other GenericAABBs * * \param lhs an arbitrary GenericAABB * \param rhs an arbitrary GenericAABB * * \post lhs does not intersect rhs => minCorner = maxCorner ) */ template< typename T > GenericAABB< T >::GenericAABB( const GenericAABB & lhs, const GenericAABB & rhs ) : minCorner_( std::max( lhs.minCorner_[0], rhs.minCorner_[0] ), std::max( lhs.minCorner_[1], rhs.minCorner_[1] ), std::max( lhs.minCorner_[2], rhs.minCorner_[2] ) ), maxCorner_( std::max( minCorner_[0], std::min( lhs.maxCorner_[0], rhs.maxCorner_[0] ) ), std::max( minCorner_[1], std::min( lhs.maxCorner_[1], rhs.maxCorner_[1] ) ), std::max( minCorner_[2], std::min( lhs.maxCorner_[2], rhs.maxCorner_[2] ) ) ) { WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a GenericAABB from a min- and a maxCorner * * \param minX x-coordinate of the minCorner * \param minY y-coordinate of the minCorner * \param minZ z-coordinate of the minCorner * \param maxX x-coordinate of the maxCorner * \param maxY y-coordinate of the maxCorner * \param maxZ z-coordinate of the maxCorner * * \pre x0 <= x1 && y0 <= y1 && z0 <= z1 */ template< typename T > GenericAABB< T >::GenericAABB( const value_type minX, const value_type minY, const value_type minZ, const value_type maxX, const value_type maxY, const value_type maxZ, MinMaxCornerGivenT ) : minCorner_( minX, minY, minZ ), maxCorner_( maxX, maxY, maxZ ) { WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Builds a GenericAABB from a min- and a maxCorner * * \param minCorner corner with minimal values * \param maxCorner corner with maximal values * * \pre minCorner.x <= maxCorner.x && minCorner.y <= maxCorner.y && minCorner.z <= maxCorner.z */ template< typename T > GenericAABB< T > GenericAABB< T >::createFromMinMaxCorner( const vector_type & theMinCorner, const vector_type & theMaxCorner ) { return GenericAABB< T >( theMinCorner, theMaxCorner, MinMaxCornerGivenT() ); } /** * \brief Builds a GenericAABB from a min- and a maxCorner * * \param minX x-coordinate of the minCorner * \param minY y-coordinate of the minCorner * \param minZ z-coordinate of the minCorner * \param maxX x-coordinate of the maxCorner * \param maxY y-coordinate of the maxCorner * \param maxZ z-coordinate of the maxCorner * * \pre x0 <= x1 && y0 <= y1 && z0 <= z1 */ template< typename T > GenericAABB< T > GenericAABB< T >::createFromMinMaxCorner( const value_type minX, const value_type minY, const value_type minZ, const value_type maxX, const value_type maxY, const value_type maxZ ) { return GenericAABB< T >( minX, minY, minZ, maxX, maxY, maxZ, MinMaxCornerGivenT() ); } /** * \brief Assignment operator for GenericAABBs of different value_type * * \tparam U value_type of other GenericAABB * * \param other other GenericAABB */ template< typename T > template< typename U > inline GenericAABB< T > & GenericAABB< T >::operator=( const GenericAABB< U > & other ) { minCorner_ = other.minCorner_(); maxCorner_ = other.maxCorner_(); return *this; } /** * \brief Provides access to the corner with minimal values * * \returns the corner with minimal values */ template< typename T > const typename GenericAABB< T >::vector_type & GenericAABB< T >::minCorner() const { return minCorner_; } /** * \brief Provides access to the corner with maximal values * * \returns the corner with maximal values */ template< typename T > const typename GenericAABB< T >::vector_type & GenericAABB< T >::maxCorner() const { return maxCorner_; } /** * \brief Provides access to the x-component of the corner with minimal values * * \returns the x-component of the corner with minimal values */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::xMin() const { return minCorner_[0]; } /** * \brief Provides access to the y-component of the corner with minimal values * * \returns the y-component of the corner with minimal values */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::yMin() const { return minCorner_[1]; } /** * \brief Provides access to the z-component of the corner with minimal values * * \returns the z-component of the corner with minimal values */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::zMin() const { return minCorner_[2]; } /** * \brief Provides access to the x-component of the corner with maximal values * * \returns the x-component of the corner with maximal values */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::xMax() const { return maxCorner_[0]; } /** * \brief Provides access to the y-component of the corner with maximal values * * \returns the y-component of the corner with maximal values */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::yMax() const { return maxCorner_[1]; } /** * \brief Provides access to the z-component of the corner with maximal values * * \returns the z-component of the corner with maximal values */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::zMax() const { return maxCorner_[2]; } /** * \brief Checks whether the GenericAABB is empty * * \returns true, if the GenericAABB is empty(), false else */ template< typename T > bool GenericAABB< T >::empty() const { return walberla::isIdentical( minCorner_[0], maxCorner_[0] ) || walberla::isIdentical( minCorner_[1], maxCorner_[1] ) || walberla::isIdentical( minCorner_[2], maxCorner_[2] ); } /** * \brief Provides access to a vector of the genericAABBs extends * * \returns A vector with the GenericAABBs extends in x-, y-, and z-Direction */ template< typename T > typename GenericAABB< T >::vector_type GenericAABB< T >::sizes() const { WALBERLA_ASSERT( checkInvariant() ); return vector_type( maxCorner_[0] - minCorner_[0], maxCorner_[1] - minCorner_[1], maxCorner_[2] - minCorner_[2] ); } /** * \brief Provides access to one of the extends of the genericAABB * * \param index Determines the axis of which the extend is given: 0 -> x, 1 -> y, 2 -> z * * \returns The extend of the GenericAABB on the requested axis */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::size( const uint_t index ) const { WALBERLA_ASSERT( checkInvariant() ); return maxCorner_[index] - minCorner_[index]; } /** * \brief Provides access to the extend of the genericAABB in x direction * * \returns The extend of the GenericAABB on the x axis */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::xSize() const { WALBERLA_ASSERT( checkInvariant() ); return maxCorner_[0] - minCorner_[0]; } /** * \brief Provides access to the extend of the genericAABB in y direction * * \returns The extend of the GenericAABB on the y axis */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::ySize() const { WALBERLA_ASSERT( checkInvariant() ); return maxCorner_[1] - minCorner_[1]; } /** * \brief Provides access to the extend of the genericAABB in z direction * * \returns The extend of the GenericAABB on the z axis */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::zSize() const { WALBERLA_ASSERT( checkInvariant() ); return maxCorner_[2] - minCorner_[2]; } /** * \brief Calculates the volume of the genericAABB * * \returns The calculated volume * * \invariant empty() => 0 */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::volume() const { WALBERLA_ASSERT( checkInvariant() ); return ( maxCorner_[0] - minCorner_[0] ) * ( maxCorner_[1] - minCorner_[1] ) * ( maxCorner_[2] - minCorner_[2] ); } /** * \brief Calculates the center of the genericAABB * * \returns The calculated center */ template< typename T > typename GenericAABB< T >::vector_type GenericAABB< T >::center() const { WALBERLA_ASSERT( checkInvariant() ); return vector_type( ( maxCorner_[0] + minCorner_[0] ) * value_type(0.5), ( maxCorner_[1] + minCorner_[1] ) * value_type(0.5), ( maxCorner_[2] + minCorner_[2] ) * value_type(0.5) ); } /** * \brief Tests whether a point lies within the GenericAABB * * This test interprets the boundaries of the GenericAABB as an half-open interval. The minimal values stored in minCorner * are considered to belong to the bounding box while the maximal values stored in maxCorner are not. * * \param x x coordinate of the point to be tested for containment * \param y y coordinate of the point to be tested for containment * \param z z coordinate of the point to be tested for containment * * \returns if point lies in the GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::contains( const value_type x, const value_type y, const value_type z ) const { return x >= minCorner_[0] && x < maxCorner_[0] && y >= minCorner_[1] && y < maxCorner_[1] && z >= minCorner_[2] && z < maxCorner_[2]; } /** * \brief Tests whether a point lies within the extended GenericAABB. * * This test interprets the boundaries of the GenericAABB as an half-open interval. The minimal values stored in minCorner * are considered to belong to the bounding box while the maximal values stored in maxCorner are not. * * \param x x coordinate of the point to be tested for containment * \param y y coordinate of the point to be tested for containment * \param z z coordinate of the point to be tested for containment * \param dx An epsilon the box is extended by in each direction before the test * * \returns if point lies in the extended GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::contains( const value_type x, const value_type y, const value_type z, const value_type dx ) const { return x >= ( minCorner_[0] - dx ) && x < ( maxCorner_[0] + dx ) && y >= ( minCorner_[1] - dx ) && y < ( maxCorner_[1] + dx ) && z >= ( minCorner_[2] - dx ) && z < ( maxCorner_[2] + dx ); } /** * \brief Tests whether a point lies within the GenericAABB * * This test interprets the boundaries of the GenericAABB as an half-open interval. The minimal values stored in minCorner * are considered to belong to the bounding box while the maximal values stored in maxCorner are not. * * \param point The point to be tested for containment * * \returns if point lies in the GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::contains( const vector_type & point ) const { return contains( point[0], point[1], point[2] ); } /** * \brief Tests whether a point lies within the extended GenericAABB. * * This test interprets the boundaries of the GenericAABB as an half-open interval. The minimal values stored in minCorner * are considered to belong to the bounding box while the maximal values stored in maxCorner are not. * * \param point The point to be tested for containment * \param dx An epsilon the box is extended by in each direction before the test * * \returns if point lies in the extended GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::contains( const vector_type & point, const value_type dx ) const { return contains( point[0], point[1], point[2], dx ); } /** * \brief Tests whether an other GenericAABB lies within the GenericAABB * * \param other An other GenericAABB * * \returns if other lies in the GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::contains( const GenericAABB & other ) const { return other.minCorner_[0] >= minCorner_[0] && other.maxCorner_[0] <= maxCorner_[0] && other.minCorner_[1] >= minCorner_[1] && other.maxCorner_[1] <= maxCorner_[1] && other.minCorner_[2] >= minCorner_[2] && other.maxCorner_[2] <= maxCorner_[2]; } /** * \brief Tests whether an other GenericAABB lies within the extended GenericAABB * * \param other An other GenericAABB * \param dx An epsilon the box is extended by in each direction before the test * * \returns if other lies in the extended GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::contains( const GenericAABB & other, const value_type dx ) const { return other.minCorner_[0] >= ( minCorner_[0] - dx ) && other.maxCorner_[0] <= ( maxCorner_[0] + dx ) && other.minCorner_[1] >= ( minCorner_[1] - dx ) && other.maxCorner_[1] <= ( maxCorner_[1] + dx ) && other.minCorner_[2] >= ( minCorner_[2] - dx ) && other.maxCorner_[2] <= ( maxCorner_[2] + dx ); } /** * \brief Tests whether a point lies within the GenericAABB * * This test interprets the boundaries of the GenericAABB as a closed interval. The minimal values stored in minCorner * are considered to belong to the bounding box as well as the maximal values stored in maxCorner. * * \param point The point to be tested for containment * * \returns if point lies in the GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::containsClosedInterval( const vector_type & point ) const { return point[0] >= minCorner_[0] && point[0] <= maxCorner_[0] && point[1] >= minCorner_[1] && point[1] <= maxCorner_[1] && point[2] >= minCorner_[2] && point[2] <= maxCorner_[2]; } /** * \brief Tests whether a point lies within the extended GenericAABB. * * This test interprets the boundaries of the GenericAABB as a closed interval. The minimal values stored in minCorner * are considered to belong to the bounding box as well as the maximal values stored in maxCorner. * * \param point The point to be tested for containment * \param dx An epsilon the box is extended by in each direction before the test * * \returns if point lies in the extended GenericAABB true, else false */ template< typename T > bool GenericAABB< T >::containsClosedInterval( const vector_type & point, const value_type dx ) const { return point[0] >= ( minCorner_[0] - dx ) && point[0] <= ( maxCorner_[0] + dx ) && point[1] >= ( minCorner_[1] - dx ) && point[1] <= ( maxCorner_[1] + dx ) && point[2] >= ( minCorner_[2] - dx ) && point[2] <= ( maxCorner_[2] + dx ); } /** * \brief Creates a new GenericAABB by extending this one * * \param e epsilon by which the bounding box is extended in each direction * * \returns The extended GenericAABB */ template< typename T > GenericAABB< T > GenericAABB< T >::getExtended( const value_type e ) const { vector_type newMinCorner( minCorner_[0] - e, minCorner_[1] - e, minCorner_[2] - e ); return createFromMinMaxCorner( newMinCorner[0], newMinCorner[1], newMinCorner[2], std::max( newMinCorner[0], maxCorner_[0] + e ), std::max( newMinCorner[1], maxCorner_[1] + e ), std::max( newMinCorner[2], maxCorner_[2] + e ) ); } /** * \brief Creates a new GenericAABB by extending this one * * \param e epsilon vector by which the bounding box is extended. The box is extended in each direction by * the corresponding vector component. * * \returns The extended GenericAABB */ template< typename T > GenericAABB< T > GenericAABB< T >::getExtended( const vector_type & e ) const { vector_type newMinCorner( minCorner_ - e ); return createFromMinMaxCorner( newMinCorner[0], newMinCorner[1], newMinCorner[2], std::max( newMinCorner[0], maxCorner_[0] + e[0] ), std::max( newMinCorner[1], maxCorner_[1] + e[0] ), std::max( newMinCorner[2], maxCorner_[2] + e[0] ) ); } /** * \brief Creates a new GenericAABB by translating this one * * \param translation Vector by which the GenericAABB is translated. * * \returns The translated GenericAABB */ template< typename T > GenericAABB< T > GenericAABB< T >::getTranslated( const vector_type & translation ) const { return createFromMinMaxCorner( minCorner_ + translation, maxCorner_ + translation ); } /** * \brief Creates a new GenericAABB by scaling this one * * \param factor Factor by which the bounding box gets scaled. * * \returns The scaled GenericAABB */ template< typename T > GenericAABB< T > GenericAABB< T >::getScaled( const value_type factor ) const { vector_type theCenter = center(); GenericAABB result = getTranslated( -theCenter ); result.minCorner_ *= factor; result.maxCorner_ *= factor; result.translate( theCenter ); return result; } /** * \brief Creates a new GenericAABB by scaling this one * * \param factor Vector of scaling factors by which the bounding box gets scaled on the * respective axises. * * \returns The scaled GenericAABB */ template< typename T > GenericAABB< T > GenericAABB< T >::getScaled( const vector_type & factors ) const { vector_type theCenter = center(); GenericAABB result = getTranslated( -theCenter ); for( uint_t i = 0; i < 3; ++i ) { result.minCorner_[i] *= factors[i]; result.maxCorner_[i] *= factors[i]; } result.translate( theCenter ); return result; } /** * \brief Creates a new GenericAABB by merging this one with an additional point * * Note that for the resulting GenericAABB containsClosedInterval( point ) will be true * but contains( point ) may be false! * * \param point The point that will be covered by the resulting GenericAABB * * \returns A GenericAABB covering point * * \post containsClosedInterval( point ) */ template< typename T > GenericAABB< T > GenericAABB< T >::getMerged( const vector_type & point ) const { return createFromMinMaxCorner( std::min( minCorner_[0], point[0] ), std::min( minCorner_[1], point[1] ), std::min( minCorner_[2], point[2] ), std::max( maxCorner_[0], point[0] ), std::max( maxCorner_[1], point[1] ), std::max( maxCorner_[2], point[2] ) ); } /** * \brief Creates a new GenericAABB by merging this one with an other GenericAABB * * \param other The GenericAABB that will be covered by the resulting GenericAABB * * \returns A GenericAABB covering other * * \post contains( other ) */ template< typename T > GenericAABB< T > GenericAABB< T >::getMerged( const GenericAABB & other ) const { return createFromMinMaxCorner( std::min( minCorner_[0], other.minCorner_[0] ), std::min( minCorner_[1], other.minCorner_[1] ), std::min( minCorner_[2], other.minCorner_[2] ), std::max( maxCorner_[0], other.maxCorner_[0] ), std::max( maxCorner_[1], other.maxCorner_[1] ), std::max( maxCorner_[2], other.maxCorner_[2] ) ); } /** * \brief Creates a new GenericAABB by merging this one to a Sequence of points or other GenericAABBs. * * \tparam InputIterator A ForwardIterator. Must dereference to Vector3< T > or GenericAABB< T >. * * \param first First element of sequence [first, last) * \param last Final element of sequence [first, last) * * \returns A GenericAABB covering *this and all the Points/GenericAABBs in the sequence */ template< typename T > template< typename InputIterator > GenericAABB< T > GenericAABB< T >::getMerged( InputIterator first, InputIterator last ) const { if( first == last ) { return *this; } else { GenericAABB< T > result( first, last ); result.merge( *this ); return result; } } /** * \brief Tests whether this genericAABB intersects another GenericAABB * * This test interprets the boundaries of the GenericAABB as an half-open interval. The minimal values stored in minCorner * are considered to belong to the bounding boxes while the maximal values stored in maxCorner are not. * * \param other Other GenericAABB to be tested for intersection * * \returns true, if *this intersects other, false else */ template< typename T > bool GenericAABB< T >::intersects( const GenericAABB & other ) const { return other.maxCorner_[0] > minCorner_[0] && other.minCorner_[0] < maxCorner_[0] && other.maxCorner_[1] > minCorner_[1] && other.minCorner_[1] < maxCorner_[1] && other.maxCorner_[2] > minCorner_[2] && other.minCorner_[2] < maxCorner_[2] && !empty() && !other.empty(); } /** * \brief Tests whether this extended GenericAABB intersects another GenericAABB * * This test interprets the boundaries of the GenericAABB as an half-open interval. The minimal values stored in minCorner * are considered to belong to the bounding boxes while the maximal values stored in maxCorner are not. * * \param other Other GenericAABB to be tested for intersection * \param dx An epsilon the box is extended by in each direction before the test * * \returns true, if *this extended by dx intersects other, false else */ template< typename T > bool GenericAABB< T >::intersects( const GenericAABB & other, const value_type dx ) const { WALBERLA_ASSERT_LESS_EQUAL( minCorner_[0] - dx, maxCorner_[0] + dx ); WALBERLA_ASSERT_LESS_EQUAL( minCorner_[1] - dx, maxCorner_[1] + dx ); WALBERLA_ASSERT_LESS_EQUAL( minCorner_[2] - dx, maxCorner_[2] + dx ); return other.maxCorner_[0] > ( minCorner_[0] - dx ) && other.minCorner_[0] < ( maxCorner_[0] + dx ) && other.maxCorner_[1] > ( minCorner_[1] - dx ) && other.minCorner_[1] < ( maxCorner_[1] + dx ) && other.maxCorner_[2] > ( minCorner_[2] - dx ) && other.minCorner_[2] < ( maxCorner_[2] + dx ) && !other.empty() && minCorner_[0] - dx < maxCorner_[0] + dx && minCorner_[1] - dx < maxCorner_[1] + dx && minCorner_[2] - dx < maxCorner_[2] + dx; } /** * \brief Tests whether this genericAABB intersects another GenericAABB * * This test interprets the boundaries of the GenericAABB as a closed interval. The minimal values stored in minCorner * are considered to belong to the bounding boxes as well as the maximal values stored in maxCorner. * * \param other Other GenericAABB to be tested for intersection * * \returns true, if *this intersects other, false else */ template< typename T > bool GenericAABB< T >::intersectsClosedInterval( const GenericAABB & other ) const { return other.maxCorner_[0] >= minCorner_[0] && other.minCorner_[0] <= maxCorner_[0] && other.maxCorner_[1] >= minCorner_[1] && other.minCorner_[1] <= maxCorner_[1] && other.maxCorner_[2] >= minCorner_[2] && other.minCorner_[2] <= maxCorner_[2]; } /** * \brief Tests whether this extended GenericAABB intersects another GenericAABB * * This test interprets the boundaries of the GenericAABB as a closed interval. The minimal values stored in minCorner * are considered to belong to the bounding boxes as well as the maximal values stored in maxCorner. * * \param other Other GenericAABB to be tested for intersection * \param dx An epsilon the box is extended by in each direction before the test * * \returns true, if *this extended by dx intersects other, false else */ template< typename T > bool GenericAABB< T >::intersectsClosedInterval( const GenericAABB & other, const value_type dx ) const { return other.maxCorner_[0] >= ( minCorner_[0] - dx ) && other.minCorner_[0] <= ( maxCorner_[0] + dx ) && other.maxCorner_[1] >= ( minCorner_[1] - dx ) && other.minCorner_[1] <= ( maxCorner_[1] + dx ) && other.maxCorner_[2] >= ( minCorner_[2] - dx ) && other.minCorner_[2] <= ( maxCorner_[2] + dx ); } /** * \brief Computes the volume of the intersection of this and another GenericAABB * * \param other Other GenericAABB to be intersected with *this * * \returns The volume of *this intersected with other */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::intersectionVolume( const GenericAABB & other ) const { return getIntersection( other ).volume(); } /** * \brief Computes the intersection of this and another GenericAABB * * \param other Other GenericAABB to be intersected with *this * * \returns The intersection of *this and other */ template< typename T > GenericAABB< T > GenericAABB< T >::getIntersection( const GenericAABB & other ) const { return GenericAABB( *this, other ); } /** * \brief Test whether this and another GenericAABB are exactly identical * * \param other Other GenericAABB to be tested for identity * * \returns true, if *this is exactly identical to other, false else */ template< typename T > bool GenericAABB< T >::isIdentical( const GenericAABB< T > & other ) const { return walberla::isIdentical( minCorner_[0], other.minCorner_[0] ) && walberla::isIdentical( minCorner_[1], other.minCorner_[1] ) && walberla::isIdentical( minCorner_[2], other.minCorner_[2] ) && walberla::isIdentical( maxCorner_[0], other.maxCorner_[0] ) && walberla::isIdentical( maxCorner_[1], other.maxCorner_[1] ) && walberla::isIdentical( maxCorner_[2], other.maxCorner_[2] ); } /** * \brief Test whether this and another GenericAABB are equal * * Uses walberla::floatIsEqual method for determination of equality. Small roundoff errors are neglected in this check. * * \param other Other GenericAABB to be tested for equality * * \returns true, if *this is equal to other, false else */ template< typename T > bool GenericAABB< T >::isEqual( const GenericAABB< T > & other ) const { return walberla::floatIsEqual( minCorner_[0], other.minCorner_[0] ) && walberla::floatIsEqual( minCorner_[1], other.minCorner_[1] ) && walberla::floatIsEqual( minCorner_[2], other.minCorner_[2] ) && walberla::floatIsEqual( maxCorner_[0], other.maxCorner_[0] ) && walberla::floatIsEqual( maxCorner_[1], other.maxCorner_[1] ) && walberla::floatIsEqual( maxCorner_[2], other.maxCorner_[2] ); } /** * \brief Computes the squared distance of point to this GenericAABB * * \param point The point of which the distance to *this should be computed * * \returns 0, if point lies inside or on the surface of *this * \returns The squared (positive) distance of point to the surface of *this, if point lies outside of *this */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::sqDistance( const vector_type & point ) const { const vector_type d = point - minCorner_; const vector_type theSizes = sizes(); value_type sqDist(0); for( uint_t i = 0; i < 3; i++ ) { if( d[i] < 0 ) sqDist += d[i] * d[i]; else if( d[i] > theSizes[i] ) { const value_type axisDist = d[i] - theSizes[i]; sqDist += axisDist * axisDist; } } WALBERLA_ASSERT_GREATER_EQUAL( sqDist, value_type( 0 ) ); return sqDist; } /** * \brief Computes the squared signed distance of point to this GenericAABB * * \param point The point of which the distance to *this should be computed * * \returns The negative squared distance of point to the surface of *this, if point lies inside of *this * \returns 0, if point lies on the surface of *this * \returns The positive squared distance of point to the surface of *this, if point lies outside of *this */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::sqSignedDistance( const vector_type & point ) const { const vector_type d = point - minCorner_; const vector_type theSizes = sizes(); bool inside = d[0] >= value_type( 0 ) && d[0] < theSizes[0] && d[1] >= value_type( 0 ) && d[1] < theSizes[1] && d[2] >= value_type( 0 ) && d[2] < theSizes[2]; if( !inside ) return sqDistance( point ); value_type sqAxisDist[3]; for( uint_t i = 0; i < 3; ++i ) { WALBERLA_ASSERT_GREATER_EQUAL( d[i], 0 ); WALBERLA_ASSERT_LESS( d[i], theSizes[i] ); if( d[i] < theSizes[i] * value_type(0.5) ) { sqAxisDist[i] = d[i] * d[i]; } else { const value_type axisDist = d[i] - theSizes[i]; sqAxisDist[i] = axisDist * axisDist; } } return -std::min( sqAxisDist[0], std::min( sqAxisDist[1], sqAxisDist[2] ) ); } /** * \brief Computes the squared maximal distance of point to the far side of this GenericAABB * * \param point The point of which the maximal distance to *this should be computed * * \returns The maximal squared (positive) distance of point to the surface of *this. */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::sqMaxDistance( const vector_type & point ) const { const vector_type d0 = point - minCorner_; const vector_type d1 = point - maxCorner_; value_type sqDist(0); for( uint_t i = 0; i < 3; i++ ) { if( std::fabs( d0[i] ) > std::fabs( d1[i] ) ) sqDist += d0[i] * d0[i]; else sqDist += d1[i] * d1[i]; } WALBERLA_ASSERT_GREATER_EQUAL( sqDist, value_type( 0 ) ); return sqDist; } /** * \brief Computes the distance of point to this GenericAABB * * \param point The point of which the distance to *this should be computed * * \returns 0, if point lies inside or on the surface of *this * \returns The (positive) distance of point to the surface of *this, if point lies outside of *this */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::distance( const vector_type & point ) const { return std::sqrt( sqDistance( point ) ); } /** * \brief Computes the signed distance of point to this GenericAABB * * \param point The point of which the distance to *this should be computed * * \returns The negative distance of point to the surface of *this, if point lies inside of *this * \returns 0, if point lies on the surface of *this * \returns The positive distance of point to the surface of *this, if point lies outside of *this */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::signedDistance( const vector_type & point ) const { const vector_type d = point - minCorner_; const vector_type theSizes = sizes(); bool inside = d[0] >= value_type( 0 ) && d[0] < theSizes[0] && d[1] >= value_type( 0 ) && d[1] < theSizes[1] && d[2] >= value_type( 0 ) && d[2] < theSizes[2]; if( !inside ) return distance( point ); value_type axisDist[3]; for( uint_t i = 0; i < 3; ++i ) { WALBERLA_ASSERT_GREATER_EQUAL( d[i], 0 ); WALBERLA_ASSERT_LESS( d[i], theSizes[i] ); if( d[i] < theSizes[i] * value_type( 0.5 ) ) { axisDist[i] = d[i]; } else { axisDist[i] = theSizes[i] - d[i]; } } return -std::min( axisDist[0], std::min( axisDist[1], axisDist[2] ) ); } /** * \brief Computes the maximal distance of point to the far side of this GenericAABB * * \param point The point of which the maximal distance to *this should be computed * * \returns The maximal (positive) distance of point to the surface of *this. */ template< typename T > typename GenericAABB< T >::value_type GenericAABB< T >::maxDistance( const vector_type & point ) const { return std::sqrt( sqMaxDistance( point ) ); } /** * \brief Computes the distance between two GenericAABBs * * \param other The other AABB to which the distance to *this should be computed * * \returns The (positive) distance of the surface of other to the surface of *this. 0 if *this and other are intersecting. */ template< typename T > inline typename GenericAABB< T >::value_type GenericAABB< T >::sqDistance( const GenericAABB & other ) const { value_type theSqDistance = value_type(0); if( other.maxCorner_[0] < minCorner_[0] ) { theSqDistance += sq( minCorner_[0] - other.maxCorner_[0] ); } else if( other.minCorner_[0] > maxCorner_[0] ) { theSqDistance += sq( other.minCorner_[0] - maxCorner_[0] ); } if( other.maxCorner_[1] < minCorner_[1] ) { theSqDistance += sq( minCorner_[1] - other.maxCorner_[1] ); } else if( other.minCorner_[1] > maxCorner_[1] ) { theSqDistance += sq( other.minCorner_[1] - maxCorner_[1] ); } if( other.maxCorner_[2] < minCorner_[2] ) { theSqDistance += sq( minCorner_[2] - other.maxCorner_[2] ); } else if( other.minCorner_[2] > maxCorner_[2] ) { theSqDistance += sq( other.minCorner_[2] - maxCorner_[2] ); } WALBERLA_ASSERT_GREATER_EQUAL( theSqDistance, value_type(0) ); WALBERLA_ASSERT( !intersects( other ) || walberla::isIdentical( theSqDistance, value_type(0) ) ); // intersect => distance == 0 return theSqDistance; } /** * \brief Computes the maximal distance of any two points from two GenericAABBs * * \param other The other AABB to which the maximal distance to *this should be computed * * \returns The maximal (positive) distance of any point in other to any point in this. */ template< typename T > inline typename GenericAABB< T >::value_type GenericAABB< T >::sqMaxDistance( const GenericAABB & other ) const { value_type theSqMaxDistance = value_type(0); theSqMaxDistance += sq( std::max( maxCorner_[0] - other.minCorner_[0], other.maxCorner_[0] - minCorner_[0] ) ); theSqMaxDistance += sq( std::max( maxCorner_[1] - other.minCorner_[1], other.maxCorner_[1] - minCorner_[1] ) ); theSqMaxDistance += sq( std::max( maxCorner_[2] - other.minCorner_[2], other.maxCorner_[2] - minCorner_[2] ) ); WALBERLA_ASSERT_GREATER_EQUAL( theSqMaxDistance, value_type(0) ); return theSqMaxDistance; } /** * \brief Computes the eight corners of this GenericAABB * * \returns An array of size eight containing the corner points. Indices match those of the stencil::D3CornerStencil */ template< typename T > inline boost::array< typename GenericAABB< T >::vector_type, 8 > GenericAABB< T >::corners() const { boost::array< vector_type, 8 > cornerArray; // TNE cornerArray[0][0] = maxCorner_[0]; cornerArray[0][1] = maxCorner_[1]; cornerArray[0][2] = maxCorner_[2]; // TNW cornerArray[1][0] = minCorner_[0]; cornerArray[1][1] = maxCorner_[1]; cornerArray[1][2] = maxCorner_[2]; // TSE cornerArray[2][0] = maxCorner_[0]; cornerArray[2][1] = minCorner_[1]; cornerArray[2][2] = maxCorner_[2]; // TSW cornerArray[3][0] = minCorner_[0]; cornerArray[3][1] = minCorner_[1]; cornerArray[3][2] = maxCorner_[2]; // BNE cornerArray[4][0] = maxCorner_[0]; cornerArray[4][1] = maxCorner_[1]; cornerArray[4][2] = minCorner_[2]; // BNW cornerArray[5][0] = minCorner_[0]; cornerArray[5][1] = maxCorner_[1]; cornerArray[5][2] = minCorner_[2]; // BSE cornerArray[6][0] = maxCorner_[0]; cornerArray[6][1] = minCorner_[1]; cornerArray[6][2] = minCorner_[2]; // BSW cornerArray[7][0] = minCorner_[0]; cornerArray[7][1] = minCorner_[1]; cornerArray[7][2] = minCorner_[2]; return cornerArray; } /** * \brief Reinitializes this GenericAABB with default values * * \post minCorner = maxCorner = (0,0,0) */ template< typename T > void GenericAABB< T >::init() { minCorner_.set( value_type( 0 ), value_type( 0 ), value_type( 0 ) ); maxCorner_.set( value_type( 0 ), value_type( 0 ), value_type( 0 ) ); WALBERLA_ASSERT( checkInvariant() ); WALBERLA_ASSERT( empty() ); } /** * \brief Reinitializes this GenericAABB from two arbitrary points * * \param corner0 first corner spanning the AABB * \param corner1 second corner spanning the AABB */ template< typename T > void GenericAABB< T >::init( const vector_type & corner0, const vector_type & corner1 ) { for( uint_t i = 0; i < 3; ++i ) { if( corner0[i] < corner1[i] ) { minCorner_[i] = corner0[i]; maxCorner_[i] = corner1[i]; } else { minCorner_[i] = corner1[i]; maxCorner_[i] = corner0[i]; } } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Reinitializes this GenericAABB from two arbitrary points * * \param x0 x-coordinate of the first corner spanning the AABB * \param y0 y-coordinate of the first corner spanning the AABB * \param z0 z-coordinate of the first corner spanning the AABB * \param x1 x-coordinate of the second corner spanning the AABB * \param y1 y-coordinate of the second corner spanning the AABB * \param z1 z-coordinate of the second corner spanning the AABB */ template< typename T > void GenericAABB< T >::init( const value_type x0, const value_type y0, const value_type z0, const value_type x1, const value_type y1, const value_type z1 ) { if( x0 < x1 ) { minCorner_[0] = x0; maxCorner_[0] = x1; } else { minCorner_[0] = x1; maxCorner_[0] = x0; } if( y0 < y1 ) { minCorner_[1] = y0; maxCorner_[1] = y1; } else { minCorner_[1] = y1; maxCorner_[1] = y0; } if( z0 < z1 ) { minCorner_[2] = z0; maxCorner_[2] = z1; } else { minCorner_[2] = z1; maxCorner_[2] = z0; } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Reinitializes this GenericAABB by merging a Sequence of points or GenericAABBs * * \tparam InputIterator ForwardIterator. Must dereference to Vector3< T > or GenericAABB< T >. * * \param first first element of sequence [first, last) * \param last final element of sequence [first, last) * * \post first == last => minCorner = maxCorner = (0,0,0) */ template< typename T > template< typename InputIterator > void GenericAABB< T >::init( InputIterator first, InputIterator last ) { if( first != last ) { minCorner_.set( std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::max() ); maxCorner_.set( -std::numeric_limits<value_type>::max(), -std::numeric_limits<value_type>::max(), -std::numeric_limits<value_type>::max() ); merge( first, last ); } else { init(); } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Reinitializes this GenericAABB from a min- and a maxCorner * * \param minCorner corner with minimal values * \param maxCorner corner with maximal values * * \pre minCorner.x <= maxCorner.x && minCorner.y <= maxCorner.y && minCorner.z <= maxCorner.z */ template< typename T > void GenericAABB< T >::initMinMaxCorner( const value_type minX, const value_type minY, const value_type minZ, const value_type maxX, const value_type maxY, const value_type maxZ ) { minCorner_[0] = minX; minCorner_[1] = minY; minCorner_[2] = minZ; maxCorner_[0] = maxX; maxCorner_[1] = maxY; maxCorner_[2] = maxZ; WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Reinitializes this GenericAABB from a min- and a maxCorner * * \param minX x-coordinate of the minCorner * \param minY y-coordinate of the minCorner * \param minZ z-coordinate of the minCorner * \param maxX x-coordinate of the maxCorner * \param maxY y-coordinate of the maxCorner * \param maxZ z-coordinate of the maxCorner * * \pre x0 <= x1 && y0 <= y1 && z0 <= z1 */ template< typename T > void GenericAABB< T >::initMinMaxCorner( const vector_type & theMinCorner, const vector_type & theMaxCorner ) { minCorner_ = theMinCorner; maxCorner_ = theMaxCorner; WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Sets the minimum and maximum for one axis * * \param index 0 for x, 1 for y, 2 for z axis * \param value* the smaller of the two values is taken as minimum, the other as maximum */ template< typename T > void GenericAABB< T >::setAxisBounds( const uint_t index, const value_type value1, const value_type value2 ) { WALBERLA_ASSERT_LESS( index, 3 ); if ( value1 < value2 ) { minCorner_[index] = value1; maxCorner_[index] = value2; } else { minCorner_[index] = value2; maxCorner_[index] = value1; } WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Extends this GenericAABB * * \param e epsilon by which the bounding box is extended in each direction */ template< typename T > void GenericAABB< T >::extend( const value_type e ) { minCorner_[0] -= e; minCorner_[1] -= e; minCorner_[2] -= e; maxCorner_[0] += e; maxCorner_[1] += e; maxCorner_[2] += e; for( uint_t i = 0; i < 3; ++i ) if( minCorner_[i] > maxCorner_[i] ) maxCorner_[i] = minCorner_[i]; WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Extends this GenericAABB * * \param e epsilon vector by which the bounding box is extended. The box is extended in each direction by * the corresponding vector component. */ template< typename T > void GenericAABB< T >::extend( const vector_type & e ) { minCorner_ -= e; maxCorner_ += e; for( uint_t i = 0; i < 3; ++i ) if( minCorner_[i] > maxCorner_[i] ) maxCorner_[i] = minCorner_[i]; WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Translates this GenericAABB * * \param translation Vector by which the GenericAABB is translated. */ template< typename T > void GenericAABB< T >::translate( const vector_type & translation ) { minCorner_ += translation; maxCorner_ += translation; } /** * \brief Scales this GenericAABB * * \param factor Factor by which the bounding box gets scaled. */ template< typename T > void GenericAABB< T >::scale( const value_type factor ) { WALBERLA_ASSERT( factor > value_type( 0 ) ); const vector_type theCenter = center(); translate( -theCenter ); minCorner_ *= factor; maxCorner_ *= factor; translate( theCenter ); } /** * \brief Scales this GenericAABB * * \param factor Vector of scaling factors by which the bounding box gets scaled on the * respective axises. */ template< typename T > void GenericAABB< T >::scale( const vector_type & factors ) { WALBERLA_ASSERT( factors[0] > value_type( 0 ) ); WALBERLA_ASSERT( factors[1] > value_type( 0 ) ); WALBERLA_ASSERT( factors[2] > value_type( 0 ) ); const vector_type theCenter = center(); translate( -theCenter ); for( uint_t i = 0; i < 3; ++i ) { minCorner_[i] *= factors[i]; maxCorner_[i] *= factors[i]; } translate( theCenter ); } /** * \brief Merges this GenericAABB with an additional point * * Note that for the resulting GenericAABB containsClosedInterval( point ) will be true * but contains( point ) may be false! * * \param point The point that will be covered by the resulting GenericAABB * * \post containsClosedInterval( point ) */ template< typename T > void GenericAABB< T >::merge( const vector_type & point ) { for( uint_t i = 0; i < 3; ++i ) { if( point[i] < minCorner_[i] ) minCorner_[i] = point[i]; if( point[i] > maxCorner_[i] ) maxCorner_[i] = point[i]; } } /** * \brief Merges this GenericAABB with an other GenericAABB * * \param other The GenericAABB that will be covered by the resulting GenericAABB * * \post contains( other ) */ template< typename T > void GenericAABB< T >::merge( const GenericAABB & other ) { for( uint_t i = 0; i < 3; ++i ) { if( other.minCorner_[i] < minCorner_[i] ) minCorner_[i] = other.minCorner_[i]; if( other.maxCorner_[i] > maxCorner_[i] ) maxCorner_[i] = other.maxCorner_[i]; } } /** * \brief Merges this GenericAABB with a Sequence of points or other GenericAABBs. * * \tparam InputIterator A ForwardIterator. Must dereference to Vector3< T > or GenericAABB< T >. * * \param first First element of sequence [first, last) * \param last Final element of sequence [first, last) */ template< typename T > template< typename InputIterator > void GenericAABB< T >::merge( InputIterator first, InputIterator last ) { while( first != last ) merge( *first++ ); } /** * \brief Intersects this with another GenericAABB * * \param other Other GenericAABB to be intersected with *this */ template< typename T > void GenericAABB< T >::intersect( const GenericAABB & other ) { minCorner_[0] = std::max( minCorner_[0], other.minCorner_[0] ); minCorner_[1] = std::max( minCorner_[1], other.minCorner_[1] ); minCorner_[2] = std::max( minCorner_[2], other.minCorner_[2] ); maxCorner_[0] = std::max( minCorner_[0], std::min( maxCorner_[0], other.maxCorner_[0] ) ); maxCorner_[1] = std::max( minCorner_[1], std::min( maxCorner_[1], other.maxCorner_[1] ) ); maxCorner_[2] = std::max( minCorner_[2], std::min( maxCorner_[2], other.maxCorner_[2] ) ); WALBERLA_ASSERT( checkInvariant() ); } /** * \brief Generates a random point uniformly distributed within the AABB * * The point is in ( [ xMin(), xMax() ), [ yMin(), yMax() ), [ zMin(), zMax() ) ) * * \pre !empty() * \param engine An Uniform Random Number Generator (e.g. boost::random::mt19937) * \returns Random point within *this */ template< typename T > template< typename Engine > typename GenericAABB< T >::vector_type GenericAABB< T >::randomPoint( Engine & engine ) const { WALBERLA_ASSERT( !empty() ); boost::random::uniform_real_distribution< T > randX( xMin(), xMax() ); boost::random::uniform_real_distribution< T > randY( yMin(), yMax() ); boost::random::uniform_real_distribution< T > randZ( zMin(), zMax() ); return vector_type( randX( engine ), randY( engine ), randZ( engine ) ); } /** * \brief Tests whether the class invariant is satisfied * * The invariant is minCorner.x <= maxCorner.x && minCorner.y <= maxCorner.y && minCorner.z <= maxCorner.z * * \returns true if the invariant is satisfied, false else */ template< typename T > bool GenericAABB< T >::checkInvariant() const { return minCorner_[0] <= maxCorner_[0] && minCorner_[1] <= maxCorner_[1] && minCorner_[2] <= maxCorner_[2]; } /** * \brief Compares two GenericeAABBs for equality * * see isEqual * * ATTENTION: Does not check for identity! If you need to check for identity, * use member function isIdentical of class GenericAABB * * \param lhs An arbitrary GenericAABB * \param rhs An arbitrary GenericAABB * * \returns true, if lhs is equal to rhs, false else */ template< typename T, typename U > bool operator==( const GenericAABB< T > & lhs, const GenericAABB< U > & rhs ) { return lhs.isEqual( rhs ); } /** * \brief Compares two GenericeAABBs for inequality * * see isEqual * * ATTENTION: Does not check for non-identity! If you need to check for non-identity, * use member function isIdentical of class GenericAABB * * \param lhs An arbitrary GenericAABB * \param rhs An arbitrary GenericAABB * * \returns false, if lhs is equal to rhs, true else */ template< typename T, typename U > bool operator!=( const GenericAABB< T > & lhs, const GenericAABB< U > & rhs ) { return !lhs.isEqual( rhs ); } /** * \brief Writes a GenericAABB to a std::ostream * * The format is [ <0,0,0>, <1,1,1> ] * * \param os The std::ostream written to * \param aabb The GenericAABB written * * \returns A reference to os */ template< typename T > std::ostream& operator<<( std::ostream& os, const GenericAABB< T > & aabb ) { return os << "[ " << aabb.minCorner() << ", " << aabb.maxCorner() << " ]"; } /** * \brief Reads an GenericAABB from a std::istream * * The format is [ <0,0,0>, <1,1,1> ] * * \param is The std::istream read from * \param aabb The GenericAABB the read values are to be stored in * * \returns A reference to is */ template< typename T > std::istream& operator>>( std::istream& is, GenericAABB< T > & aabb ) { if( !is ) return is; char bracket0, bracket1; char comma; typename GenericAABB< T >::vector_type corner0, corner1; const std::istream::pos_type pos( is.tellg() ); const std::istream::fmtflags oldFlags( is.flags() ); // Setting the 'skip whitespaces' flag is >> std::skipws; // Extracting the vector if( !( is >> bracket0 >> corner0 >> comma >> corner1 >> bracket1 ) || comma != ',' || bracket0 != '[' || bracket1 != ']' ) { is.clear(); is.seekg( pos ); is.setstate( std::istream::failbit ); is.flags( oldFlags ); return is; } // Transferring the input to the aabb values aabb.init( corner0, corner1 ); // Resetting the flags is.flags( oldFlags ); return is; } /** * \brief Serializes an GenericAABB into a mpi::GenericSendBuffer * * \param buf The mpi::GenericSendBuffer written to * \param aabb The GenericAABB the be serialized * * \returns A reference to buf */ template< typename T, // Element type of SendBuffer typename G, // Growth policy of SendBuffer typename VT > // Element type of GenericAABB mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, const GenericAABB< VT > & aabb ) { buf.addDebugMarker( "bb" ); return buf << aabb.minCorner() << aabb.maxCorner(); } } // namespace math } // namespace walberla