aboutsummaryrefslogtreecommitdiff
path: root/src/element/points.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/element/points.rs')
-rw-r--r--src/element/points.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/element/points.rs b/src/element/points.rs
new file mode 100644
index 0000000..aa07de3
--- /dev/null
+++ b/src/element/points.rs
@@ -0,0 +1,125 @@
+use super::*;
+use super::{Drawable, PointCollection};
+use crate::drawing::backend::{BackendCoord, DrawingBackend, DrawingErrorKind};
+use crate::style::{ShapeStyle, SizeDesc};
+
+/// The element that used to describe a point
+pub trait PointElement<Coord, Size: SizeDesc> {
+ fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self;
+}
+
+/// Describe a cross
+pub struct Cross<Coord, Size: SizeDesc> {
+ center: Coord,
+ size: Size,
+ style: ShapeStyle,
+}
+
+impl<Coord, Size: SizeDesc> Cross<Coord, Size> {
+ pub fn new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self {
+ Self {
+ center: coord,
+ size,
+ style: style.into(),
+ }
+ }
+}
+
+impl<'a, Coord: 'a, Size: SizeDesc> PointCollection<'a, Coord> for &'a Cross<Coord, Size> {
+ type Borrow = &'a Coord;
+ type IntoIter = std::iter::Once<&'a Coord>;
+ fn point_iter(self) -> std::iter::Once<&'a Coord> {
+ std::iter::once(&self.center)
+ }
+}
+
+impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for Cross<Coord, Size> {
+ fn draw<I: Iterator<Item = BackendCoord>>(
+ &self,
+ mut points: I,
+ backend: &mut DB,
+ ps: (u32, u32),
+ ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+ if let Some((x, y)) = points.next() {
+ let size = self.size.in_pixels(&ps);
+ let (x0, y0) = (x - size, y - size);
+ let (x1, y1) = (x + size, y + size);
+ backend.draw_line((x0, y0), (x1, y1), &self.style)?;
+ backend.draw_line((x0, y1), (x1, y0), &self.style)?;
+ }
+ Ok(())
+ }
+}
+
+/// Describe a triangle marker
+pub struct TriangleMarker<Coord, Size: SizeDesc> {
+ center: Coord,
+ size: Size,
+ style: ShapeStyle,
+}
+
+impl<Coord, Size: SizeDesc> TriangleMarker<Coord, Size> {
+ pub fn new<T: Into<ShapeStyle>>(coord: Coord, size: Size, style: T) -> Self {
+ Self {
+ center: coord,
+ size,
+ style: style.into(),
+ }
+ }
+}
+
+impl<'a, Coord: 'a, Size: SizeDesc> PointCollection<'a, Coord> for &'a TriangleMarker<Coord, Size> {
+ type Borrow = &'a Coord;
+ type IntoIter = std::iter::Once<&'a Coord>;
+ fn point_iter(self) -> std::iter::Once<&'a Coord> {
+ std::iter::once(&self.center)
+ }
+}
+
+impl<Coord, DB: DrawingBackend, Size: SizeDesc> Drawable<DB> for TriangleMarker<Coord, Size> {
+ fn draw<I: Iterator<Item = BackendCoord>>(
+ &self,
+ mut points: I,
+ backend: &mut DB,
+ ps: (u32, u32),
+ ) -> Result<(), DrawingErrorKind<DB::ErrorType>> {
+ if let Some((x, y)) = points.next() {
+ let size = self.size.in_pixels(&ps);
+ let points = [-90, -210, -330]
+ .iter()
+ .map(|deg| f64::from(*deg) * std::f64::consts::PI / 180.0)
+ .map(|rad| {
+ (
+ (rad.cos() * f64::from(size) + f64::from(x)).ceil() as i32,
+ (rad.sin() * f64::from(size) + f64::from(y)).ceil() as i32,
+ )
+ });
+ backend.fill_polygon(points, &self.style.color)?;
+ }
+ Ok(())
+ }
+}
+
+impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Cross<Coord, Size> {
+ fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
+ Self::new(pos, size, style)
+ }
+}
+
+impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for TriangleMarker<Coord, Size> {
+ fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
+ Self::new(pos, size, style)
+ }
+}
+
+impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Circle<Coord, Size> {
+ fn make_point(pos: Coord, size: Size, style: ShapeStyle) -> Self {
+ Self::new(pos, size, style)
+ }
+}
+
+impl<Coord, Size: SizeDesc> PointElement<Coord, Size> for Pixel<Coord> {
+ fn make_point(pos: Coord, _: Size, style: ShapeStyle) -> Self {
+ Self::new(pos, style)
+ }
+}