Browse Source

Start making an iterator from the line algorithm

master
Georg Hopp 6 years ago
parent
commit
8f0edfaa14
Signed by: ghopp GPG Key ID: 4C5D226768784538
  1. BIN
      fractional/.swp
  2. 221
      fractional/src/easel.rs
  3. 4
      fractional/src/geometry.rs

BIN
fractional/.swp

221
fractional/src/easel.rs

@ -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);

4
fractional/src/geometry.rs

@ -379,11 +379,11 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
None
}};
let ps :Vec<(Polygon<T>, u32)> = self.faces.iter()
let mut ps :Vec<(Polygon<T>, u32)> = self.faces.iter()
. filter_map(to_poly).collect();
// this sorts by the color value which is no longer neccessary as soon
// as the z-buffer is complete.
// ps.sort_by(|a, b| a.1.cmp(&b.1));
ps.sort_by(|a, b| a.1.cmp(&b.1));
ps
}
}
Loading…
Cancel
Save