#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2015 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library 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
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_GEOMETRY_MATH_H
#error This file must be included through Math.h
#endif
namespace Nuclex { namespace Geometry {
// ------------------------------------------------------------------------------------------- //
/// Math routines for geometry classes based on double precision floats
template <>
class Math {
/// The PI constant
public: NUCLEX_GEOMETRY_API static constexpr double Pi = (
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253
);
/// Two times PI, useful for some operations
public: NUCLEX_GEOMETRY_API static constexpr double Perigon = (
6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696507
);
/// Calculates the square root of the specified value
/// Value of which the square root is calculated
/// The square root of the specified number
public: NUCLEX_GEOMETRY_API static double SquareRoot(double value) {
return std::sqrt(value);
}
/// Returns a random number from 0.0 to the specified maximum
/// The random number generator that will be used
/// Upper limit for the random number (exclusive)
/// A random number from 0.0 to the specified maximum
public: template static double Random(
TRandomNumberEngine &random, double max
) {
std::uniform_real_distribution distribution(0.0, max);
return distribution(random);
}
/// Returns a random number in the specified range
/// The random number generator that will be used
/// Minimum possible value of the random number
/// Upper limit for the random number (exclusive)
/// A random number within the specified range
public: template static double Random(
TRandomNumberEngine &random, double min, double max
) {
std::uniform_real_distribution distribution(min, max);
return distribution(random);
}
/// Calculates the sine of the specified angle
/// Angle for which the sine will be calculated
/// The sine of the specified angle
public: NUCLEX_GEOMETRY_API static double Sine(double angleInRadians) {
return std::sin(angleInRadians);
}
/// Calculates the cosine of the specified angle
/// Angle for which the cosine will be calculated
/// The cosine of the specified angle
public: NUCLEX_GEOMETRY_API static double Cosine(double angleInRadians) {
return std::cos(angleInRadians);
}
/// Calculates the angle of the specified sine value
/// Sine value of which the angle will be calculated
/// The angle of the specified sine value in radians
public: NUCLEX_GEOMETRY_API static double ArcSine(double sineValue) {
return std::asin(sineValue);
}
/// Calculates the angle of the specified cosine value
/// Cosine value for which the angle will be calculated
/// The angle of the specified cosine value in radians
public: NUCLEX_GEOMETRY_API static double ArcCosine(double cosineValue) {
return std::acos(cosineValue);
}
/// Calculates the angle of the tangent specified by a direction
/// X coordinate of the direction
/// Y coordinate of the direction
/// The angle of the tangent specified through the direction
public: NUCLEX_GEOMETRY_API static double ArcTangent(double x, double y) {
return std::atan2(y, x);
}
/// Returns the absolute value of the specified value
/// Value of which the absolute value will be returned
/// The absolute value of the provided value
public: NUCLEX_GEOMETRY_API static double Abs(double value) {
return std::fabs(value);
}
/// Calculates to the power of
/// Value that will be multiplied
/// To which power the value will be multiplied
/// to the power of
public: NUCLEX_GEOMETRY_API static double Power(double value, double power) {
return std::pow(value, power);
}
/// Returns the smaller of two values
/// First of the two values
/// Second of the two values
/// The smaller of the two provided values
public: NUCLEX_GEOMETRY_API static double Min(double first, double second) {
return std::min(first, second);
}
/// Returns the smallest of three values
/// First of the three values
/// Second of the three values
/// Third of the three values
/// The smallest of the three provided values
public: NUCLEX_GEOMETRY_API static double Min(
double first, double second, double third
) {
return std::min(std::min(first, second), third);
}
/// Returns the larger of two values
/// First of the two values
/// Second of the two values
/// The larger of the two provided values
public: NUCLEX_GEOMETRY_API static double Max(double first, double second) {
return std::max(first, second);
}
/// Returns the largest of three values
/// First of the three values
/// Second of the three values
/// Third of the three values
/// The largest of the three provided values
public: NUCLEX_GEOMETRY_API static double Max(
double first, double second, double third
) {
return std::max(std::max(first, second), third);
}
/// Determines the extremes of two values
/// First of the values whose extremes will be found
/// Second of the values whose extremes will be found
///
/// A pair containing the smaller and the larger value in that order
///
public: NUCLEX_GEOMETRY_API static std::pair Extremes(
double first, double second
) {
if(first < second) {
return std::pair(first, second);
} else {
return std::pair(second, first);
}
}
/// Determines the extremes of three values
/// First of the values whose extremes will be found
/// Second of the values whose extremes will be found
/// Third of the values whose extremes will be found
///
/// A pair containing the smallest and the largest value of the three inputs
///
public: NUCLEX_GEOMETRY_API static std::pair Extremes(
double first, double second, double third
) {
if(first < second) {
if(second < third) { // first < second < third
return std::make_pair(first, third);
} else if(first < third) { // first < third < second
return std::make_pair(first, second);
} else { // third < first < second
return std::make_pair(third, second);
}
} else {
if(first < third) { // second < first < third
return std::make_pair(second, third);
} else if(second < third) { // second < third < first
return std::make_pair(second, first);
} else { // third < second < first
return std::make_pair(third, first);
}
}
}
/// Unwinds a value in a circular (repeating) value range
/// Value that will be unwound
/// Lower limit of the circular value range
/// Upper limit of the circular value range
/// The unwound value
public: NUCLEX_GEOMETRY_API static double Unwind(
double value, double min, double max
) {
double range = (max - min);
double floor = std::floor((value - min) / range);
return value - (floor * range);
}
/// Limits the value to the specified range
/// Value that will be limited
/// Minimum the value cannot go under
/// Maximum the value cannot go above
/// The value limited to the specified range
public: NUCLEX_GEOMETRY_API static double Clamp(
double value, double min, double max
) {
if(value < min) {
return min;
}
if(value > max) {
return max;
}
return value;
}
/// Linearly interpolates between two values
/// Value at the left interpolation point
/// Value at the right interpolation point
/// Time (0.0 .. 1.0) for which to interpolate the value
/// The interpolated value at the specified time
public: NUCLEX_GEOMETRY_API static double Lerp(
double left, double right, double t
) {
return (right - left) * t + left;
}
/// Calculates the time of a linearly interpolated value
/// Value at the left interpolation point
/// Value at the right interpolation point
/// Value that resulted from the interpolation
/// Time at which the value is placed in the interpolation range
public: NUCLEX_GEOMETRY_API static double Unlerp(
double left, double right, double value
) {
return (value - left) / (right - left);
}
/// Checks whether the specified value is invalid (not a number)
/// Value that will be checked
/// True if the specified value is not a number
public: NUCLEX_GEOMETRY_API static bool IsNan(double value) {
return std::isnan(value);
}
};
// ------------------------------------------------------------------------------------------- //
}} // namespace Nuclex::Geometry