canvas.rs 3.15 KB
//
// …
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

use std::fmt::{Debug, Display, Formatter, Result};
use std::ops::{Add, Div, Sub};
use std::sync::mpsc;

use super::drawable::Drawable;
use super::line_iterator::LineIterator;

// A 2D drawing surface.
pub trait Canvas<T> {
    fn init_events(&self);
    fn start_events(&self, tx :mpsc::Sender<i32>);

    fn width(&self) -> u16;
    fn height(&self) -> u16;

    fn clear(&mut self);
    fn draw(&mut self, c :&dyn Drawable<T>, color :u32);
    fn set_pixel(&mut self, c :Vertex<T>, color :u32);
    fn put_text(&self, ofs :Vertex<T>, s :&str);
    fn show(&self);
}

// A Vertex is a position on a 2D drawing surface along other stuff
// that needs to iterate between those coordinates.
#[derive(Debug, Clone, Copy)]
pub struct Vertex<T>{  x :i32   // canvas x coordinate
                    ,  y :i32   // canvas y coordinate
                    , zr :T   } // z reciprocal from 3D projection.

pub type Vertices<T> = Vec<Vertex<T>>;

impl<T> Vertex<T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
       + Debug + Clone + Copy + From<i32> {
    pub fn new(x :i32, y :i32, zr :T) -> Self {
        Vertex{x, y, zr}
    }

    #[inline]
    pub fn as_tuple(&self) -> (i32, i32, T) {
        (self.x, self.y, self.zr)
    }

    #[inline]
    pub fn same_column(&self, b :&Self) -> bool {
        self.x == b.x
    }

    #[inline]
    pub fn same_line(&self, b :&Self) -> bool {
        self.y == b.y
    }

    #[inline]
    pub fn same_position(&self, b :&Self) -> bool {
        self.same_column(b) && self.same_line(b)
    }

    fn iter(self, b :Self, only_edges :bool) -> LineIterator<T> {
        LineIterator::new(self, b, only_edges)
    }

    pub fn line_iter(self, b :Self) -> LineIterator<T> {
        self.iter(b, false)
    }

    pub fn line(self, b :Self) -> Vec<Self> {
        self.line_iter(b).collect()
    }

    pub fn edge_iter(self, b :Self) -> LineIterator<T> {
        self.iter(b, true)
    }

    fn edge(self, b :Self) -> Vec<Self> {
        self.edge_iter(b).collect()
    }

    fn face(edges :&[Self]) -> Vec<Self> {
        edges.to_vec()
    }
}

impl<T> Display for Vertex<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        write!(f, "<{},{}>", self.x, self.y)
    }
}

impl<T> Add for Vertex<T> where T: Add<Output=T> {
    type Output = Self;

    fn add(self, other :Self) -> Vertex<T> {
        Vertex{  x: self.x  + other.x
              ,  y: self.y  + other.y
              , zr: self.zr + other.zr }
    }
}