demo-tourbillon.rs

2.4 kB · rust · 69 lines

1use mrlycore::errors::Result;2use mrlyfig::board::Board;3use mrlyfig::ink::Ramp;4use mrlyfig::{field, ink, save};5use mrlynum::tourbillon;67const TOP: usize = 55;8const RASTER: usize = 1024;9const LAYERS: usize = 28;10const CENTRE: f64 = 14.0 / 28.0;11const SEED: u32 = 1;12const MARGIN: f64 = 0.08;13const CURVE: f64 = 1.45;1415fn shrink(source: &[f32], size: usize, side: usize) -> Vec<f64> {16    let step = size as f64 / side as f64;17    let span = |k: usize| (k as f64 * step, (k + 1) as f64 * step);18    let mut out = Vec::with_capacity(side * side);19    for row in 0..side {20        let (top, bottom) = span(row);21        for column in 0..side {22            let (left, right) = span(column);23            let mut total = 0.0;24            for y in top as usize..(bottom.ceil() as usize).min(size) {25                let height = bottom.min(y as f64 + 1.0) - top.max(y as f64);26                for x in left as usize..(right.ceil() as usize).min(size) {27                    let width = right.min(x as f64 + 1.0) - left.max(x as f64);28                    let value = source[y * size + x];29                    if !value.is_nan() {30                        total += height * width * f64::from(value);31                    }32                }33            }34            out.push(total / (step * step));35        }36    }37    out38}3940fn main() -> Result<()> {41    let list = tourbillon::layers(TOP, "golden", 0.0, "odd", "plain", SEED)?;42    assert_eq!(list.len(), LAYERS);43    assert_eq!(list[0].scale, 1);44    assert_eq!(list[LAYERS - 1].scale, TOP);4546    let spun = tourbillon::field(47        TOP, RASTER, "golden", 0.0, "odd", "plain", "cells", "mean", SEED,48    )?;49    assert_eq!(spun.len(), RASTER * RASTER);50    let read = tourbillon::stats(51        &spun, RASTER, TOP, "golden", 0.0, "odd", "plain", "mean", SEED,52    )?;53    assert_eq!(read.layers, LAYERS);54    assert_eq!(read.centre, CENTRE);5556    let mut board = Board::square();57    let frame = board.frame(MARGIN);58    let side = frame.w.round() as usize;59    let disc: Vec<f64> = shrink(&spun, RASTER, side)60        .iter()61        .map(|value| (value / read.centre).clamp(0.0, 1.0).powf(CURVE))62        .collect();63    assert_eq!(disc.len(), side * side);6465    let ramp = Ramp::new(vec![ink::ground(), ink::indigo(), ink::pink()]);66    field::draw_range(&mut board, frame, side, side, &disc, (0.0, 1.0), &ramp);67    save("demo-tourbillon", &board)?;68    Ok(())69}