feat: add asteroids.rs
This commit is contained in:
parent
b30d687963
commit
3d86835849
5 changed files with 207 additions and 4 deletions
34
pool/asteroids/ship1.svg
Normal file
34
pool/asteroids/ship1.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
height="48"
|
||||
width="48">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
id="path845"
|
||||
d="M 5.9999998,0 2,12 5.9999998,11 10,12 Z"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 940 B |
34
pool/asteroids/ship2.svg
Normal file
34
pool/asteroids/ship2.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
height="48"
|
||||
width="48">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
id="path869"
|
||||
d="M 5.9999998,0 2,12 3.9058027,11 H 7.9098644 L 10,12 Z"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 954 B |
34
pool/asteroids/ship3.svg
Normal file
34
pool/asteroids/ship3.svg
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
height="48"
|
||||
width="48">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
id="path869"
|
||||
d="M 5.9999998,0 2,12 3.9058027,9.4125 H 7.9098644 L 10,12 Z"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 958 B |
91
src/bin/asteroids.rs
Normal file
91
src/bin/asteroids.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
use geo::algorithm::intersects::Intersects;
|
||||
use geo::algorithm::rotate::Rotate;
|
||||
use geo::prelude::Translate;
|
||||
use geo::rotate::RotatePoint;
|
||||
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};
|
||||
use rand::prelude::StdRng;
|
||||
use rand::Rng;
|
||||
|
||||
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.);
|
||||
|
||||
// create asteroid
|
||||
let mut asteroids: Vec<MultiPolygon<f64>> = Vec::new();
|
||||
for _ in 0..40 {
|
||||
let without_orbit = rng.gen_range(40..140) 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;
|
||||
let asteroid = MultiPolygon(vec![create_asteroid(&mut rng, 20, 15)])
|
||||
.scale_to_width(with_orbit)
|
||||
.translate(x, y);
|
||||
|
||||
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 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// load ships
|
||||
let rotation = rng.gen_range(0..360);
|
||||
let ship = load_multipolgon_from_svg("pool/asteroids/ship3.svg")
|
||||
.unwrap()
|
||||
.scale_to_width(ship_width)
|
||||
.translate_center()
|
||||
.rotate(rotation as f64);
|
||||
context.translate_center();
|
||||
context.draw_multipolygon(&ship);
|
||||
context.restore();
|
||||
|
||||
// drawing and clipping
|
||||
let frame_space = 10.;
|
||||
let window = context.frame(frame_space, frame_space, frame_space, frame_space);
|
||||
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(),
|
||||
)
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use cairo::Format;
|
||||
use cairo::{ImageSurface, SvgSurface};
|
||||
use geo_types::{LineString, MultiPolygon, Polygon};
|
||||
use geo::{polygon, LineString, MultiPolygon, Polygon};
|
||||
use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
|
@ -22,6 +22,16 @@ pub struct Context {
|
|||
}
|
||||
|
||||
impl Context {
|
||||
/// generate a frame for the image
|
||||
pub fn frame(&mut self, left: f64, bottom: f64, right: f64, top: f64) -> Polygon<f64> {
|
||||
polygon![
|
||||
(x: left, y: top),
|
||||
(x: self.width - right, y: top),
|
||||
(x: self.width - right, y: self.height - bottom),
|
||||
(x: left , y: self.height - bottom),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn draw_multipolygon(&self, multi_polygon: &MultiPolygon<f64>) {
|
||||
for polygon in multi_polygon.iter() {
|
||||
self.draw_polygon(polygon);
|
||||
|
@ -48,10 +58,7 @@ impl Context {
|
|||
}
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
// cairo facades
|
||||
impl Context {
|
||||
/// restore state which was saved before by the context
|
||||
pub fn restore(&self) {
|
||||
self.render_container.context().restore();
|
||||
|
@ -81,6 +88,9 @@ impl Context {
|
|||
self.render_container.render();
|
||||
}
|
||||
|
||||
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());
|
||||
|
|
Loading…
Reference in a new issue