summaryrefslogtreecommitdiffstats
path: root/libdimension/dimension/math/aabb.h
blob: 4eb78704f198246a9852680080d03504ab01517d (plain)
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
/*************************************************************************
 * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com>     *
 *                                                                       *
 * This file is part of The Dimension Library.                           *
 *                                                                       *
 * The Dimension 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 3 of the *
 * License, or (at your option) any later version.                       *
 *                                                                       *
 * The Dimension 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 for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this program.  If not, see                         *
 * <http://www.gnu.org/licenses/>.                                       *
 *************************************************************************/

/**
 * @file
 * Axis-aligned bounding boxes.
 */

#ifndef DMNSN_MATH_H
#error "Please include <dimension/math.h> instead of this header directly."
#endif

/** An axis-aligned bounding box. */
typedef struct dmnsn_aabb {
  dmnsn_vector min; /**< The coordinate-wise minimum extent of the box. */
  dmnsn_vector max; /**< The coordinate-wise maximum extent of the box. */
} dmnsn_aabb;

/** A standard format string for bounding boxes. */
#define DMNSN_AABB_FORMAT "(<%g, %g, %g> ==> <%g, %g, %g>)"
/** The appropriate arguements to printf() a bounding box. */
#define DMNSN_AABB_PRINTF(box)                                          \
  DMNSN_VECTOR_PRINTF((box).min), DMNSN_VECTOR_PRINTF((box).max)

/**
 * Construct a new bounding box.
 * @param[in] min  The minimal extent of the bounding box.
 * @param[in] max  The maximal extent of the bounding box.
 * @return The new bounding box.
 */
DMNSN_INLINE dmnsn_aabb
dmnsn_new_aabb(dmnsn_vector min, dmnsn_vector max)
{
  dmnsn_aabb box = { min, max };
  return box;
}

/** Return the bounding box which contains nothing. */
DMNSN_INLINE dmnsn_aabb
dmnsn_zero_aabb(void)
{
  dmnsn_aabb box = {
    { {  DMNSN_INFINITY,  DMNSN_INFINITY,  DMNSN_INFINITY } },
    { { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY } }
  };
  return box;
}

/** Return the bounding box which contains everything. */
DMNSN_INLINE dmnsn_aabb
dmnsn_infinite_aabb(void)
{
  dmnsn_aabb box = {
    { { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY } },
    { {  DMNSN_INFINITY,  DMNSN_INFINITY,  DMNSN_INFINITY } }
  };
  return box;
}

/**
 * Construct a new symmetric bounding box.
 * @param[in] r  The extent of the bounding box from the origin.
 * @return The new bounding box.
 */
DMNSN_INLINE dmnsn_aabb
dmnsn_symmetric_aabb(dmnsn_vector r)
{
  dmnsn_vector minus_r = dmnsn_vector_negate(r);
  dmnsn_aabb box = {
    dmnsn_vector_min(r, minus_r),
    dmnsn_vector_max(r, minus_r)
  };
  return box;
}

/** Return whether \p p is within the axis-aligned bounding box. */
DMNSN_INLINE bool
dmnsn_aabb_contains(dmnsn_aabb box, dmnsn_vector p)
{
  for (unsigned int i = 0; i < 3; ++i) {
    if (p.n[i] < box.min.n[i]) {
      return false;
    }
  }

  for (unsigned int i = 0; i < 3; ++i) {
    if (p.n[i] > box.max.n[i]) {
      return false;
    }
  }

  return true;
}

/** Return whether a bounding box is infinite. */
DMNSN_INLINE bool
dmnsn_aabb_is_infinite(dmnsn_aabb box)
{
  return box.min.n[0] == -DMNSN_INFINITY;
}

/**
 * Expand a bounding box to contain a point
 * @param[in] box  The bounding box to expand.
 * @param[in] point  The point to swallow.
 * @return The expanded bounding box.
 */
DMNSN_INLINE dmnsn_aabb
dmnsn_aabb_swallow(dmnsn_aabb box, dmnsn_vector point)
{
  dmnsn_aabb ret = {
    dmnsn_vector_min(box.min, point),
    dmnsn_vector_max(box.max, point)
  };
  return ret;
}

/** Return whether a bounding box has any NaN components. */
DMNSN_INLINE bool
dmnsn_aabb_isnan(dmnsn_aabb box)
{
  return dmnsn_vector_isnan(box.min) || dmnsn_vector_isnan(box.max);
}