feat: create translate_ext.rs
This commit is contained in:
parent
e169456958
commit
1574ca725f
10 changed files with 117 additions and 48 deletions
|
@ -11,25 +11,25 @@ fn main() {
|
|||
|
||||
let font = AsteroidFont::new();
|
||||
let line = font.get_text("Hey there!".to_string(), 12., LeftRight);
|
||||
context.draw_line_strings(&line);
|
||||
context.draw_multiline_string(&line);
|
||||
context.draw_line_string(&line_string![(x : 0., y:14.), (x: 1000. , y : 14.)]);
|
||||
|
||||
context.translate(0.0, 18.);
|
||||
let line = font.get_text("How are you?".to_string(), 22., LeftRight);
|
||||
context.draw_line_strings(&line);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.translate(0.0, 28.);
|
||||
let line = font.get_text("Here a bitter text!".to_string(), 50., LeftRight);
|
||||
context.draw_line_strings(&line);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.translate(0.0, 56.);
|
||||
let line = font.get_text("0123456789".to_string(), 50., LeftRight);
|
||||
context.draw_line_strings(&line);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.restore();
|
||||
context.translate(30., 50.);
|
||||
let line = font.get_text("0123456789".to_string(), 30., TopDown);
|
||||
context.draw_line_strings(&line);
|
||||
context.draw_multiline_string(&line);
|
||||
|
||||
context.render();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use geo::{Coordinate, Point};
|
|||
use polygon_art::load_multipolygon_from_svg;
|
||||
use polygon_art::Context;
|
||||
use polygon_art::MultiPolygonExt;
|
||||
use polygon_art::TranslateExt;
|
||||
use rand::Rng;
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -6,7 +6,7 @@ use geo::LineString;
|
|||
use geo::{polygon, Coordinate, MultiPolygon, Point, Polygon};
|
||||
use geo_clipper::Clipper;
|
||||
use polygon_art::{load_multipolygon_from_svg_include, Context};
|
||||
use polygon_art::{AsteroidFont, FontDirection, MultiPolygonExt};
|
||||
use polygon_art::{AsteroidFont, FontDirection, MultiPolygonExt, TranslateExt};
|
||||
use rand::prelude::StdRng;
|
||||
use rand::Rng;
|
||||
|
||||
|
@ -91,7 +91,7 @@ fn main() {
|
|||
let score_board_lines = font.get_text(random_seed_string, font_size, FontDirection::LeftRight);
|
||||
context.save();
|
||||
context.translate(frame_offset, frame_offset);
|
||||
context.draw_line_strings(&score_board_lines);
|
||||
context.draw_multiline_string(&score_board_lines);
|
||||
context.restore();
|
||||
|
||||
// draw life board
|
||||
|
@ -102,17 +102,17 @@ fn main() {
|
|||
(x: width - frame_offset - life * x_font_size - 3., y:frame_offset + y_font_size + 3.),
|
||||
(x: width , y:frame_offset + y_font_size + 3.)
|
||||
];
|
||||
// todo translate_top
|
||||
// todo translate_left
|
||||
|
||||
let life_ship = raw_ship
|
||||
.scale_to_width(font_size)
|
||||
.rotate(-90.)
|
||||
.translate_center_y();
|
||||
.translate_center_y()
|
||||
.translate_top();
|
||||
for l in 1..(1 + life as i32) {
|
||||
context.save();
|
||||
context.translate(
|
||||
width - frame_offset - (x_font_size * l as f64) as f64,
|
||||
frame_offset + y_font_size / 2.,
|
||||
frame_offset,
|
||||
);
|
||||
context.draw_multipolygon(&life_ship);
|
||||
context.restore();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use cairo::Format;
|
||||
use cairo::{ImageSurface, SvgSurface};
|
||||
use geo::{polygon, LineString, MultiPolygon, Polygon};
|
||||
use geo::{polygon, LineString, MultiLineString, MultiPolygon, Polygon};
|
||||
use rand::rngs::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
|
||||
|
@ -71,6 +71,12 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw_multiline_string(&self, multilinestring: &MultiLineString<f64>) {
|
||||
for line in multilinestring.iter() {
|
||||
self.draw_line_string(line);
|
||||
}
|
||||
}
|
||||
|
||||
/// restore state which was saved before by the context
|
||||
pub fn restore(&self) {
|
||||
self.render_container.context().restore();
|
||||
|
|
2
src/extensions.rs
Normal file
2
src/extensions.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod multipolygon_ext;
|
||||
pub(crate) mod translate_ext;
|
|
@ -4,41 +4,13 @@ use geo::Polygon;
|
|||
use geo_types::{Coordinate, LineString, MultiPolygon};
|
||||
|
||||
pub trait MultiPolygonExt {
|
||||
fn translate_center(&self) -> Self;
|
||||
fn translate_center_x(&self) -> Self;
|
||||
fn translate_center_y(&self) -> Self;
|
||||
fn scale_to_width(&self, size: f64) -> Self;
|
||||
fn scale(&self, factor: f64) -> Self;
|
||||
}
|
||||
|
||||
impl MultiPolygonExt for MultiPolygon<f64> {
|
||||
fn translate_center(&self) -> Self {
|
||||
let option = self.bounding_rect().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn translate_center_x(&self) -> Self {
|
||||
let option = self.bounding_rect().unwrap();
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), 0.0)
|
||||
}
|
||||
|
||||
fn translate_center_y(&self) -> Self {
|
||||
let option = self.bounding_rect().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
self.translate(0.0, -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn scale_to_width(&self, size: f64) -> Self {
|
||||
// let ((x_min, y_min), (x_max, _)) = self.get_min_max_rectangle();
|
||||
let option = self.bounding_rect().unwrap();
|
||||
|
||||
let diff = f64::abs(option.min().x - option.max().x);
|
||||
let scale = size / diff;
|
||||
self.scale(scale)
|
87
src/extensions/translate_ext.rs
Normal file
87
src/extensions/translate_ext.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
use geo::algorithm::bounding_rect::BoundingRect;
|
||||
use geo::algorithm::translate::Translate;
|
||||
use geo::{CoordinateType, LineString, MultiLineString, MultiPolygon, Polygon, Rect};
|
||||
|
||||
/// Translate Extensions
|
||||
pub trait TranslateExt {
|
||||
/// translate the object to it's center
|
||||
fn translate_center(&self) -> Self;
|
||||
/// translate the object to it's center on the x aches
|
||||
fn translate_center_x(&self) -> Self;
|
||||
/// translate the object to it's center on the y aches
|
||||
fn translate_center_y(&self) -> Self;
|
||||
/// translate the object, so it touches the y aches
|
||||
fn translate_left(&self) -> Self;
|
||||
/// translate the object, so it touches the x aches
|
||||
fn translate_top(&self) -> Self;
|
||||
}
|
||||
|
||||
/// wrapper for BoundingRect because of the Output type
|
||||
pub trait ExplicitBoundingRect<T>
|
||||
where
|
||||
T: CoordinateType,
|
||||
{
|
||||
fn bounding(&self) -> Option<Rect<T>>;
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for Polygon<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for MultiPolygon<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for LineString<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CoordinateType> ExplicitBoundingRect<T> for MultiLineString<T> {
|
||||
fn bounding(&self) -> Option<Rect<T>> {
|
||||
self.bounding_rect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> TranslateExt for B
|
||||
where
|
||||
B: ExplicitBoundingRect<f64> + Translate<f64>,
|
||||
{
|
||||
fn translate_center(&self) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn translate_center_x(&self) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let x_diff = option.max().x - option.min().x;
|
||||
let x_shift = x_diff / 2.0;
|
||||
self.translate(-(option.min().x + x_shift), 0.0)
|
||||
}
|
||||
|
||||
fn translate_center_y(&self) -> Self {
|
||||
let option = self.bounding().unwrap();
|
||||
let y_diff = option.max().y - option.min().y;
|
||||
let y_shift = y_diff / 2.0;
|
||||
self.translate(0.0, -(option.min().y + y_shift))
|
||||
}
|
||||
|
||||
fn translate_left(&self) -> Self {
|
||||
let bounding = self.bounding().unwrap();
|
||||
self.translate(-bounding.min().x, 0.)
|
||||
}
|
||||
|
||||
fn translate_top(&self) -> Self {
|
||||
let bounding = self.bounding().unwrap();
|
||||
self.translate(0., -bounding.min().y)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// https://github.com/osresearch/vst/blob/master/teensyv/asteroids_font.c
|
||||
|
||||
use geo::algorithm::translate::Translate;
|
||||
use geo::{Coordinate, LineString};
|
||||
use geo::{Coordinate, LineString, MultiLineString};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AsteroidFont {
|
||||
|
@ -112,7 +112,7 @@ impl AsteroidFont {
|
|||
text: String,
|
||||
size: f64,
|
||||
direction: FontDirection,
|
||||
) -> Vec<LineString<f64>> {
|
||||
) -> MultiLineString<f64> {
|
||||
let mut letters: Vec<LineString<f64>> = Vec::new();
|
||||
let mut count = 0.;
|
||||
for char in text.chars() {
|
||||
|
@ -130,7 +130,7 @@ impl AsteroidFont {
|
|||
}
|
||||
count = count + 1.;
|
||||
}
|
||||
letters
|
||||
MultiLineString(letters)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
mod context;
|
||||
pub use crate::context::Context;
|
||||
|
||||
mod multipolygon_ext;
|
||||
pub use crate::multipolygon_ext::MultiPolygonExt;
|
||||
mod extensions;
|
||||
pub use crate::extensions::multipolygon_ext::MultiPolygonExt;
|
||||
pub use crate::extensions::translate_ext::TranslateExt;
|
||||
|
||||
mod svg;
|
||||
pub use crate::svg::load_multipolygon_from_svg;
|
||||
|
|
|
@ -9,7 +9,7 @@ use svg::Parser;
|
|||
pub fn load_multipolygon_from_svg(path: &str) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let mut content = String::new();
|
||||
let parser = svg::open(path, &mut content)?;
|
||||
parse_svg(parser)
|
||||
parse_svg_to_multipolygon(parser)
|
||||
}
|
||||
|
||||
/// load a multipolygon statically at compiletime
|
||||
|
@ -18,11 +18,11 @@ pub fn load_multipolygon_from_svg_include(
|
|||
content: &str,
|
||||
) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let parser = svg::read(content)?;
|
||||
parse_svg(parser)
|
||||
parse_svg_to_multipolygon(parser)
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
fn parse_svg(parser: Parser) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
fn parse_svg_to_multipolygon(parser: Parser) -> Result<MultiPolygon<f64>, Box<dyn Error>> {
|
||||
let mut result: Vec<Polygon<f64>> = Vec::new();
|
||||
for event in parser {
|
||||
match event {
|
||||
|
|
Loading…
Reference in a new issue