feat: add predefined formats

develop
Ingolf Wagner 2021-04-09 08:19:09 +02:00
parent 3d86835849
commit 4af31ce185
Signed by: palo
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::prelude::Translate;
use geo::rotate::RotatePoint;
use geo::LineString;
use geo::{Coordinate, MultiPolygon, Point, Polygon};
use geo::{LineString};
use geo_clipper::Clipper;
use polygon_art::MultiPolygonExt;
use polygon_art::{load_multipolgon_from_svg, Context};
@ -14,15 +14,28 @@ fn main() {
let mut context = Context::create();
let mut rng = context.gen_rng();
let ship_width = 100.;
let center_point = MultiPolygon(vec![create_asteroid(&mut rng, 20, 2)])
.scale_to_width(2.5 * ship_width)
.translate(context.width / 2., context.height / 2.);
let width = context.width;
let height = context.height;
let diagonal = f64::sqrt(width * width + height * height);
// 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
let mut asteroids: Vec<MultiPolygon<f64>> = Vec::new();
for _ in 0..40 {
let without_orbit = rng.gen_range(40..140) as f64;
for _ in 0..(max_asteroid * 2) {
let without_orbit = rng.gen_range(min_asteroid_size..max_asteroid_size) as f64;
let with_orbit = without_orbit * 1.32;
let x = rng.gen_range(0..(context.width 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)
.translate(x, y);
if !center_point.intersects(&asteroid) && asteroids
.iter()
.find(|&m| *&m.intersects(&asteroid))
.is_none()
if (!center_point.intersects(&asteroid))
&& asteroids
.iter()
.find(|&m| *&m.intersects(&asteroid))
.is_none()
{
asteroids.push(asteroid.scale_to_width(without_orbit));
}
if asteroids.len() > 23 {
if asteroids.len() > max_asteroid {
break;
}
}
@ -46,7 +60,8 @@ fn main() {
let rotation = rng.gen_range(0..360);
let ship = load_multipolgon_from_svg("pool/asteroids/ship3.svg")
.unwrap()
.scale_to_width(ship_width)
.rotate(90.) // rotate to scale ship with width
.scale_to_width(ship_length)
.translate_center()
.rotate(rotation as f64);
context.translate_center();
@ -54,8 +69,7 @@ fn main() {
context.restore();
// drawing and clipping
let frame_space = 10.;
let window = context.frame(frame_space, frame_space, frame_space, frame_space);
let window = context.frame(frame_offset, frame_offset, frame_offset, frame_offset);
context.draw_polygon(&window);
for asteroid in asteroids.iter() {

View File

@ -91,12 +91,29 @@ impl Context {
pub fn gen_rng(&mut self) -> StdRng {
StdRng::seed_from_u64(self.pseudo_random_number_generator.gen())
}
pub fn create() -> Context {
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 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 {
Some(random_seed) => random_seed,
None => match opt.random_seed_date {
@ -128,9 +145,8 @@ impl Context {
.expect("Can't svg surface");
Box::new(SvgRenderContainer::new(svg_surface, palette)) as Box<dyn RenderContainer>
} else if opt.output_type == "png" {
let png_surface =
ImageSurface::create(Format::Rgb24, opt.width.clone(), opt.height.clone())
.expect("Can't create png surface");
let png_surface = ImageSurface::create(Format::Rgb24, width as i32, height as i32)
.expect("Can't create png surface");
Box::new(PngRenderContainer::new(
opt.output.to_string_lossy().to_string(),
png_surface,

View File

@ -13,13 +13,30 @@ pub struct Opt {
pub output: PathBuf,
/// define width in pixels
#[structopt(long, default_value = "400")]
#[structopt(long, default_value = "600")]
pub width: i32,
/// define height in pixels
#[structopt(long, default_value = "400")]
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
#[structopt(long, default_value = "1.0")]
pub line_size: f64,