|
|
|
@ -62,8 +62,7 @@ pub struct LineIterator<T> where T: Debug { |
|
|
|
, b :Coordinate<T>
|
|
|
|
, dx :i32 |
|
|
|
, dy :i32 |
|
|
|
, dzx :T
|
|
|
|
, dzy :T
|
|
|
|
, dz :T
|
|
|
|
, sx :i32 |
|
|
|
, sy :i32 |
|
|
|
, err :i32 |
|
|
|
@ -75,41 +74,43 @@ 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,
|
|
|
|
};
|
|
|
|
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) }
|
|
|
|
match self.a {
|
|
|
|
None => None,
|
|
|
|
Some(a) => {
|
|
|
|
let Coordinate(ax, ay, az) = a;
|
|
|
|
let Coordinate(bx, by, _) = self.b;
|
|
|
|
|
|
|
|
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.dz ));
|
|
|
|
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.dz ));
|
|
|
|
self.err = self.err + self.dx;
|
|
|
|
r
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
let r = self.a;
|
|
|
|
self.a = Some(Coordinate( ax + self.sx
|
|
|
|
, ay + self.sy
|
|
|
|
, az + self.dz ));
|
|
|
|
self.err = self.err + self.dx + self.dy;
|
|
|
|
r
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.a = None;
|
|
|
|
Some(self.b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -122,17 +123,14 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
let Coordinate(ax, ay, az) = self;
|
|
|
|
let Coordinate(bx, by, bz) = *b;
|
|
|
|
|
|
|
|
let dx = (bx - ax).abs();
|
|
|
|
let dy = -(by - ay).abs();
|
|
|
|
let size = cmp::min(dx, -dy);
|
|
|
|
let dz = (bz - az) / size.into();
|
|
|
|
let dx = (bx - ax).abs();
|
|
|
|
let dy = -(by - ay).abs();
|
|
|
|
|
|
|
|
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() }
|
|
|
|
, dz: (bz - az) / cmp::max(dx, -dy).into()
|
|
|
|
, sx: if ax < bx { 1 } else { -1 }
|
|
|
|
, sy: if ay < by { 1 } else { -1 }
|
|
|
|
, err: dx + dy
|
|
|
|
@ -140,52 +138,20 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tail recursive Bresenham line with integer incremental error.
|
|
|
|
fn line_iter(self, b :&Self) -> LineIterator<T> {
|
|
|
|
self.iter(b, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn line(self, b :&Self) -> Vec<Self> {
|
|
|
|
self.iter(b, false).collect()
|
|
|
|
self.line_iter(b).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 },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn edge_iter(self, b :&Self) -> LineIterator<T> {
|
|
|
|
self.iter(b, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
v.push(*b);
|
|
|
|
v
|
|
|
|
*/
|
|
|
|
fn edge(self, b :&Self) -> Vec<Self> {
|
|
|
|
self.edge_iter(b).collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@ -252,40 +218,6 @@ impl<T> Display for Line<T> { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// In 3D a rectangle is not as trivial as in 2D, it might be somehow rotate
|
|
|
|
// and thus we need to specify a Z offset for the other two corners.
|
|
|
|
// As I do not need rectangle at all I just comment out this code for now.
|
|
|
|
/*
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub struct Rectangle<T>(pub Coordinate<T>, pub Coordinate<T>);
|
|
|
|
|
|
|
|
impl<T> Drawable<T> for Rectangle<T> {
|
|
|
|
fn plot(&self) -> Coordinates<T> {
|
|
|
|
let Rectangle(a, c) = *self;
|
|
|
|
let Coordinate(ax, ay, az) = a;
|
|
|
|
let Coordinate(cx, cy, cz) = c;
|
|
|
|
let b = Coordinate(cx, ay);
|
|
|
|
let d = Coordinate(ax, cy);
|
|
|
|
|
|
|
|
let mut r = a.line(&b);
|
|
|
|
r.append(&mut b.line(&c)[1..].to_vec());
|
|
|
|
r.append(&mut c.line(&d)[1..].to_vec());
|
|
|
|
let mut i = d.line(&a);
|
|
|
|
let l = i.len();
|
|
|
|
r.append(&mut i[1..l-1].to_vec());
|
|
|
|
|
|
|
|
Coordinates(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Rectangle {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
|
|
|
let Rectangle(a, b) = self;
|
|
|
|
write!(f, "Rec[{},{}]", a, b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Polyline<T>(pub Coordinates<T>);
|
|
|
|
|
|
|
|
@ -320,9 +252,126 @@ impl<T> Display for Polyline<T> where T: Copy { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
enum Direction { Left, Right }
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct Polygon<T>(pub Coordinates<T>);
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct VertexIterator<'a,T> where T: Debug {
|
|
|
|
p :&'a Polygon<T>,
|
|
|
|
top :usize,
|
|
|
|
current :Option<usize>,
|
|
|
|
inner :Option<LineIterator<T>>,
|
|
|
|
direction :Direction,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a,T> Iterator for VertexIterator<'a,T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Debug + Copy + From<i32> {
|
|
|
|
type Item = Coordinate<T>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
let inner = match self.inner {
|
|
|
|
Some(i) => i,
|
|
|
|
None => {
|
|
|
|
let current = self.current?;
|
|
|
|
let next = self.p.next_y(current, self.direction)?;
|
|
|
|
self.p.vertex(current).edge_iter(&self.p.vertex(next))
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
match self.current {
|
|
|
|
None => None,
|
|
|
|
Some(c) => {
|
|
|
|
let r = self.p.vertex(c);
|
|
|
|
self.current = self.p.next_y(c, self.direction);
|
|
|
|
Some(r)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Polygon<T> where T: Copy + Debug {
|
|
|
|
fn vert_min<'a>(&'a self) -> usize {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
type ICoord<'a,T> = (usize, &'a Coordinate<T>);
|
|
|
|
|
|
|
|
let fold = | acc :Option<ICoord<'a,T>>, x :ICoord<'a,T> |
|
|
|
|
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)}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
cs.iter().enumerate().fold(None, fold).unwrap().0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn left_vertices(&self) -> VertexIterator<T> {
|
|
|
|
VertexIterator { p: &self
|
|
|
|
, top: self.vert_min()
|
|
|
|
, current: Some(self.vert_min())
|
|
|
|
, inner: None |
|
|
|
, direction: Direction::Left }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn left(&self, v :usize) -> usize {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
match v {
|
|
|
|
0 => cs.len() - 1,
|
|
|
|
_ => v - 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn right(&self, v :usize) -> usize {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
|
|
|
|
(v + 1) % cs.len()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn step(&self, v :usize, d :Direction) -> usize {
|
|
|
|
match d {
|
|
|
|
Direction::Left => self.left(v),
|
|
|
|
Direction::Right => self.right(v),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn vertex(&self, v :usize) -> Coordinate<T> {
|
|
|
|
let Polygon(Coordinates(cs)) = self;
|
|
|
|
cs[v]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn next_y(&self, c :usize, d :Direction) -> Option<usize> {
|
|
|
|
fn inner<T>( p :&Polygon<T>
|
|
|
|
, c :usize |
|
|
|
, n :usize |
|
|
|
, d :Direction) -> Option<usize>
|
|
|
|
where T: Copy + Debug {
|
|
|
|
if c == n {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let Coordinate(_, cy, _) = p.vertex(c);
|
|
|
|
let Coordinate(_, ny, _) = p.vertex(n);
|
|
|
|
|
|
|
|
match ny.cmp(&cy) {
|
|
|
|
cmp::Ordering::Less => None,
|
|
|
|
cmp::Ordering::Equal => inner(p, c, p.step(n, d), d),
|
|
|
|
cmp::Ordering::Greater => Some(n),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inner(self, c, self.step(c, d), d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Drawable<T> for Polygon<T>
|
|
|
|
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
|
|
|
|
+ Debug + Clone + Copy + From<i32> {
|
|
|
|
@ -356,70 +405,45 @@ 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> {
|
|
|
|
|
|
|
|
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 vert_min = self.vert_min();
|
|
|
|
|
|
|
|
let right = |x :usize| (x + 1) % cs.len();
|
|
|
|
let left = |x :usize| if x == 0 { cs.len() - 1 } else { x - 1 };
|
|
|
|
println!("== vert_min: [{}] {:?}", vert_min, cs[vert_min]);
|
|
|
|
|
|
|
|
let mut r = (vert_min, next_y(cs, vert_min, &right));
|
|
|
|
let mut l = (vert_min, next_y(cs, vert_min, &left));
|
|
|
|
let mut r = (vert_min, self.next_y(vert_min, Direction::Right));
|
|
|
|
let mut l = (vert_min, self.next_y(vert_min, Direction::Left));
|
|
|
|
|
|
|
|
let mut l_edge :Vec<Coordinate<T>> = Vec::new();
|
|
|
|
let mut r_edge :Vec<Coordinate<T>> = Vec::new();
|
|
|
|
|
|
|
|
let append_edge = | v :&mut Vec<Coordinate<T>>
|
|
|
|
, e :&(usize, Option<usize>) | {
|
|
|
|
match *e {
|
|
|
|
(_, None) => *e,
|
|
|
|
, e :(usize, Option<usize>)
|
|
|
|
, f :Direction | {
|
|
|
|
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))
|
|
|
|
(b, self.next_y(b, f))
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let print_current = |s :&str, e :(usize, Option<usize>)| {
|
|
|
|
match e.1 {
|
|
|
|
None => println!( "== {}: [{:?}] - {:?}"
|
|
|
|
, s, e.1, "None"),
|
|
|
|
Some(e) => println!( "== {}: [{:?}] - {:?}"
|
|
|
|
, s, e, cs[e]),
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
while l.1 != None || r.1 != None {
|
|
|
|
l = append_edge(&mut l_edge, &l);
|
|
|
|
r = append_edge(&mut r_edge, &r);
|
|
|
|
print_current("l", l);
|
|
|
|
l = append_edge(&mut l_edge, l, Direction::Left);
|
|
|
|
print_current("r", r);
|
|
|
|
r = append_edge(&mut r_edge, r, Direction::Right);
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("== [{}] {:?}", l_edge.len(), l_edge);
|
|
|
|
|