|
|
|
@ -56,46 +56,136 @@ pub struct Coordinate<T>(pub i32, pub i32, pub T); |
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Coordinates<T>(pub Vec<Coordinate<T>>);
|
|
|
|
|
|
|
|
impl<T> Coordinate<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Clone + Copy + From<i32> {
|
|
|
|
// Tail recursive Bresenham line with integer incremental error.
|
|
|
|
fn line(self, b :&Self) -> Vec<Self> {
|
|
|
|
fn inner<T>( v :&mut [Coordinate<T>]
|
|
|
|
, bx :i32, by :i32 |
|
|
|
, dx :i32, dy :i32 |
|
|
|
, sx :i32, sy :i32 |
|
|
|
, dz :T, err :i32)
|
|
|
|
where T: Add<Output = T> + Copy {
|
|
|
|
|
|
|
|
let Coordinate(x, y, z) = v[0];
|
|
|
|
|
|
|
|
if x != bx || y != by {
|
|
|
|
let (x, y, z, err) = match (2*err >= dy, 2*err <= dx) {
|
|
|
|
(true, false) => (x + sx, y, z + dz, err + dy ),
|
|
|
|
(false, true) => ( x, y + sy, z + dz, err + dx ),
|
|
|
|
_ => (x + sx, y + sy, z + dz, err + dx + dy ),
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct LineIterator<T> where T: Debug {
|
|
|
|
a :Option<Coordinate<T>>
|
|
|
|
, b :Coordinate<T>
|
|
|
|
, dx :i32 |
|
|
|
, dy :i32 |
|
|
|
, dzx :T
|
|
|
|
, dzy :T
|
|
|
|
, sx :i32 |
|
|
|
, sy :i32 |
|
|
|
, err :i32 |
|
|
|
, only_edges :bool |
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Iterator for LineIterator<T>
|
|
|
|
where T: Add<Output = T> + Debug + Copy + From<i32> {
|
|
|
|
type Item = Coordinate<T>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
let Coordinate(ax, ay, az) = match self.a {
|
|
|
|
None => self.b,
|
|
|
|
Some(a) => a,
|
|
|
|
};
|
|
|
|
v[1] = Coordinate(x, y, z);
|
|
|
|
inner(&mut v[1..], bx, by, dx, dy, sx, sy, dz, err);
|
|
|
|
let Coordinate(bx, by, _) = self.b;
|
|
|
|
|
|
|
|
//println!("== {:?}", self);
|
|
|
|
|
|
|
|
if ax != bx || ay != by {
|
|
|
|
match (2 * self.err >= self.dy, 2 * self.err <= self.dx ) {
|
|
|
|
(true, false) => {
|
|
|
|
let r = self.a;
|
|
|
|
self.a = Some(Coordinate(ax+self.sx, ay, az+self.dzx));
|
|
|
|
self.err = self.err + self.dy;
|
|
|
|
if self.only_edges { self.next() } else { r }
|
|
|
|
},
|
|
|
|
(false, true) => {
|
|
|
|
let r = self.a;
|
|
|
|
self.a = Some(Coordinate(ax, ay+self.sy, az+self.dzy));
|
|
|
|
self.err = self.err + self.dx;
|
|
|
|
r
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
let r = self.a;
|
|
|
|
self.a = Some(Coordinate( ax + self.sx
|
|
|
|
, ay + self.sy
|
|
|
|
, az + self.dzy ));
|
|
|
|
self.err = self.err + self.dx + self.dy;
|
|
|
|
r
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
match self.a {
|
|
|
|
None => None,
|
|
|
|
Some(a) => { self.a = None; Some(a) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Coordinate<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
fn iter(self, b :&Self, only_edges :bool) -> LineIterator<T> {
|
|
|
|
let Coordinate(ax, ay, az) = self;
|
|
|
|
let Coordinate(bx, by, bz) = *b;
|
|
|
|
|
|
|
|
let dx = (bx - ax).abs();
|
|
|
|
let sx :i32 = if ax < bx { 1 } else { -1 };
|
|
|
|
let dy = (by - ay).abs();
|
|
|
|
let sy :i32 = if ay < by { 1 } else { -1 };
|
|
|
|
let size = cmp::max(dx, dy);
|
|
|
|
let dy = -(by - ay).abs();
|
|
|
|
let size = cmp::min(dx, -dy);
|
|
|
|
let dz = (bz - az) / size.into();
|
|
|
|
|
|
|
|
let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into())
|
|
|
|
; (size as usize) + 1);
|
|
|
|
v[0] = Coordinate(ax, ay, az);
|
|
|
|
inner(&mut v, bx, by, dx, -dy, sx, sy, dz, dx - dy);
|
|
|
|
LineIterator { a: Some(self)
|
|
|
|
, b: *b
|
|
|
|
, dx: dx
|
|
|
|
, dy: dy
|
|
|
|
, dzx: if size == dx { dz } else { 0.into() }
|
|
|
|
, dzy: if size == -dy { dz } else { 0.into() }
|
|
|
|
, sx: if ax < bx { 1 } else { -1 }
|
|
|
|
, sy: if ay < by { 1 } else { -1 }
|
|
|
|
, err: dx + dy
|
|
|
|
, only_edges: only_edges
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tail recursive Bresenham line with integer incremental error.
|
|
|
|
fn line(self, b :&Self) -> Vec<Self> {
|
|
|
|
self.iter(b, false).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special line algorithm just putting the outermost x values per
|
|
|
|
* line into the resulting Vector.
|
|
|
|
* This expects y of b larger than y of self.
|
|
|
|
*/
|
|
|
|
fn edge(self, b :&Self) -> Vec<Self> {
|
|
|
|
println!("== New edge: {:?} - {:?}", self, b);
|
|
|
|
self.iter(b, true).collect()
|
|
|
|
/*
|
|
|
|
let Coordinate(mut x, mut y, mut z) = self;
|
|
|
|
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.push(*b);
|
|
|
|
v
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@ -148,7 +238,7 @@ pub struct Line<T>(pub Coordinate<T>, pub Coordinate<T>); |
|
|
|
|
|
|
|
impl<T> Drawable<T> for Line<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Clone + Copy + From<i32> {
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
fn plot(&self) -> Coordinates<T> {
|
|
|
|
let Line(a, b) = *self;
|
|
|
|
Coordinates(a.line(&b))
|
|
|
|
@ -201,7 +291,7 @@ pub struct Polyline<T>(pub Coordinates<T>); |
|
|
|
|
|
|
|
impl<T> Drawable<T> for Polyline<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Clone + Copy + From<i32> {
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
fn plot(&self) -> Coordinates<T> {
|
|
|
|
let Polyline(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
@ -235,7 +325,7 @@ pub struct Polygon<T>(pub Coordinates<T>); |
|
|
|
|
|
|
|
impl<T> Drawable<T> for Polygon<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Clone + Copy + From<i32> {
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
fn plot(&self) -> Coordinates<T> {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
@ -267,45 +357,6 @@ 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> {
|
|
|
|
@ -353,24 +404,22 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
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));
|
|
|
|
let append_edge = | v :&mut Vec<Coordinate<T>>
|
|
|
|
, e :&(usize, Option<usize>) | {
|
|
|
|
match *e {
|
|
|
|
(_, None) => *e,
|
|
|
|
(a, Some(b)) => {
|
|
|
|
println!("== l: [{:?}] - {:?}", e, cs[b]);
|
|
|
|
let mut edge = cs[a].edge(&cs[b]);
|
|
|
|
v.append(&mut edge);
|
|
|
|
(b, next_y(cs, b, &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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while l.1 != None || r.1 != None {
|
|
|
|
l = append_edge(&mut l_edge, &l);
|
|
|
|
r = append_edge(&mut r_edge, &r);
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("== [{}] {:?}", l_edge.len(), l_edge);
|
|
|
|
|