|
|
@ -21,7 +21,7 @@ |
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
//
|
|
|
//
|
|
|
use std::cmp;
|
|
|
use std::cmp;
|
|
|
use std::fmt::{Formatter, Display, Result};
|
|
|
|
|
|
|
|
|
use std::fmt::{Formatter, Debug, Display, Result};
|
|
|
use std::ops::{Add, Sub, Div};
|
|
|
use std::ops::{Add, Sub, Div};
|
|
|
use std::sync::mpsc;
|
|
|
use std::sync::mpsc;
|
|
|
|
|
|
|
|
|
@ -46,6 +46,10 @@ pub trait Drawable<T> { |
|
|
fn plot(&self) -> Coordinates<T>;
|
|
|
fn plot(&self) -> Coordinates<T>;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub trait Fillable<T> {
|
|
|
|
|
|
fn fill(&self) -> Coordinates<T>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
pub struct Coordinate<T>(pub i32, pub i32, pub T);
|
|
|
pub struct Coordinate<T>(pub i32, pub i32, pub T);
|
|
|
|
|
|
|
|
|
@ -82,15 +86,15 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
|
|
|
|
|
let dx = (bx - ax).abs();
|
|
|
let dx = (bx - ax).abs();
|
|
|
let sx :i32 = if ax < bx { 1 } else { -1 };
|
|
|
let sx :i32 = if ax < bx { 1 } else { -1 };
|
|
|
let dy = -(by - ay).abs();
|
|
|
|
|
|
|
|
|
let dy = (by - ay).abs();
|
|
|
let sy :i32 = if ay < by { 1 } else { -1 };
|
|
|
let sy :i32 = if ay < by { 1 } else { -1 };
|
|
|
let size = cmp::max(dx, -dy);
|
|
|
|
|
|
|
|
|
let size = cmp::max(dx, dy);
|
|
|
let dz = (bz - az) / size.into();
|
|
|
let dz = (bz - az) / size.into();
|
|
|
|
|
|
|
|
|
let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into())
|
|
|
let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into())
|
|
|
; (size as usize) + 1);
|
|
|
; (size as usize) + 1);
|
|
|
v[0] = Coordinate(ax, ay, az);
|
|
|
v[0] = Coordinate(ax, ay, az);
|
|
|
inner(&mut v, bx, by, dx, dy, sx, sy, dz, dx + dy);
|
|
|
|
|
|
|
|
|
inner(&mut v, bx, by, dx, -dy, sx, sy, dz, dx - dy);
|
|
|
v
|
|
|
v
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@ -258,6 +262,129 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> Fillable<T> for Polygon<T>
|
|
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
|
|
fn fill(&self) -> Coordinates<T> {
|
|
|
|
|
|
|
|
|
|
|
|
/* bresenham kind of thing to get the outer x values for each y of one
|
|
|
|
|
|
* edge of the polygon. */
|
|
|
|
|
|
fn walk_edge<T>( a :Coordinate<T>
|
|
|
|
|
|
, b :Coordinate<T> ) -> Vec<Coordinate<T>>
|
|
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
|
|
+ From<i32> + Debug + Copy {
|
|
|
|
|
|
|
|
|
|
|
|
let Coordinate(mut x, mut y, mut z) = a;
|
|
|
|
|
|
let Coordinate( bx, by, bz) = b;
|
|
|
|
|
|
|
|
|
|
|
|
// next should be called with the negative of this… but dz depends
|
|
|
|
|
|
// on the positive this.
|
|
|
|
|
|
let dy = -(by - y).abs();
|
|
|
|
|
|
let dx = (bx - x).abs();
|
|
|
|
|
|
let sx = if x < bx { 1 } else { -1 };
|
|
|
|
|
|
let dz = (bz - z) / (-dy).into();
|
|
|
|
|
|
let mut err = dx + dy;
|
|
|
|
|
|
|
|
|
|
|
|
let mut v = Vec::<Coordinate<T>>::with_capacity((-dy) as usize);
|
|
|
|
|
|
|
|
|
|
|
|
while y != by {
|
|
|
|
|
|
match (2*err >= dy, 2*err <= dx) {
|
|
|
|
|
|
(true, false) => { x = x + sx
|
|
|
|
|
|
; err = err + dy },
|
|
|
|
|
|
(false, true) => { v.push(Coordinate(x, y, z))
|
|
|
|
|
|
; y = y + 1
|
|
|
|
|
|
; z = z + dz
|
|
|
|
|
|
; err = err + dx },
|
|
|
|
|
|
_ => { v.push(Coordinate(x, y, z))
|
|
|
|
|
|
; x = x + sx
|
|
|
|
|
|
; y = y + 1
|
|
|
|
|
|
; z = z + dz
|
|
|
|
|
|
; err = err + dx + dy },
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
v
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn next_y<T>( cs :&[Coordinate<T>]
|
|
|
|
|
|
, c :usize |
|
|
|
|
|
, f :&dyn Fn(usize) -> usize) -> Option<usize> {
|
|
|
|
|
|
fn inner<T>( cs :&[Coordinate<T>]
|
|
|
|
|
|
, c :usize |
|
|
|
|
|
, n :usize |
|
|
|
|
|
, f :&dyn Fn(usize) -> usize) -> Option<usize> {
|
|
|
|
|
|
if c == n {
|
|
|
|
|
|
None
|
|
|
|
|
|
} else {
|
|
|
|
|
|
let Coordinate(_, cy, _) = cs[c];
|
|
|
|
|
|
let Coordinate(_, ny, _) = cs[n];
|
|
|
|
|
|
|
|
|
|
|
|
match ny.cmp(&cy) {
|
|
|
|
|
|
cmp::Ordering::Less => None,
|
|
|
|
|
|
cmp::Ordering::Equal => inner(cs, c, f(n), f),
|
|
|
|
|
|
cmp::Ordering::Greater => Some(n),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inner(cs, c, f(c), f)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
|
|
|
|
let vert_min = cs.iter().enumerate()
|
|
|
|
|
|
. fold( None
|
|
|
|
|
|
, |acc, x| match acc {
|
|
|
|
|
|
None => Some(x),
|
|
|
|
|
|
Some(a) => {
|
|
|
|
|
|
let Coordinate(_, ay, _) = a.1;
|
|
|
|
|
|
let Coordinate(_, xy, _) = x.1;
|
|
|
|
|
|
if xy < ay {Some(x)} else {Some(a)} } } )
|
|
|
|
|
|
. unwrap().0;
|
|
|
|
|
|
|
|
|
|
|
|
println!("== vert_min: [{:?}] - {:?}", vert_min, cs[vert_min]);
|
|
|
|
|
|
|
|
|
|
|
|
let right = |x :usize| (x + 1) % cs.len();
|
|
|
|
|
|
let left = |x :usize| if x == 0 { cs.len() - 1 } else { x - 1 };
|
|
|
|
|
|
|
|
|
|
|
|
let mut r = (vert_min, next_y(cs, vert_min, &right));
|
|
|
|
|
|
let mut l = (vert_min, next_y(cs, vert_min, &left));
|
|
|
|
|
|
|
|
|
|
|
|
let mut l_edge :Vec<Coordinate<T>> = Vec::new();
|
|
|
|
|
|
let mut r_edge :Vec<Coordinate<T>> = Vec::new();
|
|
|
|
|
|
|
|
|
|
|
|
while l.1 != None || r.1 != None {
|
|
|
|
|
|
match l.1 {
|
|
|
|
|
|
None => {},
|
|
|
|
|
|
Some(a) => {
|
|
|
|
|
|
println!("== l: [{:?}] - {:?}", l, cs[a]);
|
|
|
|
|
|
l_edge.append(&mut walk_edge(cs[l.0], cs[a]));
|
|
|
|
|
|
l = (a, next_y(cs, a, &left));
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
match r.1 {
|
|
|
|
|
|
None => {},
|
|
|
|
|
|
Some(a) => {
|
|
|
|
|
|
println!("== r: [{:?}] - {:?}", r, cs[a]);
|
|
|
|
|
|
r_edge.append(&mut walk_edge(cs[r.0], cs[a]));
|
|
|
|
|
|
r = (a, next_y(cs, a, &right));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
println!("== [{}] {:?}", l_edge.len(), l_edge);
|
|
|
|
|
|
println!("== [{}] {:?}", r_edge.len(), r_edge);
|
|
|
|
|
|
|
|
|
|
|
|
// TODO we always miss the last scanline…
|
|
|
|
|
|
// TODO check what happend with at least 2 vertices with same y and
|
|
|
|
|
|
// different x…
|
|
|
|
|
|
// loop though edges…
|
|
|
|
|
|
|
|
|
|
|
|
Coordinates(Vec::<Coordinate<T>>::new())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<T> Display for Polygon<T> where T: Copy {
|
|
|
impl<T> Display for Polygon<T> where T: Copy {
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
|
|
let Polygon(a) = self;
|
|
|
let Polygon(a) = self;
|
|
|
|