#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 floating point values template <> class Math { /// The PI constant public: NUCLEX_GEOMETRY_API static constexpr float Pi = ( 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825f ); /// Two times PI, useful for some operations public: NUCLEX_GEOMETRY_API static constexpr float Perigon = ( 6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069651f ); /// 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 float SquareRoot(float 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 float Random( TRandomNumberEngine &random, float max ) { std::uniform_real_distribution distribution(0.0f, 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 float Random( TRandomNumberEngine &random, float min, float 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 float Sine(float 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 float Cosine(float 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 float ArcSine(float 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 float ArcCosine(float 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 float ArcTangent(float x, float 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 float Abs(float 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 float Power(float value, float 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 float Min(float first, float 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 float Min(float first, float second, float 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 float Max(float first, float 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 float Max(float first, float second, float 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( float first, float 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( float first, float second, float 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 float Unwind(float value, float min, float max) { float range = (max - min); float 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 float Clamp(float value, float min, float 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 float Lerp(float left, float right, float 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 float Unlerp(float left, float right, float 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(float value) { return std::isnan(value); } }; // ------------------------------------------------------------------------------------------- // }} // namespace Nuclex::Geometry