2021-04-08 22:06:39 +02:00
|
|
|
use geo::algorithm::intersects::Intersects;
|
|
|
|
use geo::algorithm::rotate::Rotate;
|
|
|
|
use geo::prelude::Translate;
|
|
|
|
use geo::rotate::RotatePoint;
|
2021-04-09 08:19:09 +02:00
|
|
|
use geo::LineString;
|
2021-04-08 22:06:39 +02:00
|
|
|
use geo::{Coordinate, MultiPolygon, Point, Polygon};
|
|
|
|
use geo_clipper::Clipper;
|
|
|
|
use polygon_art::MultiPolygonExt;
|
|
|
|
use polygon_art::{load_multipolgon_from_svg, Context};
|
|
|
|
use rand::prelude::StdRng;
|
|
|
|
use rand::Rng;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let mut context = Context::create();
|
|
|
|
let mut rng = context.gen_rng();
|
|
|
|
|
2021-04-09 08:19:09 +02:00
|
|
|
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.);
|
2021-04-08 22:06:39 +02:00
|
|
|
|
|
|
|
// create asteroid
|
|
|
|
let mut asteroids: Vec<MultiPolygon<f64>> = Vec::new();
|
2021-04-09 08:19:09 +02:00
|
|
|
for _ in 0..(max_asteroid * 2) {
|
|
|
|
let without_orbit = rng.gen_range(min_asteroid_size..max_asteroid_size) as f64;
|
2021-04-08 22:06:39 +02:00
|
|
|
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;
|
|
|
|
let asteroid = MultiPolygon(vec![create_asteroid(&mut rng, 20, 15)])
|
|
|
|
.scale_to_width(with_orbit)
|
|
|
|
.translate(x, y);
|
|
|
|
|
2021-04-09 08:19:09 +02:00
|
|
|
if (!center_point.intersects(&asteroid))
|
|
|
|
&& asteroids
|
|
|
|
.iter()
|
|
|
|
.find(|&m| *&m.intersects(&asteroid))
|
|
|
|
.is_none()
|
2021-04-08 22:06:39 +02:00
|
|
|
{
|
|
|
|
asteroids.push(asteroid.scale_to_width(without_orbit));
|
|
|
|
}
|
2021-04-09 08:19:09 +02:00
|
|
|
if asteroids.len() > max_asteroid {
|
2021-04-08 22:06:39 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// load ships
|
|
|
|
let rotation = rng.gen_range(0..360);
|
|
|
|
let ship = load_multipolgon_from_svg("pool/asteroids/ship3.svg")
|
|
|
|
.unwrap()
|
2021-04-09 08:19:09 +02:00
|
|
|
.rotate(90.) // rotate to scale ship with width
|
|
|
|
.scale_to_width(ship_length)
|
2021-04-08 22:06:39 +02:00
|
|
|
.translate_center()
|
|
|
|
.rotate(rotation as f64);
|
|
|
|
context.translate_center();
|
|
|
|
context.draw_multipolygon(&ship);
|
|
|
|
context.restore();
|
|
|
|
|
|
|
|
// drawing and clipping
|
2021-04-09 08:19:09 +02:00
|
|
|
let window = context.frame(frame_offset, frame_offset, frame_offset, frame_offset);
|
2021-04-08 22:06:39 +02:00
|
|
|
context.draw_polygon(&window);
|
|
|
|
|
|
|
|
for asteroid in asteroids.iter() {
|
|
|
|
context.draw_multipolygon(&asteroid.intersection(&window, 100.));
|
|
|
|
}
|
|
|
|
|
|
|
|
context.render();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_asteroid(rng: &mut StdRng, subdivisions: i32, radius_randomization: i32) -> Polygon<f64> {
|
|
|
|
let mut asteroid_points: Vec<Point<f64>> = Vec::new();
|
|
|
|
for _ in 0..subdivisions {
|
|
|
|
let change = rng.gen_range(0..(radius_randomization * 2));
|
|
|
|
asteroid_points.push(Point(Coordinate {
|
|
|
|
x: 0.0,
|
|
|
|
y: 100.0 + (change - radius_randomization) as f64,
|
|
|
|
}));
|
|
|
|
for point in asteroid_points.iter_mut() {
|
|
|
|
let (x, y) = point
|
|
|
|
.rotate_around_point(
|
|
|
|
360. / subdivisions as f64,
|
|
|
|
Point(Coordinate { x: 0., y: 0. }),
|
|
|
|
)
|
|
|
|
.x_y();
|
|
|
|
point.set_x(x);
|
|
|
|
point.set_y(y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Polygon::new(
|
|
|
|
LineString(asteroid_points.iter().map(|point| point.0).collect()),
|
|
|
|
Vec::new(),
|
|
|
|
)
|
|
|
|
}
|