A class which handles angles both as radians and degrees, with automatic conversions between each.
Using the class is easy.
Example usage:
Angle myAngle = new Angle(90, Angle.Type.Degrees); //new angle of 90 degrees double myAngleAsRadians = myAngle.Radians; //returns 1.57 Angle myAngle2 = new Angle(Math.PI, Angle.Type.Radians); //new angle of PI radians double myAngle2AsDegrees = myAngle.Degrees; //returns 180 Angle sum = myAngle + myAngle2; //returns a new angle of 1.5*pi rad bool isSmaller = myAngle < myAngle2; //returns true
Angle class source code
Just add a new class file to your project and copy the text below. You may wish to change the namespace.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace YourNamespace { /// <summary> /// Holds an angle as both radians and degrees, with conversions between each /// </summary> public class Angle { #region constructors /// <summary> /// Blank constructor. Remember to manually set some data to the properties! /// </summary> public Angle() { } /// <summary> /// Construct an angle with either a degree or a radian value /// </summary> /// <param name="input">Angle value</param> /// <param name="angleType">Specify whether input is in radians or degrees</param> public Angle(double input, Type angleType = Angle.Type.Radians) { if (angleType == Type.Degrees) { Degrees = input; } else if (angleType == Type.Radians) { Radians = input; } } /// <summary> /// Quickly construct a common angle /// </summary> /// <param name="preset">Choose angle</param> public Angle(Angle.Preset preset) { if (preset == Angle.Preset.Deg0) { Degrees = 0; } else if (preset == Preset.Deg180) { Degrees = 180; } else if (preset == Preset.Deg360) { Degrees = 360; } else if (preset == Preset.Rad2Pi) { Radians = twoPi; } else if (preset == Preset.RadPi) { Radians = Pi; } else Radians = 0; } #endregion constructors #region properties private double degrees; /// <summary> /// Angle in degrees /// </summary> public double Degrees { get { return degrees; } set { degrees = value; radians = ToRadians(value); updateFixedangles(); } } private double radians; /// <summary> /// Angle in radians between -pi to pi /// </summary> public double Radians { get { return radians; } set { radians = value; degrees = ToDegrees(value); updateFixedangles(); } } private double radians2pi; /// <summary> /// Angle in radians, modified to fall between 0 and 2pi. Read-only. /// </summary> public double Radians2pi { get { return radians2pi; } } private double degrees360; /// <summary> /// Value in degrees between 0 and 360. Read-only. /// </summary> public double Degrees360 { get { return degrees360; } } #endregion properties #region enums public enum Type { Radians, Degrees } /// <summary> /// Presets for quick setup of Angle constructor /// </summary> public enum Preset { Deg0, Deg180, Deg360, RadPi, Rad2Pi } #endregion enums #region constants private const double twoPi = 2 * Math.PI; private const double Pi = Math.PI; #endregion constants #region methods /// <summary> /// Convert an input angle of degrees to radians. Does not affect any properties in this class - set properties instead. /// </summary> /// <param name="val">Input in degrees</param> /// <returns>Value in radians</returns> public static double ToRadians(double val) { return val / (180 / Pi); } /// <summary> /// Convert an input angle of radians into degrees. Does not affect any properties in this class - set properties instead. /// </summary> /// <param name="val">Input in radians</param> /// <returns>Value in degrees</returns> public static double ToDegrees(double val) { return val * (180 / Pi); } /// <summary> /// Fixes an angle to between 0 and 360 or 2pi. /// </summary> /// <param name="val">Input angle</param> /// <param name="type">Specify whether the input angle is radians or degrees</param> /// <returns>The angle, fixed to between 0 and 360 or 0 and 2pi</returns> public static double FixAngle(double val, Type type) { if (type == Type.Radians) { //-2pi to 0 to between 0 and 2pi if (val < 0) { return 2 * Math.PI - (Math.Abs(val) % (2 * Math.PI)); } //over 2pi to between 0 and 2pi else if (val > 2 * Math.PI) { return val % (2 * Math.PI); } //else it's fine, return it back else { return val; } } else if (type == Type.Degrees) { //-360 to 0 to between 0 and 360 if (val < 0) { return 360 - (Math.Abs(val) % 360); } //over 360 to between 0 and 360 else if (val > 360) { return val % 360; } //else it's fine, return it back else { return val; } } else return -1; //something's gone wrong } /// <summary> /// Looks at the radians and degrees properties, and updates their respective fixed angles /// </summary> private void updateFixedangles() { radians2pi = FixAngle(radians, Type.Radians); degrees360 = FixAngle(degrees, Type.Degrees); } /// <summary> /// Copies Radians2pi to Radians, and Degrees360 to Degrees. (I.e. fixes radians to 0<2pi and degrees to 0<360) /// </summary> public void FixAngles() { updateFixedangles(); Radians = Radians2pi; //this also calls Degrees } #endregion methods #region operators /// <summary> /// Returns the sum of two angles /// </summary> /// <param name="a1">First angle</param> /// <param name="a2">Second angle</param> /// <returns>An angle constructed from the radian sum of the input angles</returns> public static Angle operator +(Angle a1, Angle a2) { return new Angle(a1.Radians + a2.Radians, Type.Radians); } /// <summary> /// Returns the difference between two angles /// </summary> /// <param name="a1">First angle</param> /// <param name="a2">Second angle</param> /// <returns>An angle constructed from the value that is the first angle minus the second angle</returns> public static Angle operator -(Angle a1, Angle a2) { return new Angle(a1.Radians - a2.Radians, Type.Radians); } /// <summary> /// Returns the exact division between two angles (i.e. how many times does the second angle fit into the first) /// </summary> /// <param name="a1">Numerator angle</param> /// <param name="a2">Dedominator angle</param> /// <returns>A new angle constructed from the value that is the first angle in radians divided by the second angle in radians</returns> public static Angle operator /(Angle a1, Angle a2) { return new Angle(a1.Radians / a2.Radians, Type.Radians); } public static Angle operator *(Angle a, double d) { return new Angle(a.Radians * d, Type.Radians); } public static Angle operator *(double d, Angle a) { return new Angle(a.Radians * d, Type.Radians); } public static Angle operator /(Angle a, double d) { return new Angle(a.Radians / d, Type.Radians); } public static bool operator <(Angle a1, Angle a2) { if (a1.Radians < a2.Radians) return true; else return false; } public static bool operator >(Angle a1, Angle a2) { if (a1.Radians > a2.Radians) return true; else return false; } public static bool operator <=(Angle a1, Angle a2) { if (a1.Radians <= a2.Radians) return true; else return false; } public static bool operator >=(Angle a1, Angle a2) { if (a1.Radians >= a2.Radians) return true; else return false; } public static implicit operator double(Angle angleobj) { return angleobj.Radians; } public static implicit operator string(Angle a) { return a.ToString(); } #endregion operators #region overrides public override string ToString() { return Radians.ToString() + " radians"; } #endregion overrides } }