mod predicates;
mod shapes;
pub use predicates::{ccw, point_in_polygon, point_in_rings, segments_intersect, signed_ring_area};
pub use shapes::{Arc, Circle, LineSegment, normalize_angle};
use crate::{EPSILON, Point};
#[must_use]
pub fn point_is_on_board(point: Point, board_size: f64) -> bool {
(0.0..=board_size).contains(&point.x) && (0.0..=board_size).contains(&point.y)
}
#[must_use]
pub fn approx_equal(a: f64, b: f64) -> bool {
(a - b).abs() < EPSILON
}
#[must_use]
pub fn truncate_coord(value: f64, decimals: usize) -> String {
let value = if value.to_bits() == (-0.0_f64).to_bits() {
0.0
} else {
value
};
format!("{value:.decimals$}")
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::{approx_equal, point_is_on_board, truncate_coord};
use crate::{EPSILON, Point};
const BOARD: f64 = 18.0;
#[test]
fn the_board_rectangle_is_closed() {
for point in [(0.0, 0.0), (BOARD, BOARD), (0.0, BOARD), (9.0, 9.0)] {
assert!(point_is_on_board(Point::new(point.0, point.1), BOARD));
}
for point in [(-1e-300, 9.0), (9.0, BOARD + 1e-9), (1e300, 9.0)] {
assert!(!point_is_on_board(Point::new(point.0, point.1), BOARD));
}
}
#[test]
fn a_coordinate_that_is_not_a_number_is_not_on_the_board() {
for coordinate in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
assert!(!point_is_on_board(Point::new(coordinate, 9.0), BOARD));
assert!(!point_is_on_board(Point::new(9.0, coordinate), BOARD));
}
}
#[test]
fn a_board_that_is_not_a_number_holds_no_positions() {
assert!(!point_is_on_board(Point::new(9.0, 9.0), f64::NAN));
assert!(!point_is_on_board(Point::new(0.0, 0.0), f64::NAN));
}
#[test]
fn approx_equal_is_a_magnitude_test() {
assert!(approx_equal(1.0, 1.0 + EPSILON / 2.0));
assert!(!approx_equal(1.0, 1.0 + EPSILON * 2.0));
assert!(approx_equal(0.0, 0.0));
}
#[test]
fn truncate_coord_fixes_the_decimals() {
assert_eq!(truncate_coord(1.0, 8), "1.00000000");
assert_eq!(truncate_coord(1.234_567_891_5, 8), "1.23456789");
assert_eq!(truncate_coord(-3.5, 2), "-3.50");
assert_eq!(truncate_coord(12.0, 0), "12");
}
#[test]
fn truncate_coord_normalizes_negative_zero() {
assert_eq!(truncate_coord(-0.0, 8), "0.00000000");
assert_eq!(truncate_coord(0.0, 8), "0.00000000");
assert_eq!(truncate_coord(-0.001, 2), "-0.00");
}
}