Skip to content

fix: Accurrately apply the miter limit - #21

Open
R-Cramer4 wants to merge 1 commit into
dfrg:mainfrom
R-Cramer4:fix-acute-miter-joins
Open

R-Cramer4 wants to merge 1 commit into
dfrg:mainfrom
R-Cramer4:fix-acute-miter-joins

Conversation

@R-Cramer4

Copy link
Copy Markdown

Lines with angles less than 90 degrees were always beveled so this fix changes that behavior to use the miter limit.

Before

joins_before

After

joins_after

Code used for the images

use std::io::Write;
use zeno::{Join, Mask, Stroke};

const T: u32 = 240;

struct Case {
    path: String,
    limit: f32,
}

fn cases() -> Vec<Case> {
    let h = 160.0 * 3f32.sqrt() / 2.0;
    let tri = format!("M 120 40 L 200 {y} L 40 {y} Z", y = 40.0 + h);
    let mut star = String::new();
    for i in 0..5 {
        let a = -std::f32::consts::FRAC_PI_2 + i as f32 * 4.0 * std::f32::consts::PI / 5.0;
        star += &format!("{} {} {} ", if i == 0 { "M" } else { "L" }, 120.0 + 90.0 * a.cos(), 130.0 + 90.0 * a.sin());
    }
    star += "Z";
    vec![
        Case { path: tri.clone(), limit: 4.0 },
        Case { path: star, limit: 4.0 },
        Case { path: "M 50 200 L 120 60 L 190 200".into(), limit: 4.0 },
        Case { path: tri, limit: 1.9 },
    ]
}

fn mask(path: &str, stroke: &Stroke) -> Vec<u8> {
    Mask::new(path).style(stroke).size(T, T).render().0
}

fn main() {
    let out = std::env::args().nth(1).expect("output .ppm path");
    let cases = cases();
    let w = T * cases.len() as u32;
    let mut img = vec![255u8; (w * T * 3) as usize];
    for (i, c) in cases.iter().enumerate() {
        let mut s = Stroke::new(20.0);
        s.join(Join::Miter).miter_limit(c.limit);
        let thick = mask(&c.path, &s);
        let thin = mask(&c.path, &Stroke::new(1.5));
        for y in 0..T {
            for x in 0..T {
                let m = (y * T + x) as usize;
                let (a, b) = (thick[m] as f32 / 255.0, thin[m] as f32 / 255.0);
                // Stroke in dark blue, centerline in red on top.
                let mut px = [255.0 * (1.0 - a) + 40.0 * a, 255.0 * (1.0 - a) + 70.0 * a, 255.0 * (1.0 - a) + 140.0 * a];
                px = [px[0] * (1.0 - b) + 230.0 * b, px[1] * (1.0 - b) + 40.0 * b, px[2] * (1.0 - b) + 40.0 * b];
                let o = ((y * w + i as u32 * T + x) * 3) as usize;
                img[o..o + 3].copy_from_slice(&px.map(|v| v as u8));
            }
        }
    }
    let mut f = std::fs::File::create(out).unwrap();
    write!(f, "P6\n{w} {T}\n255\n").unwrap();
    f.write_all(&img).unwrap();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant