Commit 8f0edfaa14775e387ad3cbf852ce94e90a589790

Authored by Georg Hopp
1 parent 721b89a1

Start making an iterator from the line algorithm

No preview for this file type
... ... @@ -56,46 +56,136 @@ pub struct Coordinate<T>(pub i32, pub i32, pub T);
56 56 #[derive(Debug, Clone)]
57 57 pub struct Coordinates<T>(pub Vec<Coordinate<T>>);
58 58
  59 +#[derive(Debug, Clone)]
  60 +pub struct LineIterator<T> where T: Debug {
  61 + a :Option<Coordinate<T>>
  62 + , b :Coordinate<T>
  63 + , dx :i32
  64 + , dy :i32
  65 + , dzx :T
  66 + , dzy :T
  67 + , sx :i32
  68 + , sy :i32
  69 + , err :i32
  70 + , only_edges :bool
  71 +}
  72 +
  73 +impl<T> Iterator for LineIterator<T>
  74 +where T: Add<Output = T> + Debug + Copy + From<i32> {
  75 + type Item = Coordinate<T>;
  76 +
  77 + fn next(&mut self) -> Option<Self::Item> {
  78 + let Coordinate(ax, ay, az) = match self.a {
  79 + None => self.b,
  80 + Some(a) => a,
  81 + };
  82 + let Coordinate(bx, by, _) = self.b;
  83 +
  84 + //println!("== {:?}", self);
  85 +
  86 + if ax != bx || ay != by {
  87 + match (2 * self.err >= self.dy, 2 * self.err <= self.dx ) {
  88 + (true, false) => {
  89 + let r = self.a;
  90 + self.a = Some(Coordinate(ax+self.sx, ay, az+self.dzx));
  91 + self.err = self.err + self.dy;
  92 + if self.only_edges { self.next() } else { r }
  93 + },
  94 + (false, true) => {
  95 + let r = self.a;
  96 + self.a = Some(Coordinate(ax, ay+self.sy, az+self.dzy));
  97 + self.err = self.err + self.dx;
  98 + r
  99 + },
  100 + _ => {
  101 + let r = self.a;
  102 + self.a = Some(Coordinate( ax + self.sx
  103 + , ay + self.sy
  104 + , az + self.dzy ));
  105 + self.err = self.err + self.dx + self.dy;
  106 + r
  107 + },
  108 + }
  109 + } else {
  110 + match self.a {
  111 + None => None,
  112 + Some(a) => { self.a = None; Some(a) }
  113 + }
  114 + }
  115 + }
  116 +}
  117 +
59 118 impl<T> Coordinate<T>
60 119 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
61   - + Clone + Copy + From<i32> {
  120 + + Debug + Clone + Copy + From<i32> {
  121 + fn iter(self, b :&Self, only_edges :bool) -> LineIterator<T> {
  122 + let Coordinate(ax, ay, az) = self;
  123 + let Coordinate(bx, by, bz) = *b;
  124 +
  125 + let dx = (bx - ax).abs();
  126 + let dy = -(by - ay).abs();
  127 + let size = cmp::min(dx, -dy);
  128 + let dz = (bz - az) / size.into();
  129 +
  130 + LineIterator { a: Some(self)
  131 + , b: *b
  132 + , dx: dx
  133 + , dy: dy
  134 + , dzx: if size == dx { dz } else { 0.into() }
  135 + , dzy: if size == -dy { dz } else { 0.into() }
  136 + , sx: if ax < bx { 1 } else { -1 }
  137 + , sy: if ay < by { 1 } else { -1 }
  138 + , err: dx + dy
  139 + , only_edges: only_edges
  140 + }
  141 + }
  142 +
62 143 // Tail recursive Bresenham line with integer incremental error.
63 144 fn line(self, b :&Self) -> Vec<Self> {
64   - fn inner<T>( v :&mut [Coordinate<T>]
65   - , bx :i32, by :i32
66   - , dx :i32, dy :i32
67   - , sx :i32, sy :i32
68   - , dz :T, err :i32)
69   - where T: Add<Output = T> + Copy {
70   -
71   - let Coordinate(x, y, z) = v[0];
72   -
73   - if x != bx || y != by {
74   - let (x, y, z, err) = match (2*err >= dy, 2*err <= dx) {
75   - (true, false) => (x + sx, y, z + dz, err + dy ),
76   - (false, true) => ( x, y + sy, z + dz, err + dx ),
77   - _ => (x + sx, y + sy, z + dz, err + dx + dy ),
78   - };
79   - v[1] = Coordinate(x, y, z);
80   - inner(&mut v[1..], bx, by, dx, dy, sx, sy, dz, err);
  145 + self.iter(b, false).collect()
  146 + }
  147 +
  148 + /*
  149 + * Special line algorithm just putting the outermost x values per
  150 + * line into the resulting Vector.
  151 + * This expects y of b larger than y of self.
  152 + */
  153 + fn edge(self, b :&Self) -> Vec<Self> {
  154 + println!("== New edge: {:?} - {:?}", self, b);
  155 + self.iter(b, true).collect()
  156 + /*
  157 + let Coordinate(mut x, mut y, mut z) = self;
  158 + let Coordinate( bx, by, bz) = *b;
  159 +
  160 + // next should be called with the negative of this… but dz depends
  161 + // on the positive this.
  162 + let dy = -(by - y).abs();
  163 + let dx = (bx - x).abs();
  164 + let sx = if x < bx { 1 } else { -1 };
  165 + let dz = (bz - z) / (-dy).into();
  166 + let mut err = dx + dy;
  167 +
  168 + let mut v = Vec::<Coordinate<T>>::with_capacity((-dy) as usize);
  169 +
  170 + while y != by {
  171 + match (2*err >= dy, 2*err <= dx) {
  172 + (true, false) => { x = x + sx
  173 + ; err = err + dy },
  174 + (false, true) => { v.push(Coordinate(x, y, z))
  175 + ; y = y + 1
  176 + ; z = z + dz
  177 + ; err = err + dx },
  178 + _ => { v.push(Coordinate(x, y, z))
  179 + ; x = x + sx
  180 + ; y = y + 1
  181 + ; z = z + dz
  182 + ; err = err + dx + dy },
81 183 }
82 184 }
83 185
84   - let Coordinate(ax, ay, az) = self;
85   - let Coordinate(bx, by, bz) = *b;
86   -
87   - let dx = (bx - ax).abs();
88   - let sx :i32 = if ax < bx { 1 } else { -1 };
89   - let dy = (by - ay).abs();
90   - let sy :i32 = if ay < by { 1 } else { -1 };
91   - let size = cmp::max(dx, dy);
92   - let dz = (bz - az) / size.into();
93   -
94   - let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into())
95   - ; (size as usize) + 1);
96   - v[0] = Coordinate(ax, ay, az);
97   - inner(&mut v, bx, by, dx, -dy, sx, sy, dz, dx - dy);
  186 + v.push(*b);
98 187 v
  188 + */
99 189 }
100 190 }
101 191
... ... @@ -148,7 +238,7 @@ pub struct Line<T>(pub Coordinate<T>, pub Coordinate<T>);
148 238
149 239 impl<T> Drawable<T> for Line<T>
150 240 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
151   - + Clone + Copy + From<i32> {
  241 + + Debug + Clone + Copy + From<i32> {
152 242 fn plot(&self) -> Coordinates<T> {
153 243 let Line(a, b) = *self;
154 244 Coordinates(a.line(&b))
... ... @@ -201,7 +291,7 @@ pub struct Polyline<T>(pub Coordinates<T>);
201 291
202 292 impl<T> Drawable<T> for Polyline<T>
203 293 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
204   - + Clone + Copy + From<i32> {
  294 + + Debug + Clone + Copy + From<i32> {
205 295 fn plot(&self) -> Coordinates<T> {
206 296 let Polyline(Coordinates(cs)) = self;
207 297
... ... @@ -235,7 +325,7 @@ pub struct Polygon<T>(pub Coordinates<T>);
235 325
236 326 impl<T> Drawable<T> for Polygon<T>
237 327 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
238   - + Clone + Copy + From<i32> {
  328 + + Debug + Clone + Copy + From<i32> {
239 329 fn plot(&self) -> Coordinates<T> {
240 330 let Polygon(Coordinates(cs)) = self;
241 331
... ... @@ -267,45 +357,6 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
267 357 + Debug + Clone + Copy + From<i32> {
268 358 fn fill(&self) -> Coordinates<T> {
269 359
270   - /* bresenham kind of thing to get the outer x values for each y of one
271   - * edge of the polygon. */
272   - fn walk_edge<T>( a :Coordinate<T>
273   - , b :Coordinate<T> ) -> Vec<Coordinate<T>>
274   - where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
275   - + From<i32> + Debug + Copy {
276   -
277   - let Coordinate(mut x, mut y, mut z) = a;
278   - let Coordinate( bx, by, bz) = b;
279   -
280   - // next should be called with the negative of this… but dz depends
281   - // on the positive this.
282   - let dy = -(by - y).abs();
283   - let dx = (bx - x).abs();
284   - let sx = if x < bx { 1 } else { -1 };
285   - let dz = (bz - z) / (-dy).into();
286   - let mut err = dx + dy;
287   -
288   - let mut v = Vec::<Coordinate<T>>::with_capacity((-dy) as usize);
289   -
290   - while y != by {
291   - match (2*err >= dy, 2*err <= dx) {
292   - (true, false) => { x = x + sx
293   - ; err = err + dy },
294   - (false, true) => { v.push(Coordinate(x, y, z))
295   - ; y = y + 1
296   - ; z = z + dz
297   - ; err = err + dx },
298   - _ => { v.push(Coordinate(x, y, z))
299   - ; x = x + sx
300   - ; y = y + 1
301   - ; z = z + dz
302   - ; err = err + dx + dy },
303   - }
304   - }
305   -
306   - v
307   - }
308   -
309 360 fn next_y<T>( cs :&[Coordinate<T>]
310 361 , c :usize
311 362 , f :&dyn Fn(usize) -> usize) -> Option<usize> {
... ... @@ -353,24 +404,22 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
353 404 let mut l_edge :Vec<Coordinate<T>> = Vec::new();
354 405 let mut r_edge :Vec<Coordinate<T>> = Vec::new();
355 406
356   - while l.1 != None || r.1 != None {
357   - match l.1 {
358   - None => {},
359   - Some(a) => {
360   - println!("== l: [{:?}] - {:?}", l, cs[a]);
361   - l_edge.append(&mut walk_edge(cs[l.0], cs[a]));
362   - l = (a, next_y(cs, a, &left));
  407 + let append_edge = | v :&mut Vec<Coordinate<T>>
  408 + , e :&(usize, Option<usize>) | {
  409 + match *e {
  410 + (_, None) => *e,
  411 + (a, Some(b)) => {
  412 + println!("== l: [{:?}] - {:?}", e, cs[b]);
  413 + let mut edge = cs[a].edge(&cs[b]);
  414 + v.append(&mut edge);
  415 + (b, next_y(cs, b, &left))
363 416 },
364 417 }
  418 + };
365 419
366   - match r.1 {
367   - None => {},
368   - Some(a) => {
369   - println!("== r: [{:?}] - {:?}", r, cs[a]);
370   - r_edge.append(&mut walk_edge(cs[r.0], cs[a]));
371   - r = (a, next_y(cs, a, &right));
372   - }
373   - }
  420 + while l.1 != None || r.1 != None {
  421 + l = append_edge(&mut l_edge, &l);
  422 + r = append_edge(&mut r_edge, &r);
374 423 }
375 424
376 425 println!("== [{}] {:?}", l_edge.len(), l_edge);
... ...
... ... @@ -379,11 +379,11 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
379 379 None
380 380 }};
381 381
382   - let ps :Vec<(Polygon<T>, u32)> = self.faces.iter()
  382 + let mut ps :Vec<(Polygon<T>, u32)> = self.faces.iter()
383 383 . filter_map(to_poly).collect();
384 384 // this sorts by the color value which is no longer neccessary as soon
385 385 // as the z-buffer is complete.
386   - // ps.sort_by(|a, b| a.1.cmp(&b.1));
  386 + ps.sort_by(|a, b| a.1.cmp(&b.1));
387 387 ps
388 388 }
389 389 }
... ...
Please register or login to post a comment