Ring360: Modular Arithmetic around a 360º circle
This crate provides a simple wrapper struct for 64-bit floats representing degrees around a 2D circle. The type lets you add and subtract with the + and - operators as well as calculate the shortest angles between two degrees. Multiplication and division only work with primitive float-64 values via the multiply() and divide() methods.
A Ring360 type is a simple tuple struct encapsulating the raw the f64 value with methods to expose its degrees(), rotations() or raw value(), e.g. Ring360(400.0) would have a raw value of 400.0 but 40º as a degree and 1 rotation.
As this data type works around a 360º circle, negative raw values yield positive degrees in the opposite direction, e.g. -60 is 300º . Longitudes around the Earth's circumference are customarily expressed as ±180º. In this case, longitudes between 0º and 180º are the same but between 180º and 360º, they descend from -180º to º0. This means -120º in the ±180 system is 240º in the 360º system. To this end, the crate has methods to convert from and to the GIS ±180 system, i.e. value_f64.to_360_gis() or Ring360_from_gis(lng180: f64). Please note that some Geographic Information Systems such QGIS use the 360º system and thus work with the standard to_360() and degrees() methods.
Add and subtract degree values
/// Add and/or subtract degrees on a circle
/// The degree value represents the longitude, while the intrinsic f64 value
/// represents the angle travelled around the circumference
let longitude_1 = 74.7.to_360; // or Ring360(74.7);
let longitude_2 = 291.4.to_360;
let longitude_3 = 126.1.to_360;
let result_1 = longitude_1 + longitude_2 + longitude_3;
println!;
/// Should read: Degrees: 132.2º, intrinsic value is 492.2, rotations: 1
let result_2 = longitude_1 - longitude_2 + longitude_3;
println!;
/// Should read: Degree value: 269.4º
Use ±180 GIS system, -180º to 180º
/// Declare two degrees on the GIS scale
let gis_lng_1 = 143.32;
let gis_lng_2 = -111.4;
/// Shift ±180 degrees to a 0º to 360º scale
let lng_360_1 = gis_lng_1.to_360_gis; // or Ring360::rom_gis(74.7);
let lng_360_2 = gis_lng_2.to_360_gis;
let angle_3 = lng_360_1.angle;
println!;
/// The longitudinal distance between 143.32 and -111.4 is 105.28
Convert from and to f64
let value_1 = 74.7;
let value_2 = 291.4;
let longitude_1 = value_1.to_360;
let longitude_2 = value_2.to_360;
let result_1_f64 = .degrees;
println!;
Multiplication and Division
These are not implemented directly for degrees as Ring360 values, but only with primitive f64 values via the multiply() and divide() methods.
let value_1 = 74.7;
let factor = 4.0;
let result_1 = value_1.to_360.multiply;
println!;
let result_2 = value_1.to_360.divide;
println!;
Angular Distance
The angle() and angle_f64() methods calculate the shortest angle in degrees between two longitudes in a circle. Negative values indicate an anticlockwise offset from A to B, e.g. from 340º to 320º would be negative, while 350º to 10º would be positive.
let value_1 = 297.4;
let longitude_1 = value_1.to_360;
let value_2: f64 = 36.2;
let longitude_2 = value_2.to_360;
let result_1 = value_1.angle;
let result_2 = value_1.angle_f64;
println!;
Calculate sine, cosine and tangent directly
let value_1 = 45.0;
let degree_1 = value_1.to_360;
println!;
// Should print: The sine of 45º is 0.707106781187
let value_2 = 60.0;
let degree_2 = value_2.to_360;
println!;
// Should print: The cosine of 60º is 0.5
Instance Methods
- degrees()-> f64 Degree value from 0º to 360º.
- to_f64() -> f64 Alias for degrees() and the default display value
- to_gis() -> f64 Convert the internal 0-360º scale to the -180º to +180º GIS scale
- rotations() -> i64 Number of rotations required to reach the current raw value, e.g. 730.0 would require 2 rotations with a degree value of 10.0.
- progress() -> f64 the instrinsic value expressed as decimal fractions of progress around a circle, i.e. 180º translates to 0.5 and 450º to 1.25
- value() -> f64 Raw f64 value
- as_tuple() -> (f64, i64) Return a tuple with degrees as f64 and rotations as i64
- multiply(multiple: f64) -> Self Multiply a Ring360 value by a normal f64 value
- divide(divisor: f64) -> Self Divide a Ring360 by a normal f64 value
- angle_f64(other_value: f64) -> f64 Calculate the shortest distance in degrees between a Ring360 value and a 64-bit float representing a degree. A positive value represents clockwise movement between the first and second longitude
- angle(other_value: Ring360) -> f64 Angular distance between to Ring360 values
- to_radians() -> f64 convert to radians for interoperability
- sin() -> f64 sine (with implicit radian conversion, e.g. 30.to_360().sin() yields 0.5)
- cos() -> f64 cosine
- tan() -> f64 tangent
- asin() -> f64 inverse sine
- acos() -> f64 inverse cosine
- atan() -> f64 inverse tangent
Static methods
- half_turn() -> f64 Half of the 360º base, i.e. 180.0
Constants
- BASE:f64 = 360.0
Traits
ToRing360
This is implemented only for f64 with the following methods:
- to_360(&self) -> Ring360 converts any 64-bit float representing a degree in tne 360º system to Ring360 value;
- to_360_gis(&self) -> Ring360 converts any 64-bit float representing a degree in tne ±180º system and normalises on the 0-360º scale.
- mod_360(&self) -> f64 A convenience method for % 360.0, but treating negative values as positive degrees in reverse, e.g. (-20.0).mod_360 equals 340º
- angle_360(&self, other_value: f64) -> f64: Calculates the shortest angle between two f64 values as degrees around a circle.
Dev Notes
This is crate is in development, but implements all core features.
Version notes
0.2.8
- progress() -> f64 Returns the rotations as decimal progress around a circle
0.2.6
The following methods have been added to Ring360
- to_radians(&self) for interoperability with other maths functions
The core trigonometric methods, sin(), cos(), tan(), asin(), acos() and atan() are calculated from degrees without explicitly converting to radians first:
- .sin() -> f64 calculates sine
- .cos() -> f64 calculates cosine
- .tan() -> f64 calculates tangent
- .asin() -> f64 calculates inverse sine (arcsine, asin)
- .acos() -> f64 calculates inverse cosine (arccoine, acos)
- .atan() -> f64 calculates inverse tangent (arctan, atan)
0.2.5
The following deprecated methods were removed from version 0.2.5:
- degree() => use degrees() instead.
- turns() => use rotations() instead.