Library of Assembled Shared Sources
min_max_policy.h
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2023 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43
44
45/** @defgroup MinMaxPolicy MinMaxPolicy
46 * @brief Policies to specify how an AABB traits misbehaving minima and maxima.
47 * @author Bram de Greve
48 * @date 2003
49 *
50 * The way an AABB handles its minima and maxima can be set by the template parameter
51 * @c MinMaxPolicy. One policy StrictMinMax will enforce you to use correct
52 * minima and maxima, and on any suspicious behaviour, it will throw an exception.
53 * And other policy AutoMinMax will try to correct misbehaviour without your
54 * notice. The third one is UncheckedMinMax and will ignore all errors in favour
55 * of faster code, but leading to undefined behaviour if you misbehave.
56 *
57 * For more information on these policies, I refer to the documentation
58 * compagning these policies.
59 *
60 * The content of the policies are rather implementation details, clients shouldn't
61 * worry about it.
62 *
63 * @note these policies can be used for points of any dimension.
64 */
65
66
67
68#ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_MIN_MAX_POLICY_H
69#define LASS_GUARDIAN_OF_INCLUSION_PRIM_MIN_MAX_POLICY_H
70
71#include "prim_common.h"
72
73namespace lass
74{
75namespace prim
76{
77
78/** Exception thrown by StrictMinMax
79 * @ingroup MinMaxPolicy
80 */
81class MinMaxError: public util::ExceptionMixin<MinMaxError>
82{
83public:
84 MinMaxError(std::string msg, std::string loc): util::ExceptionMixin<MinMaxError>(std::move(msg), std::move(loc)) {}
85 ~MinMaxError() noexcept {}
86};
87
88
89
90/** @ingroup MinMaxPolicy
91 * @brief MinMaxPolicy enforcing strict rules for the minima and maxima
92 * @author Bram de Greve
93 * @date 2003
94 *
95 * The strict policy will throw exceptions if the client misbehaves to the AABB.
96 * This policy demands that you set correct minima and maxima, it demands that the
97 * minimum is indeed a minimum. An very good example of misbehaviour would be to
98 * swap minimum and maximum. But not all component values of the minimum have to
99 * be greater than the maximum. To throw an exception, it's sufficient to have only
100 * one component value of the minimum to be greater than the corresponding component
101 * value of the maximum. This can lead to subtle errors. an example:
102 *
103 * @code
104 * Aabb3D<int, StrictMinMax> aabb(Point3D<int>(1, 2, 3), Point3D<int>(4, 5, 6));
105 * aabb.min() = Point3D<int>(5, 5, 5);
106 * @endcode
107 *
108 * The above example will throw an exception. The first line is correct, it constructs
109 * an AABB of which the maximum is indeed larger than the minimum. It's in the second
110 * line. Here, we try to adjust the minimum of the AABB by setting it to 3D point
111 * (5, 5, 5). The @a z coordinate is no problem: 5 is indeed less that 6. The @a y
112 * coordinate isn't a problem either: 5 is not greater than 5. It's the @a x coordinate
113 * that causes the trouble: 5 is greater than 4. Bang! an exception is thrown.
114 *
115 * The rest of the class are implementation details for the AABB and should not be
116 * called by the client (you :). In short we can say of this policy: make sure that
117 * minima are minima and maxima maxima.
118 */
120{
121 /** set value @a oMin to @a iMin
122 * @exception throw error if @a iMin it is in conflict with @a iMax.
123 */
124 template <typename PointType>
125 static void setMin(PointType& oMin, const PointType& iMax, const PointType& iMin)
126 {
127 if (pointwiseMin(iMin, iMax) != iMin)
128 {
129 LASS_THROW_EX(MinMaxError, "client tries to set invalid minimum '" << iMin
130 << "' with maximum '" << iMax << "'");
131 }
132 oMin = iMin;
133 }
134
135 /** set value @a oMax to @a iMax
136 * @exception throw error if @a iMax it is in conflict with @a iMin.
137 */
138 template <typename PointType>
139 static void setMax(const PointType& iMin, PointType& oMax, const PointType& iMax)
140 {
141 if (pointwiseMin(iMin, iMax) != iMin)
142 {
143 LASS_THROW_EX(MinMaxError, "client tries to set invalid maximum '" << iMax
144 << "' with minimum '" << iMin << "'");
145 }
146 oMax = iMax;
147 }
148
149 /** check if @a iMin and @a iMax are valid minima and maxima.
150 * @exception throw error if @a iMin and @a iMax are inconsistent.
151 */
152 template <typename PointType>
153 static void checkMinMax(const PointType& iMin, const PointType& iMax)
154 {
155 if (pointwiseMin(iMin, iMax) != iMin)
156 {
157 LASS_THROW_EX(MinMaxError, "inconsistent mininum '" << iMin << "' and maximum '" << iMax << "'");
158 }
159 }
160};
161
162
163
164
165
166
167/** @ingroup MinMaxPolicy
168 * @brief MinMaxPolicy automatically correcting wrong minima and maxima.
169 * @author Bram de Greve
170 * @date 2003
171 *
172 * The auto policy will @e silently correct wrong min/max situations by @e squeezing or
173 * @e swapping the values until a valid situation is achieved. How this is done, depends
174 * on the situation. We must consider two different possibities:
175 *
176 * - The easiest thing to explain is when you set both the minimum and the maximum at the
177 * same time. It can happen that you have swapped them by accident: you provided
178 * the maximum as minimum and vice versa. This policy will detect this and swap it again.
179 * Now the good thing is: it does this per component! So, you can have swapped @a x and
180 * @a y coordinates and coorect @a z coordinates, it will distill a correct minimum and
181 * maximum out of this. This is illustrated in the following example.
182 *
183 * @code
184 * Aabb3D<int, AutoMinMax> aabb(Point3D<int>(4, 5, 3), Point3D<int>(1, 2, 6));
185 * LASS_EVAL(aabb);
186 *
187 * // output: aabb == '(1, 2, 3)-(4, 5, 6)'
188 * @endcode
189 *
190 * - The other situation is when you only set the minimumm or maximum, and you want
191 * to keep to current maximum or minimum. In this case, we've opted for squeezing
192 * the values, rather than swapping them. The philosophy behind it is: when you
193 * set the minimum, you want to enforce a minimum. You don't want to be the maximum
194 * become a lesser minimum than the one you're setting, because it doesn't quite fit.
195 * No, instead of this, we squeeze or move the maximum along with the minimum. i.e.
196 * A new maximum is chooses so that it is not less than the current maximum, but
197 * not less than the new minimum either. It's hard to explain, but an example might
198 * illustrate this beautifully: for the @a y and @a z coordinate, there's nothing
199 * special to it: you set minimum values that are not greater than the maximum value,
200 * no misbehaviour here. On the other hand, for @a x coordinate the new minimum 5
201 * is greater than the current maximum 4. Instead of swapping this values so that 4
202 * becomes the new minimum, we enforce 5 as the minimum. All that is left is to
203 * choose a new value for the maximum @a x coordinate that is greater than 4 or not
204 * less than 5. Hmmm ... Would that be 5? :)
205 *
206 * @code
207 * Aabb3D<int, AutoMinMax> aabb(Point3D<int>(1, 2, 3), Point3D<int>(4, 5, 6));
208 * aabb.min() = Point3D<int>(5, 5, 5);
209 * LASS_EVAL(aabb);
210 *
211 * // output: aabb == '(5, 5, 5)-(5, 5, 6)'.
212 * @endcode
213 *
214 * @note this policy will @e not correct the empty state of an AABB. After all, in
215 * in contrary to other primitives, the empty state @e is a valid state for the
216 * AABB, so it does not have to be corrected.
217 *
218 * The rest of the class are implementation details for the AABB and should not be
219 * called by the client (you :). In short we can say of this policy: if you try to
220 * do something stupid, we try to correct it for you.
221 */
223{
224 /** set value @a oMin to @a iMin and move @a ioMax (if necessary) so it stays correct.
225 */
226 template <typename PointType>
227 static void setMin(PointType& oMin, PointType& ioMax, const PointType& iMin)
228 {
229 ioMax = pointwiseMax(ioMax, iMin);
230 oMin = iMin;
231 }
232
233 /** set value @a oMax to @a iMax and move @a ioMin (if necessary) so it stays correct.
234 */
235 template <typename PointType>
236 static void setMax(PointType& ioMin, PointType& oMax, const PointType& iMax)
237 {
238 ioMin = pointwiseMin(ioMin, iMax);
239 oMax = iMax;
240 }
241
242 /** correct @a ioMin and @a ioMax so that they are indeed then minimum and maximum.
243 */
244 template <typename PointType>
245 static void checkMinMax(PointType& ioMin, PointType& ioMax)
246 {
247 const PointType min = pointwiseMin(ioMin, ioMax);
248 ioMax = pointwiseMax(ioMin, ioMax);
249 ioMin = min;
250 }
251};
252
253
254
255/** @ingroup MinMaxPolicy
256 * @brief MinMaxPolicy that makes it your responsibility to behave well.
257 * @author Bram de Greve
258 * @date 2003
259 *
260 * The unchecked policy is the fastest policy of the pool. It will @e silently expects you to
261 * provide correct min/max values and ignores all invalid states caused by you. That way it
262 * can avoid all checks and it will be faster than the other to in speed ciritical situations.
263 *
264 * If you're using this policy, it's your responsibility to give the AABB correct values so it
265 * stays valid. If you don't, you'll get what we call undefined behaviour. Have fun :)
266 *
267 * The rest of the class are implementation details for the AABB and should not be
268 * called by the client (you :). In short we can say of this policy: if you try to
269 * do something stupid, you get undefined behaviour.
270 */
272{
273 /** set value @a oMin to @a iMin and move @a ioMax (if necessary) so it stays correct.
274 */
275 template <typename PointType>
276 static void setMin(PointType& oMin, PointType& /*ioMax*/, const PointType& iMin)
277 {
278 oMin = iMin;
279 }
280
281 /** set value @a oMax to @a iMax and move @a ioMin (if necessary) so it stays correct.
282 */
283 template <typename PointType>
284 static void setMax(PointType& /*ioMin*/, PointType& oMax, const PointType& iMax)
285 {
286 oMax = iMax;
287 }
288
289 /** correct @a ioMin and @a ioMax so that they are indeed then minimum and maximum.
290 */
291 template <typename PointType>
292 static void checkMinMax(PointType& /*ioMin*/, PointType& /*ioMax*/)
293 {
294 }
295};
296
297}
298
299}
300
301#endif
Exception thrown by StrictMinMax.
set of geometrical primitives
Definition aabb_2d.h:81
Library for Assembled Shared Sources.
Definition config.h:53
MinMaxPolicy automatically correcting wrong minima and maxima.
static void checkMinMax(PointType &ioMin, PointType &ioMax)
correct ioMin and ioMax so that they are indeed then minimum and maximum.
static void setMax(PointType &ioMin, PointType &oMax, const PointType &iMax)
set value oMax to iMax and move ioMin (if necessary) so it stays correct.
static void setMin(PointType &oMin, PointType &ioMax, const PointType &iMin)
set value oMin to iMin and move ioMax (if necessary) so it stays correct.
MinMaxPolicy enforcing strict rules for the minima and maxima.
static void checkMinMax(const PointType &iMin, const PointType &iMax)
check if iMin and iMax are valid minima and maxima.
static void setMin(PointType &oMin, const PointType &iMax, const PointType &iMin)
set value oMin to iMin
static void setMax(const PointType &iMin, PointType &oMax, const PointType &iMax)
set value oMax to iMax
MinMaxPolicy that makes it your responsibility to behave well.
static void setMax(PointType &, PointType &oMax, const PointType &iMax)
set value oMax to iMax and move ioMin (if necessary) so it stays correct.
static void setMin(PointType &oMin, PointType &, const PointType &iMin)
set value oMin to iMin and move ioMax (if necessary) so it stays correct.
static void checkMinMax(PointType &, PointType &)
correct ioMin and ioMax so that they are indeed then minimum and maximum.