Skip to content

Commit

Permalink
👀
Browse files Browse the repository at this point in the history
  • Loading branch information
ewen-lbh committed May 6, 2024
1 parent 877bf06 commit dd57a14
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ fixtures/
preview.html
out.png
stems_data/
street
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ example-video out="out.mp4" args='':
./shapemaker video --colors colorschemes/palenight.css {{out}} --sync-with fixtures/schedule-hell.midi --audio fixtures/schedule-hell.flac --grid-size 16x10 --resolution 1920 {{args}}

example-image out="out.png" args='':
./shapemaker image --colors colorschemes/palenight.css --resolution 3000 {{out}} {{args}}
./shapemaker image --colors colorschemes/snazzy-light.json --resolution 3000 {{out}} {{args}}
25 changes: 14 additions & 11 deletions src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,7 @@ impl Canvas {
let hatchable = object.hatchable();
objects.insert(
format!("{}#{}", name, i),
ColoredObject::from((
object,
if rand::thread_rng().gen_bool(0.5) {
Some(self.random_fill(hatchable))
} else {
None
},
)),
object.color(self.random_fill(hatchable)),
);
}
Layer {
Expand Down Expand Up @@ -380,6 +373,16 @@ impl Canvas {
region.start == (0, 0) && region.end == self.grid_size
}

pub fn random_region(&self) -> Region {
let start = self.random_point(&self.world_region);
let end = self.random_end_anchor(start, &self.world_region);
Region::from(if start.0 > end.0 {
(end, start)
} else {
(start, end)
})
}

pub fn random_point(&self, region: &Region) -> Point {
region.ensure_nonempty().unwrap();
Point(
Expand All @@ -391,11 +394,11 @@ impl Canvas {
pub fn random_fill(&self, hatchable: bool) -> Fill {
if hatchable {
match rand::thread_rng().gen_range(1..=2) {
1 => Fill::Solid(random_color()),
1 => Fill::Solid(random_color(self.background)),
2 => {
let hatch_size = rand::thread_rng().gen_range(5..=100) as f32 * 1e-2;
Fill::Hatched(
random_color(),
random_color(self.background),
Angle(rand::thread_rng().gen_range(0.0..360.0)),
hatch_size,
// under a certain hatch size, we can't see the hatching if the ratio is not ½
Expand All @@ -409,7 +412,7 @@ impl Canvas {
_ => unreachable!(),
}
} else {
Fill::Solid(random_color())
Fill::Solid(random_color(self.background))
}
}

Expand Down
40 changes: 24 additions & 16 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,30 @@ pub enum Color {
}

#[wasm_bindgen]
pub fn random_color() -> Color {
match rand::thread_rng().gen_range(1..=12) {
1 => Color::Black,
2 => Color::White,
3 => Color::Red,
4 => Color::Green,
5 => Color::Blue,
6 => Color::Yellow,
7 => Color::Orange,
8 => Color::Purple,
9 => Color::Brown,
10 => Color::Pink,
11 => Color::Gray,
12 => Color::Cyan,
_ => unreachable!(),
}
pub fn random_color(except: Option<Color>) -> Color {
let all = [
Color::Black,
Color::White,
Color::Red,
Color::Green,
Color::Blue,
Color::Yellow,
Color::Orange,
Color::Purple,
Color::Brown,
Color::Cyan,
Color::Pink,
Color::Gray,
];
let candidates = all
.iter()
.filter(|c| match except {
None => true,
Some(color) => &&color != c,
})
.collect::<Vec<_>>();

*candidates[rand::thread_rng().gen_range(0..candidates.len())]
}

impl Default for Color {
Expand Down
30 changes: 29 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::env;

use anyhow::Result;
use itertools::Itertools;
use rand::Rng;
use shapemaker::{
cli::{canvas_from_cli, cli_args},
*,
Expand All @@ -11,8 +15,32 @@ pub fn main() -> Result<()> {
pub fn run(args: cli::Args) -> Result<()> {
let mut canvas = canvas_from_cli(&args);

let qrname = env::var("QRCODE_NAME").unwrap();

if args.cmd_image && !args.cmd_video {
canvas = examples::dna_analysis_machine();
canvas.set_grid_size(3, 3);
canvas.add_or_replace_layer(canvas.random_layer("root"));
canvas.new_layer("qr");
let qrcode = Object::Image(
vec![
canvas.world_region.topleft(),
canvas.world_region.topright(),
canvas.world_region.bottomright(),
canvas.world_region.bottomleft(),
][rand::thread_rng().gen_range(0..4)]
.region(),
format!("./{qrname}-qr.png"),
);
canvas.root().remove_all_objects_in(&qrcode.region());
canvas.set_background(Color::White);
canvas.add_object("qr", "qr", qrcode, None).unwrap();
canvas.put_layer_on_top("qr");
canvas.root().objects.values_mut().for_each(|o| {
if !o.object.fillable() {
o.fill = Some(Fill::Solid(Color::Black));
}
});

let rendered = canvas.render(true)?;
if args.arg_file.ends_with(".svg") {
std::fs::write(args.arg_file, rendered).unwrap();
Expand Down
22 changes: 21 additions & 1 deletion src/objects.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{cell, collections::HashMap};

use crate::{ColorMapping, Fill, Filter, Point, Region, Transformation};
use itertools::Itertools;
Expand All @@ -24,6 +24,7 @@ pub enum Object {
CenteredText(Point, String, f32),
// FittedText(Region, String),
Rectangle(Point, Point),
Image(Region, String),
RawSVG(Box<dyn svg::Node>),
}

Expand Down Expand Up @@ -252,6 +253,7 @@ impl Object {
| Object::Dot(anchor)
| Object::SmallCircle(anchor) => anchor.translate(dx, dy),
Object::BigCircle(center) => center.translate(dx, dy),
Object::Image(region, ..) => region.translate(dx, dy),
Object::RawSVG(_) => {
unimplemented!()
}
Expand Down Expand Up @@ -297,6 +299,7 @@ impl Object {
| Object::Dot(anchor)
| Object::SmallCircle(anchor) => anchor.region(),
Object::BigCircle(center) => center.region(),
Object::Image(region, ..) => *region,
Object::RawSVG(_) => {
unimplemented!()
}
Expand Down Expand Up @@ -333,12 +336,29 @@ impl Object {
Object::SmallCircle(..) => self.render_small_circle(cell_size, object_sizes),
Object::Dot(..) => self.render_dot(cell_size, object_sizes),
Object::BigCircle(..) => self.render_big_circle(cell_size),
Object::Image(..) => self.render_image(cell_size),
Object::RawSVG(..) => self.render_raw_svg(),
};

group.set("data-object", id).add(rendered)
}

fn render_image(&self, cell_size: usize) -> Box<dyn svg::node::Node> {
if let Object::Image(region, path) = self {
let (x, y) = region.start.coords(cell_size);
return Box::new(
svg::node::element::Image::new()
.set("x", x)
.set("y", y)
.set("width", region.width() * cell_size)
.set("height", region.height() * cell_size)
.set("href", path.clone()),
);
}

panic!("Expected Image, got {:?}", self);
}

fn render_raw_svg(&self) -> Box<dyn svg::node::Node> {
if let Object::RawSVG(svg) = self {
return svg.clone();
Expand Down
4 changes: 2 additions & 2 deletions src/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,9 @@ impl Region {

// panics if the region is invalid
pub fn ensure_valid(self) -> Result<Self> {
if self.start.0 >= self.end.0 || self.start.1 >= self.end.1 {
if self.start.0 > self.end.0 || self.start.1 > self.end.1 {
return Err(format_err!(
"Invalid region: start ({:?}) >= end ({:?})",
"Invalid region: start ({:?}) > end ({:?})",
self.start,
self.end
));
Expand Down
13 changes: 13 additions & 0 deletions street.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
while true
set id (nanoid -s 10)
qrencode "https://shapemaker.ewen.works/found/$id" -o street/$id-qr.png
QRCODE_NAME=street/$id just example-image out.svg "--objects-count 5..15"
if test (read || echo "n") = "y"
cp out.svg street/$id.svg
resvg --width 2000 out.svg street/$id.png
echo resvg --width 2000 street/$id.svg street/$id.png
echo saved street/$id.svg \| street/$id.png
else
rm street/$id-qr.png
end
end

0 comments on commit dd57a14

Please sign in to comment.