1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 /*!
34 \class SbBox3s SbBox3s.h Inventor/SbBox3s.h
35 \brief The SbBox3s class is a 3 dimensional box with short
36 integer coordinates.
37
38 \ingroup base
39
40 This box class is used by other classes in Coin for data
41 exchange. It provides storage for two box corners with short integer
42 coordinates.
43
44 \sa SbBox2s, SbBox2f, SbBox2d, SbBox3f, SbBox3d, SbXfBox3f.
45 \since Coin 2.0
46 \since TGS Inventor ?.?
47 */
48
49
50 #include <Inventor/SbBox3s.h>
51
52 #include <limits>
53 #include <cassert>
54
55 #include <Inventor/SbBox3i32.h>
56 #include <Inventor/SbBox3f.h>
57 #include <Inventor/SbBox3d.h>
58 #if COIN_DEBUG
59 #include <Inventor/errors/SoDebugError.h>
60 #endif // COIN_DEBUG
61
62 /*!
63 \fn SbBox3s::SbBox3s(void)
64 The default constructor makes an empty box.
65 */
66
67 /*!
68 \fn SbBox3s::SbBox3s(short xmin, short ymin, short zmin, short xmax, short ymax, short zmax)
69
70 Constructs a box with the given corner coordinates.
71
72 \a xmin should be less than \a xmax, \a ymin should be less than \a
73 ymax, and \a zmin should be less than \a zmax if you want to make a
74 valid box.
75 */
76
77 /*!
78 \fn SbBox3s::SbBox3s(const SbVec3s & minvec, const SbVec3s & maxvec)
79
80 Constructs a box with the given corners.
81
82 The coordinates of \a min should be less than the coordinates of
83 \a max if you want to make a valid box.
84 */
85
86 /*!
87 \fn SbBox3s & SbBox3s::setBounds(short xmin, short ymin, short zmin, short xmax, short ymax, short zmax)
88
89 Reset the boundaries of the box.
90
91 \a xmin should be less than \a xmax, \a ymin should be less than \a
92 ymax, and \a zmin should be less than \a xmax if you want to make a
93 valid box.
94
95 Returns reference to self.
96
97 \sa getBounds().
98 */
99
100 /*!
101 \fn SbBox3s & SbBox3s::setBounds(const SbVec3s & minvec, const SbVec3s & maxvec)
102
103 Reset the boundaries of the box with the given corners.
104
105 The coordinates of \a minvec should be less than the coordinates of
106 \a maxvec if you want to make a valid box.
107
108 Returns reference to self.
109
110 \sa getBounds().
111 */
112
113 /*!
114 Reset the boundaries to the boundaries of the given \a box.
115
116 Returns reference to self.
117
118 \sa getBounds().
119 */
120
121 SbBox3s &
setBounds(const SbBox3i32 & box)122 SbBox3s::setBounds(const SbBox3i32 & box)
123 {
124 if (box.isEmpty()) {
125 makeEmpty();
126 } else {
127 minpt.setValue(box.getMin());
128 maxpt.setValue(box.getMax());
129 }
130 return *this;
131 }
132
133 /*!
134 Reset the boundaries to the boundaries of the given \a box.
135
136 Returns reference to self.
137
138 \sa getBounds().
139 */
140
141 SbBox3s &
setBounds(const SbBox3f & box)142 SbBox3s::setBounds(const SbBox3f & box)
143 {
144 if (box.isEmpty()) {
145 makeEmpty();
146 } else {
147 minpt.setValue(box.getMin());
148 maxpt.setValue(box.getMax());
149 }
150 return *this;
151 }
152
153 /*!
154 Reset the boundaries to the boundaries of the given \a box.
155
156 Returns reference to self.
157
158 \sa getBounds().
159 */
160
161 SbBox3s &
setBounds(const SbBox3d & box)162 SbBox3s::setBounds(const SbBox3d & box)
163 {
164 if (box.isEmpty()) {
165 makeEmpty();
166 } else {
167 minpt.setValue(box.getMin());
168 maxpt.setValue(box.getMax());
169 }
170 return *this;
171 }
172
173 /*!
174 Marks this as an empty box.
175
176 \sa isEmpty().
177 */
178 void
makeEmpty(void)179 SbBox3s::makeEmpty(void)
180 {
181 this->minpt.setValue(std::numeric_limits<short>::max(), std::numeric_limits<short>::max(), std::numeric_limits<short>::max());
182 this->maxpt.setValue(-std::numeric_limits<short>::max(), -std::numeric_limits<short>::max(), -std::numeric_limits<short>::max());
183 }
184
185 /*!
186 \fn const SbVec3s & SbBox3s::getMin(void) const
187
188 Returns the minimum point. This should usually be the lower left corner
189 point of the box.
190
191 \sa getOrigin(), getMax().
192 */
193
194 /*!
195 \fn const SbVec3s & SbBox3s::getMax(void) const
196
197 Returns the maximum point. This should usually be the upper right corner
198 point of the box.
199
200 \sa getMin().
201 */
202
203 /*!
204 Extend the boundaries of the box by the given point, i.e. make the
205 point fit inside the box if it isn't already within it.
206 */
207 void
extendBy(const SbVec3s & point)208 SbBox3s::extendBy(const SbVec3s & point)
209 {
210 // The explicit casts are done to humour the HPUX aCC compiler,
211 // which will otherwise say ``Template deduction failed to find a
212 // match for the call to 'SbMin'''. mortene.
213 this->minpt.setValue(SbMin(static_cast<short>(point[0]), static_cast<short>(this->minpt[0])),
214 SbMin(static_cast<short>(point[1]), static_cast<short>(this->minpt[1])),
215 SbMin(static_cast<short>(point[2]), static_cast<short>(this->minpt[2])));
216 this->maxpt.setValue(SbMax(static_cast<short>(point[0]), static_cast<short>(this->maxpt[0])),
217 SbMax(static_cast<short>(point[1]), static_cast<short>(this->maxpt[1])),
218 SbMax(static_cast<short>(point[2]), static_cast<short>(this->maxpt[2])));
219 }
220
221 /*!
222 Extend the boundaries of the box by the given \a box parameter. This
223 is equal to calling extendBy() twice with the corner points.
224 */
225 void
extendBy(const SbBox3s & box)226 SbBox3s::extendBy(const SbBox3s & box)
227 {
228 if (box.isEmpty()) { return; }
229
230 this->extendBy(box.getMin());
231 this->extendBy(box.getMax());
232 }
233
234 /*!
235 Check if the given point lies within the boundaries of this box.
236 */
237 SbBool
intersect(const SbVec3s & point) const238 SbBox3s::intersect(const SbVec3s & point) const
239 {
240 if((point[0] >= this->minpt[0]) && (point[0] <= this->maxpt[0]) &&
241 (point[1] >= this->minpt[1]) && (point[1] <= this->maxpt[1]) &&
242 (point[2] >= this->minpt[2]) && (point[2] <= this->maxpt[2])) return TRUE;
243 return FALSE;
244 }
245
246 /*!
247 Check if \a box lies wholly or partly within the boundaries
248 of this box.
249 */
250 SbBool
intersect(const SbBox3s & box) const251 SbBox3s::intersect(const SbBox3s & box) const
252 {
253 if((box.getMax()[0] < this->getMin()[0]) ||
254 (box.getMax()[1] < this->getMin()[1]) ||
255 (box.getMax()[2] < this->getMin()[2]) ||
256 (box.getMin()[0] > this->getMax()[0]) ||
257 (box.getMin()[1] > this->getMax()[1]) ||
258 (box.getMin()[2] > this->getMax()[2])) return FALSE;
259 return TRUE;
260 }
261
262 /*!
263 */
264
265 SbVec3f
getClosestPoint(const SbVec3f & pt) const266 SbBox3s::getClosestPoint(const SbVec3f & pt) const
267 {
268 SbVec3f closest = pt;
269
270 SbVec3f center = this->getCenter();
271 float devx = closest[0] - center[0];
272 float devy = closest[1] - center[1];
273 float devz = closest[2] - center[2];
274 float halfwidth = float(this->maxpt[0] - this->minpt[0]) / 2.0f;
275 float halfheight = float(this->maxpt[1] - this->minpt[1]) / 2.0f;
276 float halfdepth = float(this->maxpt[2] - this->minpt[2]) / 2.0f;
277
278 // Move point to be on the nearest plane of the box.
279 if ((fabs(devx) > fabs(devy)) && (fabs(devx) > fabs(devz)))
280 closest[0] = center[0] + halfwidth * ((devx < 0.0f) ? -1.0f : 1.0f);
281 else if (fabs(devy) > fabs(devz))
282 closest[1] = center[1] + halfheight * ((devy < 0.0f) ? -1.0f : 1.0f);
283 else
284 closest[2] = center[2] + halfdepth * ((devz < 0.0f) ? -1.0f : 1.0f);
285
286 // Clamp to be inside box.
287 closest[0] = SbMin(SbMax(closest[0], float(minpt[0])), float(maxpt[0]));
288 closest[1] = SbMin(SbMax(closest[1], float(minpt[1])), float(maxpt[1]));
289 closest[2] = SbMin(SbMax(closest[2], float(minpt[2])), float(maxpt[2]));
290
291 return closest;
292 }
293
294 /*!
295 \fn void SbBox3s::getBounds(short & xmin, short & ymin, short & zmin, short & xmax, short & ymax, short & zmax) const
296
297 Returns the box boundary coordinates.
298
299 \sa setBounds(), getMin(), getMax().
300 */
301
302 /*!
303 \fn void SbBox3s::getBounds(SbVec3s & minvec, SbVec3s & maxvec) const
304
305 Returns the box corner points.
306
307 \sa setBounds(), getMin(), getMax().
308 */
309
310 /*!
311 \fn void SbBox3s::getOrigin(short & originX, short & originY, short & originZ) const
312
313 Returns the coordinates of the box origin (i.e. the lower left corner).
314
315 \sa getMin().
316 */
317
318 /*!
319 \fn void SbBox3s::getSize(short & sizeX, short & sizeY, short & sizeZ) const
320
321 Returns width and height of box.
322 */
323
324 /*!
325 \fn int operator == (const SbBox3s & b1, const SbBox3s & b2)
326 \relates SbBox3s
327
328 Check \a b1 and \a b2 for equality.
329 */
330
331 /*!
332 \fn int operator != (const SbBox3s & b1, const SbBox3s & b2)
333 \relates SbBox3s
334
335 Check \a b1 and \a b2 for inequality.
336 */
337
338 /*!
339 \fn SbBool SbBox3s::hasVolume(void) const
340 */
341
342 #ifdef COIN_TEST_SUITE
BOOST_AUTO_TEST_CASE(checkSize)343 BOOST_AUTO_TEST_CASE(checkSize) {
344 SbVec3s min(1,2,3);
345 SbVec3s max(3,4,5);
346
347 SbVec3s diff = max - min;
348
349
350 SbBox3s box(min, max);
351
352 BOOST_CHECK_MESSAGE(box.getSize() == diff,
353 "Box has incorrect size");
354
355 }
356 #endif //COIN_TEST_SUITE
357