]> git.tdb.fi Git - libs/math.git/blobdiff - source/geometry/angle.h
Beginnings of a geometry library
[libs/math.git] / source / geometry / angle.h
diff --git a/source/geometry/angle.h b/source/geometry/angle.h
new file mode 100644 (file)
index 0000000..edd7521
--- /dev/null
@@ -0,0 +1,221 @@
+#ifndef MSP_GEOMETRY_ANGLE_H_
+#define MSP_GEOMETRY_ANGLE_H_
+
+#include <cmath>
+
+namespace Msp {
+namespace Geometry {
+
+/**
+A planar angle.  Creating an Angle from a raw value or extracting it requires
+specifying whether degrees or radians are used.  This eliminates a common
+source of errors.
+*/
+template<typename T>
+class Angle
+{
+private:
+       T value;
+
+       explicit Angle(T);
+public:
+       template<typename U>
+       Angle(const Angle<U> &);
+
+       static Angle from_degrees(T);
+       static Angle from_radians(T);
+
+       static Angle right();
+       static Angle quarter_circle();
+       static Angle straight();
+       static Angle half_circle();
+       static Angle full_circle();
+
+       T degrees() const;
+       T radians() const;
+
+       Angle &operator+=(const Angle &);
+       Angle &operator-=(const Angle &);
+       Angle &operator*=(T);
+       Angle &operator/=(T);
+};
+
+template<typename T>
+inline Angle<T>::Angle(T v):
+       value(v)
+{ }
+
+template<typename T>
+template<typename U>
+inline Angle<T>::Angle(const Angle<U> &other):
+       value(other.value)
+{ }
+
+template<typename T>
+inline Angle<T> Angle<T>::from_degrees(T d)
+{
+       return Angle<T>(d*M_PI/180);
+}
+
+template<typename T>
+inline Angle<T> Angle<T>::from_radians(T r)
+{
+       return Angle<T>(r);
+}
+
+template<typename T>
+inline Angle<T> Angle<T>::right()
+{
+       return from_radians(M_PI/2);
+}
+
+template<typename T>
+inline Angle<T> Angle<T>::quarter_circle()
+{
+       return right();
+}
+
+template<typename T>
+inline Angle<T> Angle<T>::straight()
+{
+       return from_radians(M_PI);
+}
+
+template<typename T>
+inline Angle<T> Angle<T>::half_circle()
+{
+       return straight();
+}
+
+template<typename T>
+inline Angle<T> Angle<T>::full_circle()
+{
+       return from_radians(M_PI*2);
+}
+
+template<typename T>
+inline T Angle<T>::degrees() const
+{
+       return value*180/M_PI;
+}
+
+template<typename T>
+inline T Angle<T>::radians() const
+{
+       return value;
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::operator+=(const Angle &a)
+{
+       value += a.value;
+       return *this;
+}
+
+template<typename T>
+inline Angle<T> operator+(const Angle<T> &a1, const Angle<T> &a2)
+{
+       Angle<T> r(a1);
+       return r += a2;
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::operator-=(const Angle &a)
+{
+       value -= a.value;
+       return *this;
+}
+
+template<typename T>
+inline Angle<T> operator-(const Angle<T> &a1, const Angle<T> &a2)
+{
+       Angle<T> r(a1);
+       return r -= a2;
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::operator*=(T s)
+{
+       value *= s;
+       return *this;
+}
+
+template<typename T>
+inline Angle<T> operator*(const Angle<T> &a, T s)
+{
+       Angle<T> r(a);
+       return r *= s;
+}
+
+template<typename T>
+inline Angle<T> operator*(T s, const Angle<T> &a)
+{
+       return a*s;
+}
+
+template<typename T>
+inline Angle<T> &Angle<T>::operator/=(T s)
+{
+       value /= s;
+       return *this;
+}
+
+template<typename T>
+inline Angle<T> operator/(const Angle<T> &a, T s)
+{
+       Angle<T> r(a);
+       return r /= s;
+}
+
+template<typename T>
+inline Angle<T> operator/(T s, const Angle<T> &a)
+{
+       return a/s;
+}
+
+template<typename T>
+inline T sin(const Angle<T> &angle)
+{
+       return std::sin(angle.radians());
+}
+
+template<typename T>
+inline Angle<T> asin(T s)
+{
+       return Angle<T>::from_radians(std::asin(s));
+}
+
+template<typename T>
+inline T cos(const Angle<T> &angle)
+{
+       return std::cos(angle.radians());
+}
+
+template<typename T>
+inline Angle<T> acos(T s)
+{
+       return Angle<T>::from_radians(std::acos(s));
+}
+
+template<typename T>
+inline T tan(const Angle<T> &angle)
+{
+       return std::tan(angle.radians());
+}
+
+template<typename T>
+inline Angle<T> atan(T s)
+{
+       return Angle<T>::from_radians(std::atan(s));
+}
+
+template<typename T>
+inline Angle<T> atan2(T y, T x)
+{
+       return Angle<T>::from_radians(std::atan2(y, x));
+}
+
+} // namespace Geometry
+} // namespace Msp
+
+#endif