/*
* Copyright 2010 SRI International
*
* This program 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.
*
* This program 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 .
*/
#ifndef OPEN_KARTO_MATH_H
#define OPEN_KARTO_MATH_H
#include
#include
#include
#include
namespace karto
{
/**
* Platform independent pi definitions
*/
const kt_double KT_PI = 3.14159265358979323846; // The value of PI
const kt_double KT_2PI = 6.28318530717958647692; // 2 * PI
const kt_double KT_PI_2 = 1.57079632679489661923; // PI / 2
const kt_double KT_PI_180 = 0.01745329251994329577; // PI / 180
const kt_double KT_180_PI = 57.29577951308232087685; // 180 / PI
/**
* Lets define a small number!
*/
const kt_double KT_TOLERANCE = 1e-06;
/**
* Lets define max value of kt_int32s (int32_t) to use it to mark invalid scans
*/
const kt_int32s INVALID_SCAN = std::numeric_limits::max();
namespace math
{
/**
* Converts degrees into radians
* @param degrees
* @return radian equivalent of degrees
*/
inline kt_double DegreesToRadians(kt_double degrees)
{
return degrees * KT_PI_180;
}
/**
* Converts radians into degrees
* @param radians
* @return degree equivalent of radians
*/
inline kt_double RadiansToDegrees(kt_double radians)
{
return radians * KT_180_PI;
}
/**
* Square function
* @param value
* @return square of value
*/
template
inline T Square(T value)
{
return (value * value);
}
/**
* Round function
* @param value
* @return rounds value to the nearest whole number (as double)
*/
inline kt_double Round(kt_double value)
{
return value >= 0.0 ? floor(value + 0.5) : ceil(value - 0.5);
}
/**
* Binary minimum function
* @param value1
* @param value2
* @return the lesser of value1 and value2
*/
template
inline const T& Minimum(const T& value1, const T& value2)
{
return value1 < value2 ? value1 : value2;
}
/**
* Binary maximum function
* @param value1
* @param value2
* @return the greater of value1 and value2
*/
template
inline const T& Maximum(const T& value1, const T& value2)
{
return value1 > value2 ? value1 : value2;
}
/**
* Clips a number to the specified minimum and maximum values.
* @param n number to be clipped
* @param minValue minimum value
* @param maxValue maximum value
* @return the clipped value
*/
template
inline const T& Clip(const T& n, const T& minValue, const T& maxValue)
{
return Minimum(Maximum(n, minValue), maxValue);
}
/**
* Checks whether two numbers are equal within a certain tolerance.
* @param a
* @param b
* @return true if a and b differ by at most a certain tolerance.
*/
inline kt_bool DoubleEqual(kt_double a, kt_double b)
{
double delta = a - b;
return delta < 0.0 ? delta >= -KT_TOLERANCE : delta <= KT_TOLERANCE;
}
/**
* Checks whether value is in the range [0;maximum)
* @param value
* @param maximum
*/
template
inline kt_bool IsUpTo(const T& value, const T& maximum)
{
return (value >= 0 && value < maximum);
}
/**
* Checks whether value is in the range [0;maximum)
* Specialized version for unsigned int (kt_int32u)
* @param value
* @param maximum
*/
template<>
inline kt_bool IsUpTo(const kt_int32u& value, const kt_int32u& maximum)
{
return (value < maximum);
}
/**
* Checks whether value is in the range [a;b]
* @param value
* @param a
* @param b
*/
template
inline kt_bool InRange(const T& value, const T& a, const T& b)
{
return (value >= a && value <= b);
}
/**
* Normalizes angle to be in the range of [-pi, pi]
* @param angle to be normalized
* @return normalized angle
*/
inline kt_double NormalizeAngle(kt_double angle)
{
while (angle < -KT_PI)
{
if (angle < -KT_2PI)
{
angle += (kt_int32u)(angle / -KT_2PI) * KT_2PI;
}
else
{
angle += KT_2PI;
}
}
while (angle > KT_PI)
{
if (angle > KT_2PI)
{
angle -= (kt_int32u)(angle / KT_2PI) * KT_2PI;
}
else
{
angle -= KT_2PI;
}
}
assert(math::InRange(angle, -KT_PI, KT_PI));
return angle;
}
/**
* Returns an equivalent angle to the first parameter such that the difference
* when the second parameter is subtracted from this new value is an angle
* in the normalized range of [-pi, pi], i.e. abs(minuend - subtrahend) <= pi.
* @param minuend
* @param subtrahend
* @return normalized angle
*/
inline kt_double NormalizeAngleDifference(kt_double minuend, kt_double subtrahend)
{
while (minuend - subtrahend < -KT_PI)
{
minuend += KT_2PI;
}
while (minuend - subtrahend > KT_PI)
{
minuend -= KT_2PI;
}
return minuend;
}
/**
* Align a value to the alignValue.
* The alignValue should be the power of two (2, 4, 8, 16, 32 and so on)
* @param value
* @param alignValue
* @return aligned value
*/
template
inline T AlignValue(size_t value, size_t alignValue = 8)
{
return static_cast ((value + (alignValue - 1)) & ~(alignValue - 1));
}
} // namespace math
} // namespace karto
#endif // OPEN_KARTO_MATH_H