mcsdf 0.1.0

Multi-channel signed distance fields rasterizer library
Documentation
use std::f32::consts::PI;

pub fn solve_quadratic(a: f32, b: f32, c: f32) -> (Option<f32>, Option<f32>) {
    if a == 0.0 {
        if b == 0.0 {
            return (None, None);
        }
        return (Some(-c / b), None);
    }
    let discriminant = b * b - 4.0 * a * c;
    if discriminant < 0.0 {
        return (None, None);
    }
    if discriminant == 0.0 {
        return (Some(-0.5 * b / a), None);
    }

    let sqrt_delta = discriminant.sqrt();
    let t1 = (-b + sqrt_delta) / (2.0 * a);
    let t2 = (-b - sqrt_delta) / (2.0 * a);

    (Some(t1), Some(t2))
}

#[allow(clippy::many_single_char_names)]
pub fn solve_cubic(a: f32, b: f32, c: f32, d: f32) -> (Option<f32>, Option<f32>, Option<f32>) {
    if a == 0.0 {
        let (r1, r2) = solve_quadratic(b, c, d);
        return (r1, r2, None);
    }

    let b = b / a;
    let c = c / a;
    let d = d / a;

    let q = (b * b - 3.0 * c) / 9.0;
    let r = (2.0 * b * b * b - 9.0 * b * c + 27.0 * d) / 54.0;
    let qqq = q * q * q;
    let discriminant = qqq - r * r;
    let third = 1.0 / 3.0;

    if discriminant >= 0.0 {
        let twopi = 2.0 * PI;
        let theta = (r / qqq.sqrt()).acos();
        let mult = -2.0 * q.sqrt();
        let add = -b * third;
        let r0 = mult * (third * theta).cos() + add;
        let r1 = mult * (third * (theta + twopi)).cos() + add;
        let r2 = mult * (third * (theta + twopi + twopi)).cos() + add;
        return (Some(r0), Some(r1), Some(r2));
    }

    let temp = ((-discriminant).sqrt() + r.abs()).powf(third);
    let sign = r.signum();
    let r = -sign * (temp + q / temp) - third * b;
    return (Some(r), None, None);
}

pub fn median<T: Ord + Copy>(c: [T; 3]) -> T {
    c[0].min(c[1]).max(c[0].max(c[1]).min(c[2]))
}

pub fn median_f32(c: [f32; 3]) -> f32 {
    c[0].min(c[1]).max(c[0].max(c[1]).min(c[2]))
}

pub fn clamp<T: Ord + Copy>(x: T, x_min: T, x_max: T) -> T {
    x.max(x_min).min(x_max)
}

pub fn clamp_f32(x: f32, x_min: f32, x_max: f32) -> f32 {
    x.max(x_min).min(x_max)
}

pub fn min<T: Ord + Copy>(c: [T; 3]) -> T {
    c[0].min(c[1]).min(c[2])
}

pub fn max<T: Ord + Copy>(c: [T; 3]) -> T {
    c[0].max(c[1]).max(c[2])
}