Crates.io | aspect360 |
lib.rs | aspect360 |
version | 0.1.8 |
source | src |
created_at | 2024-03-08 17:36:15.382785 |
updated_at | 2024-07-06 11:24:10.352288 |
description | This builds on the Ring360 to calculate aspect matches from target angles with orbs or an array of target aspect/orb pairs. |
homepage | |
repository | https://github.com/neilg63/aspect360 |
max_upload_size | |
id | 1167132 |
size | 15,998 |
This crate builds on the ring360 library to calculate aspects between two angles with a target aspect and orb or an array of aspect/orb pairs.
This crate re-exports ring360, so there is no need to install it separately.
/// Cast two 64-bit floats to Ring360 values
let angle_1 = 74.7.to_360();
let angle_2 = 164.4.to_360();
// calculate the aspect to ±90º within a 2º orb
let result = angle_1.calc_aspect(&angle_2, 90.0, 2.0);
println!("{:.1}º and {:.1}º are {:.1}º apart, {:.1}º from the target aspect of {:.1}º with an orb of {:.1}. Matched: {}",
angle_1.degrees(),
angle_2.degrees(),
result.aspect(),
result.distance(),
result.target(),
result.orb(),
result.matched(),
);
/// Should read: 74.7º and 164.4º are 89.7º apart, -0.3 from the target aspect of 90.0º with an orb of 2.0. Match: true
let lng_1 = 98.202928;
let lng_2 = 249.325729;
let angle_1 = lng_1.to_360();
let angle_2 = lng_2.to_360();
// List target aspect as pairs of target angles and orbs
let targets = [
(0.0, 8.0), // conjunction
(90.0, 5.0), // square
(120.0, 3.0), // trine
(180.0, 4.0) // opposition
].to_aspect_orbs(); // cast the tuple pairs to a vector of AspectOrb structs
let aspect_match_opt = angle_1.find_aspect(&angle_2, &targets);
if let Some(aspect_match) = aspect_match_opt {
println!(
"{:.6}º and {:.6}º have an an aspect match of {:.0}º within {:.6}º",
angle_1,
angle_2,
aspect_match.target(),
aspect_match.distance(),
);
// Should read: 98.202928º and 249.325729º have an an aspect match of 150º within 1.122801º
}
In practice, where aspect definitions cannot overlap, the find_aspect() method will be more efficient as it will return the first matched AspectOrb object. However, when definitions overlap (e.g. a sextile is only around 8.57º away from septile), the first match may not be the best match as the example below illustrates.
let lng_1 = 192.928202;
let lng_2 = 249.325729;
let angle_1 = lng_1.to_360();
let angle_2 = lng_2.to_360();
let targets = [
(30.0, 5.0), // semisextile
(45.0, 8.0), // semisquare
(360.0 / 7.0, 9.0), // septile 360/7 = approx. 51.428571
(60.0, 8.0), // sextile
(90.0, 8.0), // square
(120.0, 8.0), // trine
(150.0, 10.0) // quincunx
].to_aspect_orbs(); // cast to a vector of AspectOrb structs
let aspect_matches = angle_1.find_aspects(&angle_2, &targets);
println!("{} aspects have been matched within the specified ranges", aspect_matches.len());
// yields a vector with 2 matched AspectResults
// Two aspects are matched.
let first_match = angle_1.find_aspect(&angle_2, &targets);
// yields the first matched aspect even if it's not best aspect. In this case a septile with a wide orb of 9.0
println!("The first match is {}º from the target aspect of {}º", first_match.unwrap().divergence(), first_match.unwrap().target());
// prints: The first match is 4.968955571428566º from the target aspect of 51.42857142857143º
// However, the best match is sextile and not septile, which would have been matched first
let best_aspect_match = angle_1.find_best_aspect(&angle_2, &targets);
// Yields a sextile
println!("The best match is {}º from the target aspect of {}º", best_aspect_match.unwrap().divergence(), best_aspect_match.unwrap().target());
// prints: The best match is 3.6024730000000034º from the target aspect of 60º
A simple tuple struct with the target aspect and an orb, both 64-bit floats. Any array or vector of tuple pairs with f64 values representing target angles and orbs can be converted to AspectOrb objects via to_aspect_orbs()
.
This trait is implemented only for Ring360, but any 64-bit float can be cast to a Ring360 via the .to_360() extension method and variant methods ending in _f64 accept normal f64 values as comparison angles, which will be normalised within the 0º to º360 range.
Version 0.1.4 introduced two new methods find_aspects() and find_best_aspect() deal with situations where aspect definitions (AspectOrb) may overlap.
Version 0.1.7 adds a new trait ToAspectOrb
witb a to_aspect_orbs
method to convert an array of simple (f64, f64) tuples into a vector of AspectOrb() structs for use with find_aspect()
, find_best_aspect()
and find_aspects()
. This reduces boilerplate code.