plottery_lib 0.7.0

Core geometry library of Plottery, a creative coding framework for generative vector graphics and pen plotting.
Documentation
use crate::{Line, V2};

#[derive(Debug, Clone, Copy)]
pub struct SamplePoint {
    pub pos: V2,
    pub value: f32,
}

#[derive(Debug, Clone, Copy)]
pub struct SampleTriangle {
    pub a: SamplePoint,
    pub b: SamplePoint,
    pub c: SamplePoint,
    pub min_value: f32,
    pub max_value: f32,
}

impl SampleTriangle {
    pub fn new(a: SamplePoint, b: SamplePoint, c: SamplePoint) -> Self {
        let min_value = a.value.min(b.value).min(c.value);
        let max_value = a.value.max(b.value).max(c.value);
        Self {
            a,
            b,
            c,
            min_value,
            max_value,
        }
    }

    pub fn get_intersection_line(&self, target_value: f32) -> Option<Line> {
        if target_value < self.min_value || target_value > self.max_value {
            return None;
        }

        let num_above = [self.a, self.b, self.c]
            .iter()
            .fold(0, |acc, point: &SamplePoint| {
                acc + if point.value > target_value { 1 } else { 0 }
            });
        if num_above == 0 || num_above == 3 {
            return None;
        }

        let mut points = Vec::with_capacity(2);
        for i in 0..3 {
            let a = [self.a, self.b, self.c][i];
            let b = [self.a, self.b, self.c][(i + 1) % 3];
            if a.value > target_value && b.value > target_value
                || a.value < target_value && b.value < target_value
            {
                continue;
            }
            let err_a = (target_value - a.value).abs();
            let err_b = (target_value - b.value).abs();
            let t = err_a / (err_a + err_b);
            points.push(a.pos.lerp(b.pos, t));
        }

        Some(Line::new(points[0], points[1]))
    }
}

#[derive(Debug, Clone, Copy)]
pub struct SampleRect {
    pub triangles: [SampleTriangle; 4],
}

impl SampleRect {
    pub fn new(
        tl: SamplePoint,
        tr: SamplePoint,
        br: SamplePoint,
        bl: SamplePoint,
        center: SamplePoint,
    ) -> Self {
        let triangles = [
            SampleTriangle::new(tl, tr, center),
            SampleTriangle::new(tr, br, center),
            SampleTriangle::new(br, bl, center),
            SampleTriangle::new(bl, tl, center),
        ];
        Self { triangles }
    }
}