cavalier_contours 0.7.0

2D polyline/shape library for offsetting, combining, etc.
Documentation
mod test_utils;

use cavalier_contours::{polyline::Polyline, shape_algorithms::Shape};
use test_utils::{PlineProperties, create_property_set};

use crate::test_utils::property_sets_match;

fn run_shape_offset_tests<I>(input: I, offset: f64, expected_properties_set: &[PlineProperties])
where
    I: IntoIterator<Item = Polyline>,
{
    let s = Shape::from_plines(input);
    let result = s.parallel_offset(offset, Default::default());
    let plines = result
        .ccw_plines
        .iter()
        .chain(result.cw_plines.iter())
        .map(|p| &p.polyline);
    let result_properties = create_property_set(plines, false);

    assert!(
        property_sets_match(&result_properties, expected_properties_set),
        "result property sets do not match"
    )
}

macro_rules! declare_offset_tests {
    ($($name:ident { $($value:expr => $expected:expr),+ $(,)? })*) => {
        $(
            #[test]
            fn $name() {
                $(
                    run_shape_offset_tests($value.0, $value.1, &$expected);
                )+
            }
        )+
    };
}
mod test_simple {
    use super::*;
    use cavalier_contours::pline_closed_userdata;

    declare_offset_tests!(
        empty_returns_empty {
          (Vec::<Polyline>::new(), 5.0) => []
        }
        set_of_empty_returns_empty {
          ([Polyline::<f64>::new_closed(), Polyline::new_closed()], 5.0) => []
        }
        rectangle_inside_shape {
            ([pline_closed_userdata![[4], (100.0, 100.0, -0.5), (80.0, 90.0, 0.374794619217547), (210.0, 0.0, 0.0), (230.0, 0.0, 1.0), (320.0, 0.0, -0.5), (280.0, 0.0, 0.5), (390.0, 210.0, 0.0), (280.0, 120.0, 0.5)],
              pline_closed_userdata![[117], (150.0, 50.0, 0.0), (150.0, 100.0, 0.0), (200.0, 100.0, 0.0), (200.0, 50.0, 0.0)]], 3.0) =>
             [PlineProperties::new(12, 40977.79061358948, 998.5536075336107, 84.32384698504309, -41.99999999999997, 401.41586988912127, 205.22199935960901, vec![4]),
              PlineProperties::new(8, -3128.274333882308, 218.84955592153878, 147.0, 47.0, 203.0, 103.0, vec![117])]
        }
    );
}

mod test_specific {
    use super::*;
    use cavalier_contours::pline_closed_userdata;

    declare_offset_tests!(
        case1 {
            ([pline_closed_userdata![[4], (100.0, 100.0, -0.5), (80.0, 90.0, 0.374794619217547), (210.0, 0.0, 0.0), (230.0, 0.0, 1.0), (320.0, 0.0, -0.5), (280.0, 0.0, 0.5), (390.0, 210.0, 0.0), (280.0, 120.0, 0.5)],
              pline_closed_userdata![[117], (150.0, 50.0, 0.0), (146.32758944101474, 104.13867601941358, 0.0), (200.0, 100.0, 0.0), (200.0, 50.0, 0.0)]], 17.0) =>
             [PlineProperties::new(22, 20848.93377998434, 1149.2701898185926, 102.79564651409214, -28.000000000000004, 387.41586988912127, 181.8843855860552, vec![4, 117])]
        }
        case2 {
            ([pline_closed_userdata![[4], (160.655879768138, 148.75471430537402, -0.5), (80.0, 90.0, 0.374794619217547), (210.0, 0.0, 0.0), (230.0, 0.0, 1.0), (320.0, 0.0, -0.5), (280.0, 0.0, 0.5), (390.0, 210.0, 0.0), (280.0, 120.0, 0.5)],
              pline_closed_userdata![[117], (150.0, 50.0, 0.0), (192.62381977774953, 130.82800839110848, 0.0), (200.0, 100.0, 0.0), (200.0, 50.0, 0.0)]], 17.0) =>
             [PlineProperties::new(20, 20135.256681247833, 1053.2414865948808, 105.64684517241575, -28.000000000000004, 387.41586988912127, 181.8843855860552, vec![4, 117]),
              PlineProperties::new(4, 2.091291658768, 9.557331573939933, 176.64810774674345, 136.97815392110508, 178.9335673169721, 140.906549335123, vec![4, 117])]
        }
        // Test case for issue fixed: https://github.com/jbuckmccready/cavalier_contours/issues/66
        case3 {
            ([
                pline_closed_userdata![[], (511.25220437557994, 328.84948025435654, 0.0), (561.2119896118824, 328.84948025435654, 0.0), (561.2119896118824, 363.8703101013724, 0.0), (511.25220437557994, 363.8703101013724, 0.0)],
                pline_closed_userdata![[], (540.0335350561843, 343.6169427142472, -0.2382488851276809), (537.4421349268171, 345.12517844750175, -0.009889532389405053), (537.3232102367999, 345.3220639672001, 0.0), (535.3578079577983, 348.7262405716385, 0.0), (535.32462892643, 348.7834560296831, -0.011646639385887355), (535.2271073347746, 348.9562631479, -0.25910007835503845), (535.2805330874, 352.1843242602999, 0.0), (537.0000084336, 355.1625429223, 0.0), (543.6691202685, 343.6113023833, 0.0), (540.2257285374734, 343.6113053474554, 0.0), (540.16153451323, 343.6120105305873, 0.0)],
                pline_closed_userdata![[], (535.4816659760771, 346.2417647657877, -0.23822264248219718), (535.4722003945319, 343.2448614622984, -0.009951542143624231), (535.3601905012999, 343.0416179385001, 0.0), (533.3951100416035, 339.6379987413748, 0.0), (533.3623248097243, 339.5809609408148, -0.011710653864622287), (533.2619655102294, 339.4110081813505, -0.11747560444569163), (532.1675755117166, 338.3268271911126, -0.13757287100703242), (530.4835288827071, 337.8423335382348, 0.0), (530.438959126, 337.8420348466, 0.0), (527.0000084336, 337.8420348466, 0.0), (533.6691202683, 349.3932753857, 0.0), (535.3908302312102, 346.4111802353502, 0.0), (535.4223097645596, 346.3552449203639, 0.0)]
            ], 0.8) =>
            [PlineProperties::new(4, 1616.2241538207163, 163.56123016663673, 512.0522043755799, 329.64948025435655, 560.4119896118824, 363.0703101013724, vec![]),
             PlineProperties::new(28, -148.47469897242397, 61.018056828113345, 526.2000084335999, 337.04203484659996, 544.4691202685001, 355.96254292230003, vec![])]
        }
    );
}