use crate::geo_types::boolean::BooleanOp;
use crate::geo_types::buffer::Buffer;
use crate::geo_types::shapes::arc_center;
use geo::algorithm::rotate::Rotate;
use geo_types::{coord, point, Geometry, GeometryCollection, LineString, Point, Rect};
use std::collections::HashMap;
use std::error::Error;
use std::rc::Rc;
pub enum CarlsonSmithTruchet {
TLBR(bool),
DIV(bool),
DOTS(bool),
PINWHEEL(bool),
PLUS(bool),
UNHAPPY(bool),
HUGS(bool),
}
impl CarlsonSmithTruchet {
pub fn full_set() -> HashMap<String, Rc<Geometry<f64>>> {
let prefix = |x| if x { "^" } else { "" };
let mut truchets = HashMap::new();
for invert in vec![true, false] {
for i in (0..360).step_by(90) {
truchets.insert(
format!("{}TLBR{}", prefix(invert), i),
Rc::new(
CarlsonSmithTruchet::TLBR(invert)
.draw()
.unwrap()
.rotate_around_point(f64::from(i), point! {x: 0.0, y: 0.0}),
),
);
truchets.insert(
format!("{}DIV{}", prefix(invert), i),
Rc::new(
CarlsonSmithTruchet::DIV(invert)
.draw()
.unwrap()
.rotate_around_point(f64::from(i), point! {x: 0.0, y: 0.0}),
),
);
truchets.insert(
format!("{}UNHAPPY{}", prefix(invert), i),
Rc::new(
CarlsonSmithTruchet::UNHAPPY(invert)
.draw()
.unwrap()
.rotate_around_point(f64::from(i), point! {x: 0.0, y: 0.0}),
),
);
truchets.insert(
format!("{}HUGS{}", prefix(invert), i),
Rc::new(
CarlsonSmithTruchet::HUGS(invert)
.draw()
.unwrap()
.rotate_around_point(f64::from(i), point! {x: 0.0, y: 0.0}),
),
);
truchets.insert(
format!("{}DOTS{}", prefix(invert), i),
Rc::new(CarlsonSmithTruchet::DOTS(invert).draw().unwrap()),
);
truchets.insert(
format!("{}PINWHEEL{}", prefix(invert), i),
Rc::new(CarlsonSmithTruchet::PINWHEEL(invert).draw().unwrap()),
);
truchets.insert(
format!("{}PLUS{}", prefix(invert), i),
Rc::new(CarlsonSmithTruchet::PLUS(invert).draw().unwrap()),
);
}
}
truchets
}
pub fn draw(&self) -> Result<Geometry<f64>, Box<dyn Error>> {
match self {
CarlsonSmithTruchet::TLBR(false) => {
let mut ac1 = Geometry::LineString(arc_center(0.5, 0.5, 0.5, 180.0, 270.0))
.buffer(1.0f64 / 6.0f64)?; let ac2 = Geometry::LineString(arc_center(-0.5, -0.5, 0.5, 90.0, 0.0))
.buffer(1.0f64 / 6.0f64)?; ac1.0.extend(ac2.0);
Ok(Geometry::MultiPolygon(ac1))
}
CarlsonSmithTruchet::DIV(false) => Ok(Geometry::GeometryCollection(
GeometryCollection::new_from(vec![
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.0, 0.5))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.0, -0.5))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::LineString(LineString::new(vec![
coord! {x: -0.5, y: 0.0},
coord! {x: 0.5, y: 0.0},
]))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
]),
)),
CarlsonSmithTruchet::DOTS(false) => Ok(Geometry::GeometryCollection(
GeometryCollection::new_from(vec![
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.0, 0.5))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.0, -0.5))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.5, 0.0))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, -0.0))
.buffer(1.0f64 / 6.0f64)
.unwrap(),
),
]),
)),
CarlsonSmithTruchet::PINWHEEL(false) => {
let center = Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y:-0.5},
coord! {x: 0.5, y: 0.5},
));
let corners = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
let points = CarlsonSmithTruchet::DOTS(false).draw()?;
let out = center.union(&points)?.difference(&corners)?;
Ok(out)
}
CarlsonSmithTruchet::PINWHEEL(true) => Ok(Geometry::GeometryCollection(
GeometryCollection::new_from(vec![
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.5, 0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.5, -0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, 0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, -0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
]),
)),
CarlsonSmithTruchet::PLUS(false) => Ok(Geometry::MultiPolygon(
Geometry::LineString(LineString::new(vec![
coord! {x: -0.5, y: 0.0},
coord! {x: 0.5, y: 0.0},
]))
.buffer(1.0f64 / 6.0f64)?,
)
.union(&Geometry::MultiPolygon(
Geometry::LineString(LineString::new(vec![
coord! {x:0.0, y:-0.5},
coord! {x:0.0, y: 0.5},
]))
.buffer(1.0f64 / 6.0f64)?,
))?),
CarlsonSmithTruchet::UNHAPPY(false) => Ok(Geometry::GeometryCollection(
GeometryCollection::new_from(vec![
Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, 0.0)).buffer(1.0f64 / 6.0f64)?,
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.0, -0.5)).buffer(1.0f64 / 6.0f64)?,
),
Geometry::MultiPolygon(
Geometry::LineString(arc_center(0.5, 0.5, 0.5, 180.0, 270.0))
.buffer(1.0f64 / 6.0f64)?,
),
]),
)),
CarlsonSmithTruchet::HUGS(false) => {
let center = Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y: 0.5},
coord! {x: 0.5, y: -1.0/6.0},
));
let corners = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
let points = CarlsonSmithTruchet::DOTS(false).draw()?;
let out = center.union(&points)?.difference(&corners)?;
Ok(out)
}
CarlsonSmithTruchet::HUGS(true) => {
let negative = CarlsonSmithTruchet::HUGS(false).draw()?;
let positive = Geometry::GeometryCollection(GeometryCollection::new_from(vec![
Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y:-0.5},
coord! {x: 0.5, y: 0.5},
)),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.5, 0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(0.5, -0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, 0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, -0.5))
.buffer(1.0f64 / 3.0f64)
.unwrap(),
),
]))
.unary_union()?;
Ok(positive.difference(&negative)?)
}
CarlsonSmithTruchet::TLBR(true) => {
let dots = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
let line = Geometry::MultiPolygon(
Geometry::LineString(LineString(vec![
coord! {x: -0.5, y: 0.5},
coord! {x:0.5, y:-0.5},
]))
.buffer(1.0f64 / 5.0f64)?,
);
Ok(dots
.union(&line)?
.difference(&CarlsonSmithTruchet::TLBR(false).draw()?)?)
}
CarlsonSmithTruchet::DIV(true) => {
let center = Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y:-0.5},
coord! {x: 0.5, y: 0.5},
));
let corners = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
Ok(center
.union(&corners)?
.difference(&CarlsonSmithTruchet::DIV(false).draw()?)?)
}
CarlsonSmithTruchet::DOTS(true) => {
let center = Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y:-0.5},
coord! {x: 0.5, y: 0.5},
));
let corners = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
Ok(center
.union(&corners)?
.difference(&CarlsonSmithTruchet::DOTS(false).draw()?)?)
}
CarlsonSmithTruchet::PLUS(true) => {
let center = Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y:-0.5},
coord! {x: 0.5, y: 0.5},
));
let corners = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
Ok(center
.union(&corners)?
.difference(&CarlsonSmithTruchet::PLUS(false).draw()?)?)
}
CarlsonSmithTruchet::UNHAPPY(true) => {
let center = Geometry::Rect(Rect::<f64>::new(
coord! {x:-0.5, y:-0.5},
coord! {x: 0.5, y: 0.5},
));
let corners = CarlsonSmithTruchet::PINWHEEL(true).draw()?;
let ac1 = Geometry::LineString(arc_center(0.5, 0.5, 0.5, 180.0, 270.0))
.buffer(1.0f64 / 6.0f64)?; let p1 = Geometry::MultiPolygon(
Geometry::Point(Point::new(-0.5, 0.0)).buffer(1.0f64 / 6.0f64)?,
);
let p2 = Geometry::MultiPolygon(
Geometry::Point(Point::new(0.0, -0.5)).buffer(1.0f64 / 6.0f64)?,
);
Ok(center
.union(&corners)?
.difference(&Geometry::MultiPolygon(ac1))?
.difference(&p1)?
.difference(&p2)?)
}
}
}
}
#[cfg(test)]
pub mod tests {
use crate::elements::CarlsonSmithTruchet;
#[test]
fn test_cst_all() {
let _full_set = CarlsonSmithTruchet::full_set();
let _full_set = CarlsonSmithTruchet::full_set();
}
}