69 lines
2.3 KiB
Rust
69 lines
2.3 KiB
Rust
use crate::extensions::translate_ext::ExplicitBoundingRect;
|
|
use geo::algorithm::map_coords::MapCoords;
|
|
use geo::algorithm::translate::Translate;
|
|
use geo::{CoordinateType, LineString, MultiLineString, MultiPolygon, Polygon};
|
|
|
|
pub trait ExplicitMapCoords<T> {
|
|
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self;
|
|
}
|
|
|
|
impl<T: CoordinateType> ExplicitMapCoords<T> for LineString<T> {
|
|
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
|
self.map_coords(func)
|
|
}
|
|
}
|
|
|
|
impl<T: CoordinateType> ExplicitMapCoords<T> for MultiLineString<T> {
|
|
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
|
self.map_coords(func)
|
|
}
|
|
}
|
|
|
|
impl<T: CoordinateType> ExplicitMapCoords<T> for MultiPolygon<T> {
|
|
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
|
self.map_coords(func)
|
|
}
|
|
}
|
|
|
|
impl<T: CoordinateType> ExplicitMapCoords<T> for Polygon<T> {
|
|
fn map_coordinates(&self, func: impl Fn(&(T, T)) -> (T, T) + Copy) -> Self {
|
|
self.map_coords(func)
|
|
}
|
|
}
|
|
|
|
pub trait ScaleExt {
|
|
/// scale object
|
|
fn scale(&self, scale_x: f64, scale_y: f64) -> Self;
|
|
/// scale object to given width (in 1:1 ratio)
|
|
fn scale_to_width(&self, size: f64) -> Self;
|
|
/// scale object to given height (in 1:1 ratio)
|
|
fn scale_to_height(&self, size: f64) -> Self;
|
|
}
|
|
|
|
impl<V> ScaleExt for V
|
|
where
|
|
V: ExplicitBoundingRect<f64> + ExplicitMapCoords<f64> + Translate<f64>,
|
|
{
|
|
fn scale(&self, scale_x: f64, scale_y: f64) -> Self {
|
|
let bounding_rectangle = self.bounding().unwrap();
|
|
let minimum_coordinates = bounding_rectangle.min();
|
|
self.translate(-minimum_coordinates.x, -minimum_coordinates.y)
|
|
.map_coordinates(|&(x, y)| (x * scale_x, y * scale_y))
|
|
.translate(minimum_coordinates.x, minimum_coordinates.y)
|
|
}
|
|
|
|
fn scale_to_width(&self, size: f64) -> Self {
|
|
let option = self.bounding().unwrap();
|
|
let diff = f64::abs(option.min().x - option.max().x);
|
|
let scale = size / diff;
|
|
self.scale(scale, scale)
|
|
}
|
|
|
|
fn scale_to_height(&self, size: f64) -> Self {
|
|
let option = self.bounding().unwrap();
|
|
let diff = f64::abs(option.min().y - option.max().y);
|
|
let scale = size / diff;
|
|
self.scale(scale, scale)
|
|
}
|
|
}
|