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 SbBox2s SbBox2s.h Inventor/SbBox2s.h
35   \brief The SbBox2s class is a 2 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, which is among other things useful for representing
43   screen or canvas areas in absolute window coordinates.
44 
45   \sa SbBox2f, SbBox2d, SbBox3s, SbBox3f, SbBox3d, SbXfBox3f.
46 */
47 
48 // *************************************************************************
49 
50 #include <Inventor/SbBox2s.h>
51 
52 #include <limits>
53 #include <cassert>
54 
55 #include <Inventor/SbBox2i32.h>
56 #include <Inventor/SbBox2f.h>
57 #include <Inventor/SbBox2d.h>
58 #include <Inventor/errors/SoDebugError.h>
59 
60 // *************************************************************************
61 
62 /*!
63   \fn SbBox2s::SbBox2s(void)
64 
65   The default constructor makes an empty box.
66 */
67 
68 /*!
69   \fn SbBox2s::SbBox2s(short xmin, short ymin, short xmax, short ymax)
70 
71   Constructs a box with the given corner coordinates.
72 
73   \a xmin should be less than \a xmax and \a ymin should be less than
74   \a ymax if you want to make a valid box.
75 */
76 
77 /*!
78   \fn SbBox2s::SbBox2s(const SbVec2s & boxmin, const SbVec2s & boxmax)
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 SbBox2s & SbBox2s::setBounds(short xmin, short ymin, short xmax, short ymax)
88 
89   Reset the boundaries of the box.
90 
91   \a xmin should be less than \a xmax and \a ymin should be less than
92   \a ymax if you want to make a valid box.
93 
94   Returns reference to self.
95 
96   \sa getBounds().
97 */
98 
99 /*!
100   \fn SbBox2s & SbBox2s::setBounds(const SbVec2s & boxmin, const SbVec2s & boxmax)
101 
102   Reset the boundaries of the box with the given corners.
103 
104   The coordinates of \a min should be less than the coordinates of
105   \a max if you want to make a valid box.
106 
107   Returns reference to self.
108 
109   \sa getBounds().
110 */
111 
112 /*!
113   Reset the boundaries with the boundaries of the given \a box.
114 
115   Returns reference to self.
116 
117   \sa setBounds()
118 */
119 
120 SbBox2s &
setBounds(const SbBox2i32 & box)121 SbBox2s::setBounds(const SbBox2i32 & box)
122 {
123   if (box.isEmpty()) {
124     makeEmpty();
125   } else {
126     minpt.setValue(box.getMin());
127     maxpt.setValue(box.getMax());
128   }
129   return *this;
130 }
131 
132 /*!
133   Reset the boundaries with the boundaries of the given \a box.
134 
135   Returns reference to self.
136 
137   \sa setBounds()
138 */
139 
140 SbBox2s &
setBounds(const SbBox2f & box)141 SbBox2s::setBounds(const SbBox2f & box)
142 {
143   if (box.isEmpty()) {
144     makeEmpty();
145   } else {
146     minpt.setValue(box.getMin());
147     maxpt.setValue(box.getMax());
148   }
149   return *this;
150 }
151 
152 /*!
153   Reset the boundaries with the boundaries of the given \a box.
154 
155   Returns reference to self.
156 
157   \sa setBounds()
158 */
159 
160 SbBox2s &
setBounds(const SbBox2d & box)161 SbBox2s::setBounds(const SbBox2d & box)
162 {
163   if (box.isEmpty()) {
164     makeEmpty();
165   } else {
166     minpt.setValue(box.getMin());
167     maxpt.setValue(box.getMax());
168   }
169   return *this;
170 }
171 
172 /*!
173   Marks this as an empty box.
174 
175   \sa isEmpty().
176 */
177 void
makeEmpty(void)178 SbBox2s::makeEmpty(void)
179 {
180   minpt.setValue(std::numeric_limits<short>::max(), std::numeric_limits<short>::max());
181   maxpt.setValue(-std::numeric_limits<short>::max(), -std::numeric_limits<short>::max());
182 }
183 
184 /*!
185   \fn const SbVec2s & SbBox2s::getMin(void) const
186 
187   Returns the minimum point. This should usually be the lower left corner
188   point of the box.
189 
190   \sa getOrigin(), getMax().
191 */
192 
193 /*!
194   \fn const SbVec2s & SbBox2s::getMax(void) const
195 
196   Returns the maximum point. This should usually be the upper right corner
197   point of the box.
198 
199   \sa getMin().
200 */
201 
202 /*!
203   Extend the boundaries of the box by the given point, i.e. make the
204   point fit inside the box if it isn't already within it.
205 */
206 void
extendBy(const SbVec2s & point)207 SbBox2s::extendBy(const SbVec2s & point)
208 {
209   // The explicit casts are done to humour the HPUX aCC compiler,
210   // which will otherwise say ``Template deduction failed to find a
211   // match for the call to 'SbMin'''. mortene.
212   this->minpt.setValue(SbMin(static_cast<short>(point[0]), static_cast<short>(this->minpt[0])),
213                        SbMin(static_cast<short>(point[1]), static_cast<short>(this->minpt[1])));
214   this->maxpt.setValue(SbMax(static_cast<short>(point[0]), static_cast<short>(this->maxpt[0])),
215                        SbMax(static_cast<short>(point[1]), static_cast<short>(this->maxpt[1])));
216 }
217 
218 /*!
219   Extend the boundaries of the box by the given \a box parameter. This
220   is equal to calling extendBy() twice with the corner points.
221 */
222 void
extendBy(const SbBox2s & box)223 SbBox2s::extendBy(const SbBox2s & box)
224 {
225   if (box.isEmpty()) { return; }
226 
227   this->extendBy(box.getMin());
228   this->extendBy(box.getMax());
229 }
230 
231 /*!
232   Check if the given point lies within the boundaries of this box.
233 */
234 SbBool
intersect(const SbVec2s & point) const235 SbBox2s::intersect(const SbVec2s & point) const
236 {
237   if((point[0] >= this->minpt[0]) && (point[0] <= this->maxpt[0]) &&
238      (point[1] >= this->minpt[1]) && (point[1] <= this->maxpt[1])) return TRUE;
239   return FALSE;
240 }
241 
242 /*!
243   Check if \a box lies wholly or partly within the boundaries
244   of this box.
245 */
246 SbBool
intersect(const SbBox2s & box) const247 SbBox2s::intersect(const SbBox2s & box) const
248 {
249   if((box.getMax()[0] < this->getMin()[0]) ||
250      (box.getMax()[1] < this->getMin()[1]) ||
251      (box.getMin()[0] > this->getMax()[0]) ||
252      (box.getMin()[1] > this->getMax()[1])) return FALSE;
253   return TRUE;
254 }
255 
256 /*!
257   \fn void SbBox2s::getBounds(short & xmin, short & ymin, short & xmax, short & ymax) const
258 
259   Returns the box boundary coordinates.
260 
261   \sa setBounds(), getMin(), getMax().
262 */
263 
264 /*!
265   \fn void SbBox2s::getBounds(SbVec2s & boxmin, SbVec2s & boxmax) const
266 
267   Returns the box corner points.
268 
269   \sa setBounds(), getMin(), getMax().
270 */
271 
272 /*!
273   \fn void SbBox2s::getOrigin(short & originX, short & originY) const
274 
275   Returns the coordinates of the box origin (i.e. the lower left corner).
276 
277   \sa getMin().
278 */
279 
280 /*!
281   \fn void SbBox2s::getSize(short & sizeX, short & sizeY) const
282 
283   Returns width and height of box.
284 */
285 
286 /*!
287   \fn float SbBox2s::getAspectRatio(void) const
288 
289   Returns aspect ratio of box, which is defined as box width divided on
290   box height.
291 */
292 
293 /*!
294   \fn int operator == (const SbBox2s & b1, const SbBox2s & b2)
295   \relates SbBox2s
296 
297   Check \a b1 and \a b2 for equality.
298 */
299 
300 /*!
301   \fn int operator != (const SbBox2s & b1, const SbBox2s & b2)
302   \relates SbBox2s
303 
304   Check \a b1 and \a b2 for inequality.
305 */
306 
307 /*!
308   \fn SbBool SbBox2s::hasArea(void) const
309 */
310 
311 #ifdef COIN_TEST_SUITE
BOOST_AUTO_TEST_CASE(checkSize)312 BOOST_AUTO_TEST_CASE(checkSize) {
313   SbVec2s min(1,2);
314   SbVec2s max(3,4);
315 
316   SbVec2s diff = max - min;
317 
318 
319   SbBox2s box(min, max);
320 
321   BOOST_CHECK_MESSAGE(box.getSize() == diff,
322                       "Box has incorrect size");
323 
324 }
325 #endif //COIN_TEST_SUITE
326