library of assembled shared sources

http://lass.cocamware.com

min_max_policy.h

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 
00044 
00045 /** @defgroup MinMaxPolicy MinMaxPolicy
00046  *  @brief Policies to specify how an AABB traits misbehaving minima and maxima.
00047  *  @author Bram de Greve
00048  *  @date 2003
00049  *
00050  *  The way an AABB handles its minima and maxima can be set by the template parameter
00051  *  @c MinMaxPolicy.  One policy StrictMinMax will enforce you to use correct
00052  *  minima and maxima, and on any suspicious behaviour, it will throw an exception.
00053  *  And other policy AutoMinMax will try to correct misbehaviour without your
00054  *  notice.  The third one is UncheckedMinMax and will ignore all errors in favour
00055  *  of faster code, but leading to undefined behaviour if you misbehave.
00056  *
00057  *  For more information on these policies, I refer to the documentation
00058  *  compagning these policies.
00059  *
00060  *  The content of the policies are rather implementation details, clients shouldn't
00061  *  worry about it.
00062  *
00063  *  @note these policies can be used for points of any dimension.
00064  */
00065 
00066 
00067 
00068 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_MIN_MAX_POLICY_H
00069 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_MIN_MAX_POLICY_H
00070 
00071 namespace lass
00072 {
00073 namespace prim
00074 {
00075 
00076 /** Exception thrown by StrictMinMax
00077  *  @ingroup MinMaxPolicy
00078  */
00079 class MinMaxError: public util::Exception
00080 {
00081 public:
00082     MinMaxError(const std::string& msg, const std::string& loc): util::Exception(msg, loc) {}
00083 private:
00084     LASS_UTIL_EXCEPTION_PRIVATE_IMPL(MinMaxError)
00085 };
00086 
00087 
00088 
00089 /** @ingroup MinMaxPolicy
00090  *  @brief MinMaxPolicy enforcing strict rules for the minima and maxima
00091  *  @author Bram de Greve
00092  *  @date 2003
00093  *
00094  *  The strict policy will throw exceptions if the client misbehaves to the AABB.
00095  *  This policy demands that you set correct minima and maxima, it demands that the
00096  *  minimum is indeed a minimum.  An very good example of misbehaviour would be to
00097  *  swap minimum and maximum.  But not all component values of the minimum have to
00098  *  be greater than the maximum.  To throw an exception, it's sufficient to have only
00099  *  one component value of the minimum to be greater than the corresponding component
00100  *  value of the maximum.  This can lead to subtle errors.  an example:
00101  *
00102  *  @code
00103  *  Aabb3D<int, StrictMinMax> aabb(Point3D<int>(1, 2, 3), Point3D<int>(4, 5, 6));
00104  *  aabb.min() = Point3D<int>(5, 5, 5);
00105  *  @endcode
00106  *
00107  *  The above example will throw an exception.  The first line is correct, it constructs
00108  *  an AABB of which the maximum is indeed larger than the minimum.  It's in the second
00109  *  line.  Here, we try to adjust the minimum of the AABB by setting it to 3D point
00110  *  (5, 5, 5).  The @a z coordinate is no problem: 5 is indeed less that 6.  The @a y
00111  *  coordinate isn't a problem either: 5 is not greater than 5.  It's the @a x coordinate
00112  *  that causes the trouble: 5 is greater than 4.  Bang!  an exception is thrown.
00113  *
00114  *  The rest of the class are implementation details for the AABB and should not be
00115  *  called by the client (you :).  In short we can say of this policy: make sure that
00116  *  minima are minima and maxima maxima.
00117  */
00118 struct StrictMinMax
00119 {
00120     /** set value @a oMin to @a iMin
00121      *  @exception throw error if @a iMin it is in conflict with @a iMax.
00122      */
00123     template <typename PointType>
00124     static void setMin(PointType& oMin, const PointType& iMax, const PointType& iMin)
00125     {
00126         if (pointwiseMin(iMin, iMax) != iMin)
00127         {
00128             LASS_THROW_EX(MinMaxError, "client tries to set invalid minimum '" << iMin
00129                 << "' with maximum '" << iMax << "'");
00130         }
00131         oMin = iMin;
00132     }
00133 
00134     /** set value @a oMax to @a iMax
00135      *  @exception throw error if @a iMax it is in conflict with @a iMin.
00136      */
00137     template <typename PointType>
00138     static void setMax(const PointType& iMin, PointType& oMax, const PointType& iMax)
00139     {
00140         if (pointwiseMin(iMin, iMax) != iMin)
00141         {
00142             LASS_THROW_EX(MinMaxError, "client tries to set invalid maximum '" << iMax
00143                 << "' with minimum '" << iMin << "'");
00144         }
00145         oMax = iMax;
00146     }
00147 
00148     /** check if @a iMin and @a iMax are valid minima and maxima.
00149      *  @exception throw error if @a iMin and @a iMax are inconsistent.
00150      */
00151     template <typename PointType>
00152     static void checkMinMax(const PointType& iMin, const PointType& iMax)
00153     {
00154         if (pointwiseMin(iMin, iMax) != iMin)
00155         {
00156             LASS_THROW_EX(MinMaxError, "inconsistent mininum '" << iMin << "' and maximum '" << iMax << "'");
00157         }
00158     }
00159 };
00160 
00161 
00162 
00163 
00164 
00165 
00166 /** @ingroup MinMaxPolicy
00167  *  @brief MinMaxPolicy automatically correcting wrong minima and maxima.
00168  *  @author Bram de Greve
00169  *  @date 2003
00170  *
00171  *  The auto policy will @e silently correct wrong min/max situations by @e squeezing or
00172  *  @e swapping the values until a valid situation is achieved.  How this is done, depends
00173  *  on the situation.  We must consider two different possibities:
00174  *
00175  *  - The easiest thing to explain is when you set both the minimum and the maximum at the
00176  *  same time.  It can happen that you have swapped them by accident: you provided
00177  *  the maximum as minimum and vice versa.  This policy will detect this and swap it again.
00178  *  Now the good thing is: it does this per component!  So, you can have swapped @a x and
00179  *  @a y coordinates and coorect @a z coordinates, it will distill a correct minimum and
00180  *  maximum out of this.  This is illustrated in the following example.
00181  *
00182  *  @code
00183  *  Aabb3D<int, AutoMinMax> aabb(Point3D<int>(4, 5, 3), Point3D<int>(1, 2, 6));
00184  *  LASS_EVAL(aabb);
00185  *
00186  *  // output: aabb == '(1, 2, 3)-(4, 5, 6)'
00187  *  @endcode
00188  *
00189  *  - The other situation is when you only set the minimumm or maximum, and you want
00190  *    to keep to current maximum or minimum.  In this case, we've opted for squeezing
00191  *    the values, rather than swapping them.  The philosophy behind it is: when you
00192  *    set the minimum, you want to enforce a minimum.  You don't want to be the maximum
00193  *    become a lesser minimum than the one you're setting, because it doesn't quite fit.
00194  *    No, instead of this, we squeeze or move the maximum along with the minimum.  i.e.
00195  *    A new maximum is chooses so that it is not less than the current maximum, but
00196  *    not less than the new minimum either.  It's hard to explain, but an example might
00197  *    illustrate this beautifully: for the @a y and @a z coordinate, there's nothing
00198  *    special to it: you set minimum values that are not greater than the maximum value,
00199  *    no misbehaviour here.  On the other hand, for @a x coordinate the new minimum 5
00200  *    is greater than the current maximum 4.  Instead of swapping this values so that 4
00201  *    becomes the new minimum, we enforce 5 as the minimum.  All that is left is to
00202  *    choose a new value for the maximum @a x coordinate that is greater than 4 or not
00203  *    less than 5.  Hmmm ... Would that be 5? :)
00204  *
00205  *  @code
00206  *  Aabb3D<int, AutoMinMax> aabb(Point3D<int>(1, 2, 3), Point3D<int>(4, 5, 6));
00207  *  aabb.min() = Point3D<int>(5, 5, 5);
00208  *  LASS_EVAL(aabb);
00209  *
00210  *  // output: aabb == '(5, 5, 5)-(5, 5, 6)'.
00211  *  @endcode
00212  *
00213  *  @note this policy will @e not correct the empty state of an AABB.  After all, in
00214  *        in contrary to other primitives, the empty state @e is a valid state for the
00215  *        AABB, so it does not have to be corrected.
00216  *
00217  *  The rest of the class are implementation details for the AABB and should not be
00218  *  called by the client (you :).  In short we can say of this policy: if you try to
00219  *  do something stupid, we try to correct it for you.
00220  */
00221 struct AutoMinMax
00222 {
00223     /** set value @a oMin to @a iMin and move @a ioMax (if necessary) so it stays correct.
00224      */
00225     template <typename PointType>
00226     static void setMin(PointType& oMin, PointType& ioMax, const PointType& iMin)
00227     {
00228         ioMax = pointwiseMax(ioMax, iMin);
00229         oMin = iMin;
00230     }
00231 
00232     /** set value @a oMax to @a iMax and move @a ioMin (if necessary) so it stays correct.
00233      */
00234     template <typename PointType>
00235     static void setMax(PointType& ioMin, PointType& oMax, const PointType& iMax)
00236     {
00237         ioMin = pointwiseMin(ioMin, iMax);
00238         oMax = iMax;
00239     }
00240 
00241     /** correct @a ioMin and @a ioMax so that they are indeed then minimum and maximum.
00242      */
00243     template <typename PointType>
00244     static void checkMinMax(PointType& ioMin, PointType& ioMax)
00245     {
00246         const PointType min = pointwiseMin(ioMin, ioMax);
00247         ioMax = pointwiseMax(ioMin, ioMax);
00248         ioMin = min;
00249     }
00250 };
00251 
00252 
00253 
00254 /** @ingroup MinMaxPolicy
00255  *  @brief MinMaxPolicy that makes it your responsibility to behave well.
00256  *  @author Bram de Greve
00257  *  @date 2003
00258  *
00259  *  The unchecked policy is the fastest policy of the pool.  It will @e silently expects you to
00260  *  provide correct min/max values and ignores all invalid states caused by you.  That way it
00261  *  can avoid all checks and it will be faster than the other to in speed ciritical situations.
00262  *
00263  *  If you're using this policy, it's your responsibility to give the AABB correct values so it
00264  *  stays valid.  If you don't, you'll get what we call undefined behaviour.  Have fun :)
00265  *
00266  *  The rest of the class are implementation details for the AABB and should not be
00267  *  called by the client (you :).  In short we can say of this policy: if you try to
00268  *  do something stupid, you get undefined behaviour.
00269  */
00270 struct UncheckedMinMax
00271 {
00272     /** set value @a oMin to @a iMin and move @a ioMax (if necessary) so it stays correct.
00273      */
00274     template <typename PointType>
00275     static void setMin(PointType& oMin, PointType& ioMax, const PointType& iMin)
00276     {
00277         oMin = iMin;
00278     }
00279 
00280     /** set value @a oMax to @a iMax and move @a ioMin (if necessary) so it stays correct.
00281      */
00282     template <typename PointType>
00283     static void setMax(PointType& ioMin, PointType& oMax, const PointType& iMax)
00284     {
00285         oMax = iMax;
00286     }
00287 
00288     /** correct @a ioMin and @a ioMax so that they are indeed then minimum and maximum.
00289      */
00290     template <typename PointType>
00291     static void checkMinMax(PointType& /*ioMin*/, PointType& /*ioMax*/)
00292     {
00293     }
00294 };
00295 
00296 }
00297 
00298 }
00299 
00300 #endif

Generated on Mon Nov 10 14:20:31 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo