commit ddc7e4f6ce43bc5ea66cf3d38be500f38bf5b39c Author: qwertzuiopy Date: Mon Apr 7 22:54:05 2025 +0200 :3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..09a1b31 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,250 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "deckbox" +version = "0.1.0" +dependencies = [ + "glam", + "rand", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + +[[package]] +name = "glam" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17fcdf9683c406c2fc4d124afd29c0d595e22210d633cbdb8695ba9935ab1dc6" + +[[package]] +name = "libc" +version = "0.2.170" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha", + "rand_core", + "zerocopy 0.8.23", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "syn" +version = "2.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +dependencies = [ + "zerocopy-derive 0.8.23", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5c21af8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "deckbox" +version = "0.1.0" +edition = "2021" + +[dependencies] +glam = "0.30.0" +rand = "0.9.0" diff --git a/deckbox.stl b/deckbox.stl new file mode 100644 index 0000000..1381aad Binary files /dev/null and b/deckbox.stl differ diff --git a/deckbox_part2.stl b/deckbox_part2.stl new file mode 100644 index 0000000..e480d37 Binary files /dev/null and b/deckbox_part2.stl differ diff --git a/deckbox_part3.stl b/deckbox_part3.stl new file mode 100644 index 0000000..aad34da Binary files /dev/null and b/deckbox_part3.stl differ diff --git a/output/output.scad b/output/output.scad new file mode 100644 index 0000000..829dfcd --- /dev/null +++ b/output/output.scad @@ -0,0 +1 @@ +$fa= 0.1;$fn= 150;difference(){ union(){ translate([-3, -3, -3]) { cube([25, 25, 15], center=false); } translate([1.5, 1.5, 12]) { cube([20.5, 20.5, 1], center=false); } } cube([50, 50, 7], center=false); {translate([-3, -3, 0]) { rotate([0, 0, 45]) { cube([2, 50, 50], center=true); } }mirror([0, 1, 0]) { rotate([90, 0, 0]) { translate([-3, -3, 0]) { rotate([0, 0, 45]) { cube([2, 50, 50], center=true); } } } }mirror([1, 0, 0]) { rotate([0, -90, 0]) { translate([-3, -3, 0]) { rotate([0, 0, 45]) { cube([2, 50, 50], center=true); } } } }} {translate([22, -3, 0]) { rotate([0, 0, -45]) { cube([2, 50, 50], center=true); } }mirror([0, 1, 0]) { rotate([90, 0, 0]) { translate([22, -3, 0]) { rotate([0, 0, -45]) { cube([2, 50, 50], center=true); } } } }mirror([1, 0, 0]) { rotate([0, -90, 0]) { translate([22, -3, 0]) { rotate([0, 0, -45]) { cube([2, 50, 50], center=true); } } } }} {translate([-3, 22, 0]) { rotate([0, 0, -45]) { cube([2, 50, 50], center=true); } }mirror([0, 1, 0]) { rotate([90, 0, 0]) { translate([-3, 22, 0]) { rotate([0, 0, -45]) { cube([2, 50, 50], center=true); } } } }mirror([1, 0, 0]) { rotate([0, -90, 0]) { translate([-3, 22, 0]) { rotate([0, 0, -45]) { cube([2, 50, 50], center=true); } } } }} translate([10, 10, 0]) { cube([50, 50, 50], center=false); } translate([5, 5, 8.9]) { cylinder(h=2.2, r1=3.2, r2=3.2); } translate([5, 5, 8.9]) { rotate([0, 0, 45]) { translate([0, -3.2, 0]) { cube([50, 6.4, 2.2], center=false); } } } }translate([7, 7, 0]) { cube([15, 15, 3], center=false); }translate([-0.001, -0.001, -0.001]) { cube([7.001, 7.001, 7.001], center=false); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1dc95e6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,288 @@ +mod rcad; +use crate::rcad::*; + +const STICK: f32 = 7.; +const WOOD: f32 = 4.; +const SIDEPLATE_LENGTH: f32 = 25.; +const SIDEPLATE_THICK: f32 = 3.; +const TAMPER: f32 = 2.; +const TOP_HEIGHT: f32 = 10.; +const TOP_OVERLAP_TOP: f32 = 5.; +const TOP_OVERLAP_MIDDLE: f32 = 3.; +const TOP_OVERLAP_INNER: f32 = 3.; +const MAGNET_RADIUS: f32 = 3.2; +const MAGNET_THICK: f32 = 2.2; +const INSET_HEIGHT: f32 = 1.; +const INSET_RIM: f32 = 1.; +const INSET_GAP: f32 = 0.5; +const TOP_TOP_HEIGHT: f32 = 15.; + +fn main() -> Result<(), std::io::Error> { + let mut data = init()?; + data.push_str(&top_top()?); + + process(data)?; + + Ok(()) +} + +fn top_top() -> Result { + let mut data = String::new(); + + data.push_str(&difference(&vec![ + union(&vec![ + translate( + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + cube(SIDEPLATE_LENGTH, SIDEPLATE_LENGTH, TOP_TOP_HEIGHT, false), + ), + translate( + INSET_RIM + INSET_GAP, + INSET_RIM + INSET_GAP, + TOP_TOP_HEIGHT - SIDEPLATE_THICK, + cube( + SIDEPLATE_LENGTH - SIDEPLATE_THICK - INSET_RIM - INSET_GAP, + SIDEPLATE_LENGTH - SIDEPLATE_THICK - INSET_RIM - INSET_GAP, + INSET_HEIGHT, + false, + ), + ), + ]), + cube(INF, INF, STICK, false), + corner_mirror(translate( + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + rotate(0., 0., 45., cube(TAMPER, INF, INF, true)), + )), + corner_mirror(translate( + SIDEPLATE_LENGTH - SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + rotate(0., 0., -45., cube(TAMPER, INF, INF, true)), + )), + corner_mirror(translate( + -SIDEPLATE_THICK, + SIDEPLATE_LENGTH - SIDEPLATE_THICK, + 0., + rotate(0., 0., -45., cube(TAMPER, INF, INF, true)), + )), + translate( + TOP_OVERLAP_MIDDLE + STICK, + TOP_OVERLAP_MIDDLE + STICK, + 0., + cube(INF, INF, INF, false), + ), + translate( + (TOP_OVERLAP_MIDDLE + STICK) / 2., + (TOP_OVERLAP_MIDDLE + STICK) / 2., + (TOP_TOP_HEIGHT - SIDEPLATE_THICK + INSET_HEIGHT - MAGNET_THICK + STICK) / 2., + cylinder(MAGNET_THICK, MAGNET_RADIUS), + ), + translate( + (TOP_OVERLAP_MIDDLE + STICK) / 2., + (TOP_OVERLAP_MIDDLE + STICK) / 2., + (TOP_TOP_HEIGHT - SIDEPLATE_THICK + INSET_HEIGHT - MAGNET_THICK + STICK) / 2., + rotate( + 0., + 0., + 45., + translate( + 0., + -MAGNET_RADIUS, + 0., + cube(INF, MAGNET_RADIUS * 2., MAGNET_THICK, false), + ), + ), + ), + ])); + data.push_str(&translate( + STICK, + STICK, + 0., + cube( + SIDEPLATE_LENGTH - STICK - SIDEPLATE_THICK, + SIDEPLATE_LENGTH - STICK - SIDEPLATE_THICK, + STICK - WOOD, + false, + ), + )); + data.push_str( + &(translate( + -EPS, + -EPS, + -EPS, + cube(STICK + EPS, STICK + EPS, STICK + EPS, false), + )), + ); + Ok(data) +} + +fn top() -> Result { + let mut data = String::new(); + data.push_str(&difference(&vec![ + translate( + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + cube( + SIDEPLATE_LENGTH, + SIDEPLATE_LENGTH, + TOP_HEIGHT + TOP_OVERLAP_TOP, + false, + ), + ), + translate(0., 0., -EPS, cube(INF, INF, TOP_HEIGHT + EPS, false)), + translate( + TOP_OVERLAP_MIDDLE + STICK, + TOP_OVERLAP_MIDDLE + STICK, + 0., + cube(INF, INF, INF, false), + ), + translate( + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + rotate(0., 0., 45., cube(TAMPER, INF, INF, true)), + ), + translate( + SIDEPLATE_LENGTH - SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + rotate(0., 0., -45., cube(TAMPER, INF, INF, true)), + ), + translate( + -SIDEPLATE_THICK, + SIDEPLATE_LENGTH - SIDEPLATE_THICK, + 0., + rotate(0., 0., -45., cube(TAMPER, INF, INF, true)), + ), + mirror( + 1., + -1., + 0., + translate( + -SIDEPLATE_THICK, + 0., + 0., + rotate(0., -45., 0., cube(TAMPER, INF, INF, true)), + ), + ), + translate( + (TOP_OVERLAP_MIDDLE + STICK) / 2., + (TOP_OVERLAP_MIDDLE + STICK) / 2., + TOP_HEIGHT + TOP_OVERLAP_TOP / 2. - MAGNET_THICK / 2. - INSET_HEIGHT / 2., + cylinder(MAGNET_THICK, MAGNET_RADIUS), + ), + translate( + (TOP_OVERLAP_MIDDLE + STICK) / 2., + (TOP_OVERLAP_MIDDLE + STICK) / 2., + TOP_HEIGHT + TOP_OVERLAP_TOP / 2. - MAGNET_THICK / 2. - INSET_HEIGHT / 2., + rotate( + 0., + 0., + 45., + translate( + 0., + -MAGNET_RADIUS, + 0., + cube(INF, MAGNET_RADIUS * 2., MAGNET_THICK, false), + ), + ), + ), + translate( + INSET_RIM, + INSET_RIM, + TOP_HEIGHT + TOP_OVERLAP_TOP - INSET_HEIGHT, + cube(INF, INF, INSET_HEIGHT + EPS, false), + ), + ])); + data.push_str(&mirror( + 1., + -1., + 0., + translate( + 0., + STICK, + 0., + cube( + STICK - WOOD, + SIDEPLATE_LENGTH - STICK - SIDEPLATE_THICK, + TOP_HEIGHT, + false, + ), + ), + )); + data.push_str(&mirror( + 1., + -1., + 0., + translate( + STICK, + STICK, + TOP_HEIGHT - TOP_OVERLAP_INNER, + cube( + TOP_OVERLAP_MIDDLE, + SIDEPLATE_LENGTH - STICK - SIDEPLATE_THICK, + TOP_OVERLAP_INNER, + false, + ), + ), + )); + Ok(data) +} + +fn full_corner() -> Result<(), std::io::Error> { + let mut data = init()?; + + data.push_str(&difference(&vec![ + translate( + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + cube(SIDEPLATE_LENGTH, SIDEPLATE_LENGTH, SIDEPLATE_LENGTH, false), + ), + cube(INF, INF, INF, false), + corner_mirror(translate( + -SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + rotate(0., 0., 45., cube(TAMPER, INF, INF, true)), + )), + corner_mirror(translate( + SIDEPLATE_LENGTH - SIDEPLATE_THICK, + -SIDEPLATE_THICK, + 0., + rotate(0., 0., -45., cube(TAMPER, INF, INF, true)), + )), + corner_mirror(translate( + -SIDEPLATE_THICK, + SIDEPLATE_LENGTH - SIDEPLATE_THICK, + 0., + rotate(0., 0., -45., cube(TAMPER, INF, INF, true)), + )), + ])); + data.push_str(&corner_mirror(translate( + STICK, + STICK, + 0., + cube( + SIDEPLATE_LENGTH - STICK - SIDEPLATE_THICK, + SIDEPLATE_LENGTH - STICK - SIDEPLATE_THICK, + STICK - WOOD, + false, + ), + ))); + data.push_str( + &(translate( + -EPS, + -EPS, + -EPS, + cube(STICK + EPS, STICK + EPS, STICK + EPS, false), + )), + ); + + process(data)?; + Ok(()) +} diff --git a/src/rcad/mod.rs b/src/rcad/mod.rs new file mode 100644 index 0000000..5e76346 --- /dev/null +++ b/src/rcad/mod.rs @@ -0,0 +1,193 @@ +use glam::f32::Vec2; +use rand::Rng; +use std::process::Command; +use std::{fs, io}; + +pub const EPS: f32 = 0.001; +pub const INF: f32 = 50.; + +pub fn init() -> Result { + if fs::exists("output")? { + println!("output dir already exists, emptying"); + fs::remove_dir_all("output")?; + } + if let Ok(_) = fs::create_dir("output") { + println!("successfully created output directory"); + } else { + println!("could not create output directory"); + } + + let mut data = String::new(); + data.push_str(&set("fa".into(), 0.1)); + data.push_str(&set("fn".into(), 150.)); + return Ok(data); +} + +pub fn process(data: String) -> Result<(), io::Error> { + fs::write("./output/output.scad", data)?; + let output = Command::new("flatpak") + .arg("run") + .arg("org.openscad.OpenSCAD") + .arg("./output/output.scad") + .output()?; + println!("{:?}", output); + Ok(()) +} + +pub fn corner_mirror(what: String) -> String { + let mut res = String::new(); + res.push_str("{"); + res.push_str(&what); + res.push_str(&mirror_nocopy( + 0., + 1., + 0., + rotate(90., 0., 0., what.clone()), + )); + res.push_str(&mirror_nocopy(1., 0., 0., rotate(0., -90., 0., what))); + res.push_str("}"); + res +} + +fn process_svg(path: &str) { + let output = Command::new("inkscape") + .arg(format!( + "--actions=select:path1; object-stroke-to-path; export-filename:{};export-do", + path + )) + .arg(format!("{path}")) + .output() + .expect("Could not execute command"); + print!("{:?}", output); +} + +pub enum Path { + Move(Vec2), + Line(Vec2), + Bezier((Vec2, Vec2, Vec2)), + Close, +} + +fn path_to_svg(path: &Vec, stroke: Option) -> String { + let mut s = String::from(""); + s +} + +fn path(path: &Vec, stroke: Option) -> String { + let mut name = String::from("blah"); + let mut rng = rand::rng(); + name.push_str(&rng.random::().to_string()); + name.push_str(".svg"); + fs::write(format!("output/{}", name), path_to_svg(&path, stroke)) + .expect("Unable to write file"); + process_svg(&name); + include(&name) +} + +pub fn set(var: String, value: f32) -> String { + format!("${var}= {value};") +} + +pub struct ExOptions { + height: f32, + center: bool, + convexity: f32, + twist: f32, + slices: f32, + scale: f32, +} +impl Default for ExOptions { + fn default() -> ExOptions { + ExOptions { + height: 1.0, + center: true, + convexity: 10.0, + twist: 0.0, + slices: 20.0, + scale: 1.0, + } + } +} + +pub fn include(what: &str) -> String { + format!("import(file=\"{what}\");") +} + +pub fn linear_extrude(opt: ExOptions, what: String) -> String { + format!("linear_extrude(height={height}, center={center}, convexity={convexity}, twist={twist}, slices={slices}, scale={scale}) {{ {what} }}", + height=opt.height, center=opt.center,convexity=opt.convexity,twist=opt.twist,slices=opt.slices,scale=opt.scale) +} +pub fn rotate_extrude(angle: f32, convexity: f32, what: String) -> String { + format!("rotate_extrude(angle={angle}, convexity={convexity}) {{ {what} }}") +} +pub fn circle(radius: f32) -> String { + format!("circle({radius});") +} +pub fn sphere(radius: f32) -> String { + format!("sphere({});", radius) +} +pub fn cube(width: f32, depth: f32, height: f32, center: bool) -> String { + format!( + "cube([{}, {}, {}], center={});", + width, depth, height, center + ) +} +pub fn cylinder(height: f32, radius: f32) -> String { + format!("cylinder(h={height}, r1={radius}, r2={radius});") +} +pub fn translate(x: f32, y: f32, z: f32, what: String) -> String { + format!("translate([{}, {}, {}]) {{ {} }}", x, y, z, what) +} +pub fn rotate(x: f32, y: f32, z: f32, what: String) -> String { + format!("rotate([{}, {}, {}]) {{ {} }}", x, y, z, what) +} +pub fn mirror(x: f32, y: f32, z: f32, what: String) -> String { + format!( + "mirror([{}, {}, {}]) {{ {} }} {{ {} }}", + x, y, z, what, what + ) +} +pub fn mirror_nocopy(x: f32, y: f32, z: f32, what: String) -> String { + format!("mirror([{}, {}, {}]) {{ {} }}", x, y, z, what) +} +pub fn intersection(what: &[String]) -> String { + let mut s = format!("intersection(){{ "); + for i in what.iter() { + s = format!("{} {}", s, i); + } + format!("{} }}", s) +} +pub fn union(what: &[String]) -> String { + let mut s = format!("union(){{ "); + for i in what.iter() { + s = format!("{} {}", s, i); + } + format!("{} }}", s) +} +pub fn difference(what: &[String]) -> String { + let mut s = format!("difference(){{ "); + for i in what.iter() { + s = format!("{} {}", s, i); + } + format!("{} }}", s) +}