Browse Source

Add PNG output of the charts

main
raffitz 3 years ago
parent
commit
bbc1dfcf43
Signed by: raffitz
GPG Key ID: BB3596BD0A31252D
  1. 106
      Cargo.lock
  2. 2
      Cargo.toml
  3. 11
      src/error.rs
  4. 105
      src/main.rs

106
Cargo.lock generated

@ -1,5 +1,17 @@ @@ -1,5 +1,17 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
[[package]]
name = "ansi_term"
version = "0.11.0"
@ -20,6 +32,12 @@ dependencies = [ @@ -20,6 +32,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "beef"
version = "0.5.0"
@ -32,6 +50,18 @@ version = "1.2.1" @@ -32,6 +50,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bytemuck"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
@ -47,12 +77,51 @@ dependencies = [ @@ -47,12 +77,51 @@ dependencies = [
"vec_map",
]
[[package]]
name = "crc32fast"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if",
]
[[package]]
name = "fallible_collections"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74bebf0efe2e883c1619c455e3f1764333064694ebd5125d2faddabfb5963186"
dependencies = [
"hashbrown",
]
[[package]]
name = "flate2"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
dependencies = [
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
dependencies = [
"ahash",
]
[[package]]
name = "hermit-abi"
version = "0.1.17"
@ -64,9 +133,21 @@ dependencies = [ @@ -64,9 +133,21 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.80"
version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
[[package]]
name = "lodepng"
version = "3.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c60778a2380faaea48875fd8d007bae8aea7786c47dd7a455c1c813c3a4c36d7"
dependencies = [
"fallible_collections",
"flate2",
"libc",
"rgb",
]
[[package]]
name = "logos"
@ -92,6 +173,16 @@ dependencies = [ @@ -92,6 +173,16 @@ dependencies = [
"utf8-ranges",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "pomelo"
version = "0.1.5"
@ -136,6 +227,15 @@ version = "0.6.23" @@ -136,6 +227,15 @@ version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "rgb"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287f3c3f8236abb92d8b7e36797f19159df4b58f0a658cc3fb6dd3004b1f3bd3"
dependencies = [
"bytemuck",
]
[[package]]
name = "strsim"
version = "0.8.0"
@ -191,8 +291,10 @@ name = "voxelmap" @@ -191,8 +291,10 @@ name = "voxelmap"
version = "0.1.0"
dependencies = [
"clap",
"lodepng",
"logos",
"pomelo",
"rgb",
]
[[package]]

2
Cargo.toml

@ -9,3 +9,5 @@ description = "Converts mathematical descriptions of objects to voxel maps" @@ -9,3 +9,5 @@ description = "Converts mathematical descriptions of objects to voxel maps"
clap = "2.33"
logos = "0.12"
pomelo = "0.1.5"
lodepng = "3.4"
rgb = "0.8"

11
src/error.rs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
#[derive(Debug, PartialEq)]
use lodepng::Error as LPNGError;
#[derive(Debug)]
pub enum Error {
ParserError,
UnrecognisedBinaryOperator,
@ -11,6 +13,7 @@ pub enum Error { @@ -11,6 +13,7 @@ pub enum Error {
IllegalVarInBoundary,
IllegarBoundedVar,
UnboundedVar,
LodePNG(LPNGError),
}
impl From<()> for Error {
@ -18,3 +21,9 @@ impl From<()> for Error { @@ -18,3 +21,9 @@ impl From<()> for Error {
Error::ParserError
}
}
impl From<LPNGError> for Error {
fn from(lode: LPNGError) -> Self {
Error::LodePNG(lode)
}
}

105
src/main.rs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg};
use logos::Logos;
use pomelo::pomelo;
use rgb::*;
use std::collections::HashMap;
use std::fs;
use std::io::{Error, ErrorKind, Read};
@ -17,7 +18,8 @@ macro_rules! scale_message { @@ -17,7 +18,8 @@ macro_rules! scale_message {
fn io_error(err: Error, path: &str) -> String {
match err.kind() {
ErrorKind::NotFound => format!("{} not found", path),
ErrorKind::PermissionDenied => format!("Permission to read {} denied", path),
ErrorKind::PermissionDenied => format!("Permission to access {} denied", path),
ErrorKind::AlreadyExists => format!("{} already exists", path),
_ => format!("Unexpected error accessing {}", path),
}
}
@ -266,6 +268,14 @@ fn main() -> Result<(), error::Error> { @@ -266,6 +268,14 @@ fn main() -> Result<(), error::Error> {
}
}),
)
.arg(
Arg::with_name("offset")
.short("o")
.long("offset")
.help("Offset the computation by half a block")
.takes_value(false)
.multiple(false),
)
.arg(
Arg::with_name("FILE")
.help("The file describing the shape to map")
@ -278,12 +288,28 @@ fn main() -> Result<(), error::Error> { @@ -278,12 +288,28 @@ fn main() -> Result<(), error::Error> {
}
}),
)
.arg(
Arg::with_name("OUTPUT_DIR")
.help("The folder where the output images will be stored")
.required(true)
.index(2)
.validator(move |path: String| -> Result<(), String> {
match fs::create_dir(&path) {
Ok(_) => Ok(()),
Err(error) => Err(io_error(error, &path)),
}
}),
)
.get_matches();
let scale = matches.value_of("scale").map(|s| s.parse::<i32>().unwrap());
let mut object_description = fs::File::open(matches.value_of("FILE").unwrap()).unwrap();
let output_folder = matches.value_of("OUTPUT_DIR").unwrap();
let offset = matches.is_present("offset");
let mut data = String::new();
if object_description.read_to_string(&mut data).is_ok() {
@ -337,7 +363,8 @@ fn main() -> Result<(), error::Error> { @@ -337,7 +363,8 @@ fn main() -> Result<(), error::Error> {
}
}
let var_arg = Some(&vars);
let min = limit.min.eval(&ident_arg, &var_arg)?.floor() as i64;
let min =
(limit.min.eval(&ident_arg, &var_arg)?.floor() as i64) - if offset { 1 } else { 0 };
let max = limit.max.eval(&ident_arg, &var_arg)?.ceil() as i64;
match limit.var {
'x' => {
@ -375,6 +402,80 @@ fn main() -> Result<(), error::Error> { @@ -375,6 +402,80 @@ fn main() -> Result<(), error::Error> {
if unbounded {
return Err(Error::UnboundedVar);
}
let min_x: i64 = min_x.unwrap();
let max_x: i64 = max_x.unwrap();
let min_y: i64 = min_y.unwrap();
let max_y: i64 = max_y.unwrap();
let min_z: i64 = min_z.unwrap();
let max_z: i64 = max_z.unwrap();
let width: i64 = 1 + max_x - min_x;
let height: i64 = 1 + max_y - min_y;
let pix_width: usize = 6 * (width as usize) + 1;
let pix_height: usize = 6 * (height as usize) + 1;
let pix_size: usize = pix_width * pix_height;
for z in min_z..=max_z {
let name = format! {"{}/layer{:04}.png",output_folder,1 + z - min_z};
let filled_in = RGBA8::new(0, 0, 0, 255); // Black
let empty = RGBA8::new(255, 255, 255, 255); // White
let multiple_filled_in = RGBA8::new(0, 0, 255, 255); // Blue
let multiple_empty = RGBA8::new(255, 255, 0, 255); // Yellow
let grid = RGBA8::new(255, 128, 128, 255); // Coral (Grid)
let mut pixels: Vec<RGBA8> = Vec::with_capacity(pix_size);
pixels.resize(pix_size, grid);
for y in min_y..=max_y {
let square_start_y = 6 * (y - min_y) as usize;
let grid_y = y.abs() % 10 == 0;
for x in min_x..=max_x {
let x_f: f64 = (x as f64) + if offset { 0.5_f64 } else { 0_f64 };
let y_f: f64 = (y as f64) + if offset { 0.5_f64 } else { 0_f64 };
let z_f: f64 = (z as f64) + if offset { 0.5_f64 } else { 0_f64 };
let rho: f64 = (x_f.powi(2) + y_f.powi(2)).sqrt();
let phi: f64 = y_f.atan2(x_f);
let r: f64 = (z_f.powi(2) + rho.powi(2)).sqrt();
let tht: f64 = (z_f / rho).atan();
vars.insert('x', x_f);
vars.insert('y', y_f);
vars.insert('z', z_f);
vars.insert('ρ', rho);
vars.insert('φ', phi);
vars.insert('r', r);
vars.insert('θ', tht);
let var_arg = Some(&vars);
let square_start_x = 6 * (x - min_x) as usize;
let grid = if grid_y { true } else { x.abs() % 10 == 0 };
let is_filled = tree.eval(&ident_arg, &var_arg)?;
let color = match (is_filled, grid) {
(false, false) => empty,
(false, true) => multiple_empty,
(true, false) => filled_in,
(true, true) => multiple_filled_in,
};
for pix_x in 0..5 {
for pix_y in 0..5 {
pixels[(1 + square_start_y + pix_y) * pix_width
+ 1
+ square_start_x
+ pix_x] = color;
}
}
}
}
lodepng::encode32_file(name, &pixels, pix_width, pix_height)?;
}
}
Ok(())

Loading…
Cancel
Save