feat: add predefined formats

This commit is contained in:
Ingolf Wagner 2021-04-09 08:19:09 +02:00
parent 3d86835849
commit 4af31ce185
No known key found for this signature in database
GPG key ID: 76BF5F1928B9618B
3 changed files with 68 additions and 21 deletions

View file

@ -2,8 +2,8 @@ use geo::algorithm::intersects::Intersects;
use geo::algorithm::rotate::Rotate; use geo::algorithm::rotate::Rotate;
use geo::prelude::Translate; use geo::prelude::Translate;
use geo::rotate::RotatePoint; use geo::rotate::RotatePoint;
use geo::LineString;
use geo::{Coordinate, MultiPolygon, Point, Polygon}; use geo::{Coordinate, MultiPolygon, Point, Polygon};
use geo::{LineString};
use geo_clipper::Clipper; use geo_clipper::Clipper;
use polygon_art::MultiPolygonExt; use polygon_art::MultiPolygonExt;
use polygon_art::{load_multipolgon_from_svg, Context}; use polygon_art::{load_multipolgon_from_svg, Context};
@ -14,15 +14,28 @@ fn main() {
let mut context = Context::create(); let mut context = Context::create();
let mut rng = context.gen_rng(); let mut rng = context.gen_rng();
let ship_width = 100.; let width = context.width;
let center_point = MultiPolygon(vec![create_asteroid(&mut rng, 20, 2)]) let height = context.height;
.scale_to_width(2.5 * ship_width) let diagonal = f64::sqrt(width * width + height * height);
.translate(context.width / 2., context.height / 2.);
// todo : it does not make to much sense to define all parameters like this
// todo : it makes more sense to create a static (diagonal / width /height ratio ) setup and scale it up
let frame_offset = diagonal * 0.01;
let max_asteroid = (diagonal / 40.) as usize;
let min_asteroid_size = diagonal / 40.;
let max_asteroid_size = diagonal / 12.;
let ship_length = diagonal / 23.;
let ship_orbit = 3.0;
let center_point = MultiPolygon(vec![create_asteroid(&mut rng, 8, 2)])
.scale_to_width(ship_orbit * ship_length)
.translate(width / 2., height / 2.);
// create asteroid // create asteroid
let mut asteroids: Vec<MultiPolygon<f64>> = Vec::new(); let mut asteroids: Vec<MultiPolygon<f64>> = Vec::new();
for _ in 0..40 { for _ in 0..(max_asteroid * 2) {
let without_orbit = rng.gen_range(40..140) as f64; let without_orbit = rng.gen_range(min_asteroid_size..max_asteroid_size) as f64;
let with_orbit = without_orbit * 1.32; let with_orbit = without_orbit * 1.32;
let x = rng.gen_range(0..(context.width as i32)) as f64; let x = rng.gen_range(0..(context.width as i32)) as f64;
let y = rng.gen_range(0..(context.height as i32)) as f64; let y = rng.gen_range(0..(context.height as i32)) as f64;
@ -30,14 +43,15 @@ fn main() {
.scale_to_width(with_orbit) .scale_to_width(with_orbit)
.translate(x, y); .translate(x, y);
if !center_point.intersects(&asteroid) && asteroids if (!center_point.intersects(&asteroid))
.iter() && asteroids
.find(|&m| *&m.intersects(&asteroid)) .iter()
.is_none() .find(|&m| *&m.intersects(&asteroid))
.is_none()
{ {
asteroids.push(asteroid.scale_to_width(without_orbit)); asteroids.push(asteroid.scale_to_width(without_orbit));
} }
if asteroids.len() > 23 { if asteroids.len() > max_asteroid {
break; break;
} }
} }
@ -46,7 +60,8 @@ fn main() {
let rotation = rng.gen_range(0..360); let rotation = rng.gen_range(0..360);
let ship = load_multipolgon_from_svg("pool/asteroids/ship3.svg") let ship = load_multipolgon_from_svg("pool/asteroids/ship3.svg")
.unwrap() .unwrap()
.scale_to_width(ship_width) .rotate(90.) // rotate to scale ship with width
.scale_to_width(ship_length)
.translate_center() .translate_center()
.rotate(rotation as f64); .rotate(rotation as f64);
context.translate_center(); context.translate_center();
@ -54,8 +69,7 @@ fn main() {
context.restore(); context.restore();
// drawing and clipping // drawing and clipping
let frame_space = 10.; let window = context.frame(frame_offset, frame_offset, frame_offset, frame_offset);
let window = context.frame(frame_space, frame_space, frame_space, frame_space);
context.draw_polygon(&window); context.draw_polygon(&window);
for asteroid in asteroids.iter() { for asteroid in asteroids.iter() {

View file

@ -91,12 +91,29 @@ impl Context {
pub fn gen_rng(&mut self) -> StdRng { pub fn gen_rng(&mut self) -> StdRng {
StdRng::seed_from_u64(self.pseudo_random_number_generator.gen()) StdRng::seed_from_u64(self.pseudo_random_number_generator.gen())
} }
pub fn create() -> Context { pub fn create() -> Context {
let opt = Opt::get_command_line_arguments(); let opt = Opt::get_command_line_arguments();
let height = f64::from(opt.height.clone());
let width = f64::from(opt.width.clone());
let line_size = opt.line_size.clone(); let line_size = opt.line_size.clone();
let mm = 3.779527547619048; // calculated with inkscape 1587.40157 (px) / 420 (mm) (from a3)
let (mut height, mut width) = match opt.format {
None => (f64::from(opt.height.clone()), f64::from(opt.width.clone())),
Some(format) => match &format[..] {
"a3" => (297. * mm, 420. * mm),
"a4" => (210. * mm, 297. * mm),
"a5" => (148. * mm, 210. * mm),
"x220" => (768., 1366.),
_ => (f64::from(opt.height.clone()), f64::from(opt.width.clone())),
},
};
if opt.orientation == "portrait" {
let cache = height;
height = width;
width = cache;
}
let random_seed = match opt.random_seed { let random_seed = match opt.random_seed {
Some(random_seed) => random_seed, Some(random_seed) => random_seed,
None => match opt.random_seed_date { None => match opt.random_seed_date {
@ -128,9 +145,8 @@ impl Context {
.expect("Can't svg surface"); .expect("Can't svg surface");
Box::new(SvgRenderContainer::new(svg_surface, palette)) as Box<dyn RenderContainer> Box::new(SvgRenderContainer::new(svg_surface, palette)) as Box<dyn RenderContainer>
} else if opt.output_type == "png" { } else if opt.output_type == "png" {
let png_surface = let png_surface = ImageSurface::create(Format::Rgb24, width as i32, height as i32)
ImageSurface::create(Format::Rgb24, opt.width.clone(), opt.height.clone()) .expect("Can't create png surface");
.expect("Can't create png surface");
Box::new(PngRenderContainer::new( Box::new(PngRenderContainer::new(
opt.output.to_string_lossy().to_string(), opt.output.to_string_lossy().to_string(),
png_surface, png_surface,

View file

@ -13,13 +13,30 @@ pub struct Opt {
pub output: PathBuf, pub output: PathBuf,
/// define width in pixels /// define width in pixels
#[structopt(long, default_value = "400")] #[structopt(long, default_value = "600")]
pub width: i32, pub width: i32,
/// define height in pixels /// define height in pixels
#[structopt(long, default_value = "400")] #[structopt(long, default_value = "400")]
pub height: i32, pub height: i32,
/// use a predefined format
#[structopt(
long,
conflicts_with="height",
conflicts_with="width",
possible_values=&["a3", "a4", "a5", "x220"]
)]
pub format: Option<String>,
/// change orientation
#[structopt(
long,
default_value="landscape",
possible_values=&["portrait", "landscape"]
)]
pub orientation: String,
/// define line size in pixels, all lines will be this thick /// define line size in pixels, all lines will be this thick
#[structopt(long, default_value = "1.0")] #[structopt(long, default_value = "1.0")]
pub line_size: f64, pub line_size: f64,