dms-coordinates 1.3.1

Package to handle D°M'S'' coordinates
Documentation
D°M'S"
======

[![Rust](https://github.com/gwbres/dms-coordinates/actions/workflows/rust.yml/badge.svg?branch=main)](https://github.com/gwbres/dms-coordinates/actions/workflows/rust.yml)
[![crates.io](https://docs.rs/dms-coordinates/badge.svg)](https://docs.rs/dms-coordinates/badge.svg)
[![crates.io](https://img.shields.io/crates/d/dms-coordinates.svg)](https://crates.io/crates/dms-coordinates)   
[![crates.io](https://img.shields.io/crates/v/dms-coordinates.svg)](https://crates.io/crates/dms-coordinates)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](https://github.com/gwbres/dms-coordinates/blob/main/LICENSE-APACHE)
[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/gwbres/dms-coordinates/blob/main/LICENSE-MIT) 

`D°M'S"` represents an angle in sexagesimal format, where
* D° for degrees, positive integer, 0 <= D° < 360° in case
no cardinal associated to it
* M' for minutes, 0 <= M' < 60, 60'=1D°
* S" for fractionnal seconds, double precision, 0 <= S" < 60, 60"=1'
* Optionnal Cardinal point, among "N", "S", "E", "W"

```rust
let dms = dms_coordinates::DMS::new(40, 43, 50.196, None);
assert_eq!(dms.degrees, 40);
assert_eq!(dms.minutes, 43);
assert_float_relative_eq!(dms.seconds, 50.196, 1E-6); 
assert_eq!(dms.cardinal, None);
```

A couple other methods are available

```rust
// Total amount of S" (unit basis) in D°M'S"
let dms = DMS::new(0, 10, 55.0);
total = dms.total_seconds(); 
assert_eq!(total, 10*60+55);

// Build D°M'S" from total amount of seconds
let d = DMS::from_seconds(total);
assert_eq!(dms, d);
```

D°M'S" supports overflow and wrapps internal so D°, M' and S"
remain within predefined ranges.

For instance, overflows are allowed when building a D°M'S":
```rust
let dms = DMS::new(10, 61, 0.0);
assert_eq!(dms.degrees, 11); // 61' = 1°+1'
assert_eq!(dms.minutes,  1);
```

It is possible to cast a D°M'S" angle into
* a `f64` number: you get the total amount of seconds, with fractionnal and double precision
* a `f32` number: you get the total amount of seconds, with fractionnal part and precision loss (6 digits)
* `u64`, `u32`, `u16`, `u8` : you get the total amount of seconds, but fractionnal part is lost

```rust
let dms = DMS::new(0, 1, 30.33);
let secs : f64 = dms.into();
assert_eq!(secs, 60.0+30.33);

let secs : u32 = dms.into();
assert_eq!(secs, 1*60+30); // fractionnal part is lost
```

## Arithmetics

D°M'S" supports all basic mathematical operations, for convenient
operations performed in navigation (like course and angle calculations).

It is possible to perform (*) (/) (+) and (-) 

* between two D°M'S" angles
* between one D°M'S" angle and a number

### Operations with another angle

D°M'S" (+) D°M'S"
```rust
let d0 = DMS::new(0, 10, 55.0);
let d1 = DMS::new(0, 20, 5.0);
let d = d0 + d1;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 31);
assert_eq!(d.seconds, 0.0);
```

D°M'S" (-) D°M'S"
```rust
let d0 = DMS::new(0, 20, 55.0);
let d1 = DMS::new(0, 3, 5.0);
let d = d0 - d1;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 17);
assert_eq!(d.seconds, 50.0);
```

* D°M'S" (*) D°M'S" is not feasible
* D°M'S" (/) D°M'S" is not feasible

I doubt these have a practical use

### Operations with a number

D°M'S" (+) ɑ: we consider ɑ in seconds

```rust
// add 5"
let d = DMS::new(0, 20, 55.0) + 5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 21);
assert_eq!(d.seconds, 0.0);

// add 10" with fractionnal part
let d = DMS::new(0, 59, 50.0) + 10.3;
assert_eq!(d.degrees, 1);
assert_eq!(d.minutes, 0);
assert_eq!(d.seconds, 0.3);
```

D°M'S" (-) ɑ: we consider ɑ in seconds

```rust
// substract 5"
let d = DMS::new(0, 20, 55.0) + 5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 20);
assert_eq!(d.seconds, 50.0);

// substract 10" with fractionnal part
let d = DMS::new(0, 59, 9.0) - 10.3;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 58);
assert_eq!(d.seconds, 59.7);
```

D°M'S" (*) ɑ: we consider ɑ as an integral ratio 

```rust
// multiply by factor of 5
let d = DMS::new(0, 1, 10.0) * 5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 5);
assert_eq!(d.seconds, 50.0);

// multiply by factor of 5.5
let d = DMS::new(0, 1, 10.0) * 5.5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 5);
assert_eq!(d.seconds, 55.0);

// divide by 2
let d = DMS::new(0, 1, 10.0) *0.5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 0);
assert_eq!(d.seconds, 5.0);
```

D°M'S" (/) ɑ: we consider ɑ as an integral ratio 

```rust
// divide by factor of 5
let d = DMS::new(0, 1, 10.0) / 5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 0);
assert_eq!(d.seconds, 2.0);

// divide by fractionnal factor 
let d = DMS::new(0, 1, 10.0) / 5.5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 1.8181);

// multiply by 2 
let d = DMS::new(0, 1, 10.0) /0.5;
assert_eq!(d.degrees, 0);
assert_eq!(d.minutes, 2);
assert_eq!(d.seconds, 20.0);
```