1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#ifndef BOUND_BOX_HPP
#define BOUND_BOX_HPP

#include "moab/Interface.hpp"
#include "moab/CartVect.hpp"

#include <cfloat>

namespace moab
{

class BoundBox
{
  public:
    BoundBox() : bMin( DBL_MAX ), bMax( -DBL_MAX ) {}
    BoundBox( const CartVect& min, const CartVect& max ) : bMin( min ), bMax( max ) {}
    BoundBox( const double* corners );
    // constructor used in element maps
    BoundBox( std::vector< CartVect > points ) : bMin( DBL_MAX ), bMax( -DBL_MAX )
    {
        for( size_t i = 0; i < points.size(); i++ )
        {
            update_min( points[i].array() );
            update_max( points[i].array() );
        }
    }
    BoundBox( const BoundBox& from ) : bMin( from.bMin ), bMax( from.bMax ) {}

    ~BoundBox() {}

    bool contains_point( const double* point, const double tol = 0.0 ) const;
    bool intersects_box( const BoundBox& b, const double tol = 0.0 ) const;
    void compute_center( CartVect& center );
    void update( const BoundBox& other_box );
    void update( const double* coords );
    ErrorCode update( Interface& iface, const Range& elems, bool spherical = false, double radius = 1. );
    ErrorCode update( Interface& iface, const EntityHandle ent, bool spherical = false, double radius = 1. );
    void update_min( const BoundBox& other_box );
    void update_min( const double* coords );
    void update_max( const BoundBox& other_box );
    void update_max( const double* coords );
    ErrorCode get( double* coords );
    /** in case of spherical elements, account for curvature if needed
     */
    void update_box_spherical_elem( const CartVect* coordverts, int len, double radius );

    /** \brief Return the diagonal length of this box
     */
    double diagonal_length() const;

    /** \brief Return the square of the diagonal length of this box
     */
    double diagonal_squared() const;

    /** \brief Return square of distance from box, or zero if inside
     * \param from_point Point from which you want distance_sq
     */
    double distance_squared( const double* from_point ) const;

    /** \brief Return distance from box, or zero if inside
     * \param from_point Point from which you want distance
     */
    double distance( const double* from_point ) const;

    BoundBox& operator=( const BoundBox& from )
    {
        bMin = from.bMin;
        bMax = from.bMax;
        return *this;
    }
    inline bool operator==( const BoundBox& box ) const
    {
        return ( bMin == box.bMin && bMax == box.bMax );
    }

    CartVect bMin, bMax;
};

inline BoundBox::BoundBox( const double* corners )
{
    // relies on CartVect being Plain Old Data, no virtual table
    double* arr = bMin.array();
    for( int i = 0; i < 6; i++ )
        arr[i] = corners[i];
}

inline bool BoundBox::contains_point( const double* point, const double tol ) const
{
    if( point[0] < bMin[0] - tol || point[0] > bMax[0] + tol || point[1] < bMin[1] - tol || point[1] > bMax[1] + tol ||
        point[2] < bMin[2] - tol || point[2] > bMax[2] + tol )
        return false;
    else
        return true;
}

inline bool BoundBox::intersects_box( const BoundBox& b, const double tol ) const
{
    if( b.bMax[0] < bMin[0] - tol || b.bMin[0] > bMax[0] + tol || b.bMax[1] < bMin[1] - tol ||
        b.bMin[1] > bMax[1] + tol || b.bMax[2] < bMin[2] - tol || b.bMin[2] > bMax[2] + tol )
        return false;

    else
        return true;
}

inline void BoundBox::update( const BoundBox& other_box )
{
    update_min( other_box );
    update_max( other_box );
}

inline void BoundBox::update( const double* coords )
{
    update_min( coords );
    update_max( coords + 3 );
}

inline void BoundBox::update_min( const BoundBox& other_box )
{
    bMin[0] = std::min( bMin[0], other_box.bMin[0] );
    bMin[1] = std::min( bMin[1], other_box.bMin[1] );
    bMin[2] = std::min( bMin[2], other_box.bMin[2] );
}

inline void BoundBox::update_min( const double* coords )
{
    bMin[0] = std::min( bMin[0], coords[0] );
    bMin[1] = std::min( bMin[1], coords[1] );
    bMin[2] = std::min( bMin[2], coords[2] );
}

inline void BoundBox::update_max( const BoundBox& other_box )
{
    bMax[0] = std::max( bMax[0], other_box.bMax[0] );
    bMax[1] = std::max( bMax[1], other_box.bMax[1] );
    bMax[2] = std::max( bMax[2], other_box.bMax[2] );
}

inline void BoundBox::update_max( const double* coords )
{
    bMax[0] = std::max( bMax[0], coords[0] );
    bMax[1] = std::max( bMax[1], coords[1] );
    bMax[2] = std::max( bMax[2], coords[2] );
}

inline ErrorCode BoundBox::get( double* coords )
{
    bMin.get( coords );
    bMax.get( coords + 3 );
    return MB_SUCCESS;
}

inline void BoundBox::compute_center( CartVect& center )
{
    center = 0.5 * ( bMin + bMax );
}

inline std::ostream& operator<<( std::ostream& out, const BoundBox& box )
{
    out << ( std::string ) "Min: ";
    out << box.bMin;
    out << ( std::string ) ", Max: ";
    out << box.bMax;
    return out;
}

inline ErrorCode BoundBox::update( Interface& iface, const EntityHandle ent, bool spherical, double radius )
{
    Range tmp_range( ent, ent );
    return update( iface, tmp_range, spherical, radius );
}

inline double BoundBox::distance_squared( const double* from_point ) const
{
    double dist_sq = 0.0;
    for( int i = 0; i < 3; ++i )
    {
        if( from_point[i] < bMin[i] )
            dist_sq += ( bMin[i] - from_point[i] ) * ( bMin[i] - from_point[i] );
        else if( from_point[i] > bMax[i] )
            dist_sq += ( bMax[i] - from_point[i] ) * ( bMax[i] - from_point[i] );
    }
    return dist_sq;
}

inline double BoundBox::distance( const double* from_point ) const
{
    double dist_sq = distance_squared( from_point );
    return sqrt( dist_sq );
}

inline double BoundBox::diagonal_length() const
{
    if( DBL_MAX == bMax[0] || DBL_MAX == bMax[1] || DBL_MAX == bMax[2] || DBL_MAX == bMin[0] || DBL_MAX == bMin[1] ||
        DBL_MAX == bMin[2] )
        return DBL_MAX;
    return ( bMax - bMin ).length();
}

inline double BoundBox::diagonal_squared() const
{
    if( DBL_MAX == bMax[0] || DBL_MAX == bMax[1] || DBL_MAX == bMax[2] || DBL_MAX == bMin[0] || DBL_MAX == bMin[1] ||
        DBL_MAX == bMin[2] )
        return DBL_MAX;
    return ( bMax - bMin ).length_squared();
}

}  // namespace moab

#endif