spirograph.rs
5.3 kB · rust · 173 lines
1use mrlycore::json::parse;2use mrlydemo::spirograph::*;3use mrlydemo::two::two_grid;45fn carpet() -> Vec<u8> {6 let grid = two_grid("495", 3, 1, 0, 3).unwrap();7 assert_eq!((grid.width, grid.height), (3, 3));8 assert_eq!(grid.types.iter().map(|&b| b as usize).sum::<usize>(), 8);9 assert_eq!(grid.types[4], 0);10 grid.types11}1213fn read(pens: &str, track: &str, ring: usize, wheel: usize, laps: usize) -> mrlycore::Json {14 parse(15 &spirograph_read(16 &carpet(),17 3,18 3,19 pens,20 track,21 ring,22 wheel,23 4,24 laps,25 0.9,26 0.0,27 1,28 )29 .unwrap(),30 )31 .unwrap()32}3334#[test]35fn the_carpet_seats_eight_pencils_and_the_law_counts_the_curves() {36 let four = read("fill", "in", 7, 4, 1);37 assert_eq!(four["pencils"], 8);38 assert_eq!(four["fills"], 8);39 assert_eq!(four["distinct"], 2);40 assert_eq!(read("fill", "in", 7, 2, 1)["distinct"], 4);41 assert_eq!(read("fill", "in", 7, 3, 1)["distinct"], 8);42 assert_eq!(read("fill", "line", 7, 3, 2)["distinct"], 2);43 assert_eq!(read("void", "in", 7, 3, 1)["pencils"], 1);44 assert_eq!(read("corners", "in", 7, 3, 1)["corners"], 16);45}4647#[test]48fn the_ring_over_the_wheel_closes_the_circle() {49 let seven = read("fill", "in", 7, 3, 1);50 assert_eq!(51 format!(52 "{} {} {} {}",53 seven["a"], seven["b"], seven["orbits"], seven["fold"]54 ),55 "7 3 3 7"56 );57 assert_eq!(58 format!("{:.6}", seven["turns"].as_f64().unwrap()),59 "4.000000"60 );61 let trace = spirograph(&carpet(), 3, 3, "fill", "in", 7, 3, 4, 1, 0.9, 0.0, 1, 720).unwrap();62 assert_eq!(trace.len(), 8 * 720 * 2);63 assert!((trace[0] - trace[1438]).abs() < 1e-4 && (trace[1] - trace[1439]).abs() < 1e-4);64 let start = spirograph_pose("in", 7, 3, 4, 1, 0.0).unwrap();65 let end = spirograph_pose("in", 7, 3, 4, 1, 1.0).unwrap();66 assert_eq!(67 format!("{:.6} {:.6} {:.6}", start[0], start[1], start[2]),68 "4.000000 0.000000 0.000000"69 );70 assert_eq!(71 format!("{:.6} {:.6}", end[0], end[2] / std::f64::consts::PI),72 "4.000000 -8.000000"73 );74}7576#[test]77fn the_nodes_come_back_only_inside_the_seat_window() {78 assert_eq!(read("fill", "in", 7, 3, 1)["nodes"], 1288);79 assert_eq!(read("fill", "in", 7, 4, 1)["nodes"], 98);80 assert_eq!(read("fill", "out", 5, 8, 1)["nodes"], 150);81 assert!(read("fill", "in", 7, 6, 1)["nodes"].is_null());82 assert!(read("fill", "line", 7, 3, 2)["nodes"].is_null());83 assert!(read("void", "in", 7, 3, 1)["nodes"].is_null());84 let past =85 parse(&spirograph_read(&carpet(), 3, 3, "fill", "in", 7, 4, 4, 1, 1.35, 0.0, 1).unwrap())86 .unwrap();87 assert_eq!(past["distinct"], 2);88 assert!(past["nodes"].is_null());89 let far =90 parse(&spirograph_read(&carpet(), 3, 3, "corners", "in", 7, 3, 4, 1, 1.2, 0.0, 1).unwrap())91 .unwrap();92 assert_eq!(far["corners"], 16);93 assert!(far["nodes"].is_null());94}9596#[test]97fn a_wheel_that_does_not_fit_is_refused() {98 assert!(spirograph_read(&carpet(), 3, 3, "fill", "in", 3, 3, 4, 1, 0.9, 0.0, 1).is_err());99 assert!(spirograph_read(&carpet(), 3, 3, "fill", "polyin", 4, 3, 3, 1, 0.9, 0.0, 1).is_err());100 assert!(spirograph_read(&carpet(), 3, 3, "edges", "in", 7, 3, 4, 1, 0.9, 0.0, 1).is_err());101}102103#[test]104fn the_cover_walls_the_carpet_and_the_winding_checks_it() {105 let side = 256;106 let cover =107 spirograph_cover(&carpet(), 3, 3, "fill", "in", 7, 3, 4, 1, 0.9, 0.0, 1, side).unwrap();108 assert_eq!(cover.side as usize, side);109 assert_eq!(cover.mask.len(), side * side);110 assert_eq!(111 format!(112 "{:.6} {:.6} {:.6} {:.6} {:.6}",113 cover.covered, cover.hole, cover.wall, cover.winding, cover.areas114 ),115 "0.814487 0.140825 0.269255 9.104609 9.103448"116 );117 let disc = &cover.disc;118 assert_eq!(119 format!("{:.6} {:.6} {:.6}", disc[0], disc[2], disc[3]),120 "0.000000 5.800000 2.200000"121 );122 let inside = cover.mask.iter().filter(|&&code| code > 0).count();123 let shape = cover.mask.iter().filter(|&&code| code == 3).count();124 assert_eq!(format!("{:.6}", shape as f64 / inside as f64), "0.814487");125 let d = 0.9 / (1.5_f64).hypot(0.5);126 for (kind, rho, want) in [127 ("in", 2.0, "0.014922 0.500622 0.508005 0.507814"),128 ("out", 4.0, "0.016671 0.819733 0.828554 0.828445"),129 ] {130 let one = spirograph_cover(131 &[1, 0, 0],132 3,133 1,134 "fill",135 kind,136 3,137 1,138 4,139 1,140 0.9,141 0.0,142 1,143 side,144 )145 .unwrap();146 let sign = if kind == "in" { -1.0 } else { 1.0 };147 let form = rho * (rho + sign * d * d) / (rho + d).powi(2);148 assert!((one.areas - form).abs() < 1e-12);149 assert_eq!(150 format!(151 "{:.6} {:.6} {:.6} {:.6}",152 one.covered, one.hole, one.winding, form153 ),154 want155 );156 }157 assert!(spirograph_cover(158 &carpet(),159 3,160 3,161 "fill",162 "line",163 7,164 3,165 4,166 2,167 0.9,168 0.0,169 1,170 side171 )172 .is_err());173}