Commit 29c366d709d8e31ae0f16d9f2a18b9e7aeab6147

Authored by Georg Hopp
1 parent 8f0edfaa

More iterators

Showing 1 changed file with 190 additions and 166 deletions
@@ -62,8 +62,7 @@ pub struct LineIterator<T> where T: Debug { @@ -62,8 +62,7 @@ pub struct LineIterator<T> where T: Debug {
62 , b :Coordinate<T> 62 , b :Coordinate<T>
63 , dx :i32 63 , dx :i32
64 , dy :i32 64 , dy :i32
65 - , dzx :T  
66 - , dzy :T 65 + , dz :T
67 , sx :i32 66 , sx :i32
68 , sy :i32 67 , sy :i32
69 , err :i32 68 , err :i32
@@ -75,41 +74,43 @@ where T: Add<Output = T> + Debug + Copy + From<i32> { @@ -75,41 +74,43 @@ where T: Add<Output = T> + Debug + Copy + From<i32> {
75 type Item = Coordinate<T>; 74 type Item = Coordinate<T>;
76 75
77 fn next(&mut self) -> Option<Self::Item> { 76 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) } 77 + match self.a {
  78 + None => None,
  79 + Some(a) => {
  80 + let Coordinate(ax, ay, az) = a;
  81 + let Coordinate(bx, by, _) = self.b;
  82 +
  83 + if ax != bx || ay != by {
  84 + match (2 * self.err >= self.dy, 2 * self.err <= self.dx ) {
  85 + (true, false) => {
  86 + let r = self.a;
  87 + self.a = Some(Coordinate( ax + self.sx
  88 + , ay
  89 + , az + self.dz ));
  90 + self.err = self.err + self.dy;
  91 + if self.only_edges { self.next() } else { r }
  92 + },
  93 + (false, true) => {
  94 + let r = self.a;
  95 + self.a = Some(Coordinate( ax
  96 + , ay + self.sy
  97 + , az + self.dz ));
  98 + self.err = self.err + self.dx;
  99 + r
  100 + },
  101 + _ => {
  102 + let r = self.a;
  103 + self.a = Some(Coordinate( ax + self.sx
  104 + , ay + self.sy
  105 + , az + self.dz ));
  106 + self.err = self.err + self.dx + self.dy;
  107 + r
  108 + },
  109 + }
  110 + } else {
  111 + self.a = None;
  112 + Some(self.b)
  113 + }
113 } 114 }
114 } 115 }
115 } 116 }
@@ -122,17 +123,14 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> @@ -122,17 +123,14 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
122 let Coordinate(ax, ay, az) = self; 123 let Coordinate(ax, ay, az) = self;
123 let Coordinate(bx, by, bz) = *b; 124 let Coordinate(bx, by, bz) = *b;
124 125
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(); 126 + let dx = (bx - ax).abs();
  127 + let dy = -(by - ay).abs();
129 128
130 LineIterator { a: Some(self) 129 LineIterator { a: Some(self)
131 , b: *b 130 , b: *b
132 , dx: dx 131 , dx: dx
133 , dy: dy 132 , dy: dy
134 - , dzx: if size == dx { dz } else { 0.into() }  
135 - , dzy: if size == -dy { dz } else { 0.into() } 133 + , dz: (bz - az) / cmp::max(dx, -dy).into()
136 , sx: if ax < bx { 1 } else { -1 } 134 , sx: if ax < bx { 1 } else { -1 }
137 , sy: if ay < by { 1 } else { -1 } 135 , sy: if ay < by { 1 } else { -1 }
138 , err: dx + dy 136 , err: dx + dy
@@ -140,52 +138,20 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> @@ -140,52 +138,20 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
140 } 138 }
141 } 139 }
142 140
143 - // Tail recursive Bresenham line with integer incremental error. 141 + fn line_iter(self, b :&Self) -> LineIterator<T> {
  142 + self.iter(b, false)
  143 + }
  144 +
144 fn line(self, b :&Self) -> Vec<Self> { 145 fn line(self, b :&Self) -> Vec<Self> {
145 - self.iter(b, false).collect() 146 + self.line_iter(b).collect()
146 } 147 }
147 148
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 },  
183 - }  
184 - } 149 + fn edge_iter(self, b :&Self) -> LineIterator<T> {
  150 + self.iter(b, true)
  151 + }
185 152
186 - v.push(*b);  
187 - v  
188 - */ 153 + fn edge(self, b :&Self) -> Vec<Self> {
  154 + self.edge_iter(b).collect()
189 } 155 }
190 } 156 }
191 157
@@ -252,40 +218,6 @@ impl<T> Display for Line<T> { @@ -252,40 +218,6 @@ impl<T> Display for Line<T> {
252 } 218 }
253 } 219 }
254 220
255 -// In 3D a rectangle is not as trivial as in 2D, it might be somehow rotate  
256 -// and thus we need to specify a Z offset for the other two corners.  
257 -// As I do not need rectangle at all I just comment out this code for now.  
258 -/*  
259 -#[derive(Debug, Clone, Copy)]  
260 -pub struct Rectangle<T>(pub Coordinate<T>, pub Coordinate<T>);  
261 -  
262 -impl<T> Drawable<T> for Rectangle<T> {  
263 - fn plot(&self) -> Coordinates<T> {  
264 - let Rectangle(a, c) = *self;  
265 - let Coordinate(ax, ay, az) = a;  
266 - let Coordinate(cx, cy, cz) = c;  
267 - let b = Coordinate(cx, ay);  
268 - let d = Coordinate(ax, cy);  
269 -  
270 - let mut r = a.line(&b);  
271 - r.append(&mut b.line(&c)[1..].to_vec());  
272 - r.append(&mut c.line(&d)[1..].to_vec());  
273 - let mut i = d.line(&a);  
274 - let l = i.len();  
275 - r.append(&mut i[1..l-1].to_vec());  
276 -  
277 - Coordinates(r)  
278 - }  
279 -}  
280 -  
281 -impl Display for Rectangle {  
282 - fn fmt(&self, f: &mut Formatter<'_>) -> Result {  
283 - let Rectangle(a, b) = self;  
284 - write!(f, "Rec[{},{}]", a, b)  
285 - }  
286 -}  
287 -*/  
288 -  
289 #[derive(Debug, Clone)] 221 #[derive(Debug, Clone)]
290 pub struct Polyline<T>(pub Coordinates<T>); 222 pub struct Polyline<T>(pub Coordinates<T>);
291 223
@@ -320,9 +252,126 @@ impl<T> Display for Polyline<T> where T: Copy { @@ -320,9 +252,126 @@ impl<T> Display for Polyline<T> where T: Copy {
320 } 252 }
321 } 253 }
322 254
  255 +#[derive(Debug, Clone, Copy)]
  256 +enum Direction { Left, Right }
  257 +
323 #[derive(Debug, Clone)] 258 #[derive(Debug, Clone)]
324 pub struct Polygon<T>(pub Coordinates<T>); 259 pub struct Polygon<T>(pub Coordinates<T>);
325 260
  261 +#[derive(Debug, Clone)]
  262 +pub struct VertexIterator<'a,T> where T: Debug {
  263 + p :&'a Polygon<T>,
  264 + top :usize,
  265 + current :Option<usize>,
  266 + inner :Option<LineIterator<T>>,
  267 + direction :Direction,
  268 +}
  269 +
  270 +impl<'a,T> Iterator for VertexIterator<'a,T>
  271 +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
  272 + + Debug + Copy + From<i32> {
  273 + type Item = Coordinate<T>;
  274 +
  275 + fn next(&mut self) -> Option<Self::Item> {
  276 + let inner = match self.inner {
  277 + Some(i) => i,
  278 + None => {
  279 + let current = self.current?;
  280 + let next = self.p.next_y(current, self.direction)?;
  281 + self.p.vertex(current).edge_iter(&self.p.vertex(next))
  282 + },
  283 + }
  284 +
  285 + match self.current {
  286 + None => None,
  287 + Some(c) => {
  288 + let r = self.p.vertex(c);
  289 + self.current = self.p.next_y(c, self.direction);
  290 + Some(r)
  291 + },
  292 + }
  293 + }
  294 +}
  295 +
  296 +impl<T> Polygon<T> where T: Copy + Debug {
  297 + fn vert_min<'a>(&'a self) -> usize {
  298 + let Polygon(Coordinates(cs)) = self;
  299 +
  300 + type ICoord<'a,T> = (usize, &'a Coordinate<T>);
  301 +
  302 + let fold = | acc :Option<ICoord<'a,T>>, x :ICoord<'a,T> |
  303 + match acc {
  304 + None => Some(x),
  305 + Some(a) => {
  306 + let Coordinate(_, ay, _) = a.1;
  307 + let Coordinate(_, xy, _) = x.1;
  308 + if xy < ay {Some(x)} else {Some(a)}
  309 + },
  310 + };
  311 +
  312 + cs.iter().enumerate().fold(None, fold).unwrap().0
  313 + }
  314 +
  315 + fn left_vertices(&self) -> VertexIterator<T> {
  316 + VertexIterator { p: &self
  317 + , top: self.vert_min()
  318 + , current: Some(self.vert_min())
  319 + , inner: None
  320 + , direction: Direction::Left }
  321 + }
  322 +
  323 + fn left(&self, v :usize) -> usize {
  324 + let Polygon(Coordinates(cs)) = self;
  325 +
  326 + match v {
  327 + 0 => cs.len() - 1,
  328 + _ => v - 1,
  329 + }
  330 + }
  331 +
  332 + fn right(&self, v :usize) -> usize {
  333 + let Polygon(Coordinates(cs)) = self;
  334 +
  335 + (v + 1) % cs.len()
  336 + }
  337 +
  338 + fn step(&self, v :usize, d :Direction) -> usize {
  339 + match d {
  340 + Direction::Left => self.left(v),
  341 + Direction::Right => self.right(v),
  342 + }
  343 + }
  344 +
  345 + #[inline]
  346 + fn vertex(&self, v :usize) -> Coordinate<T> {
  347 + let Polygon(Coordinates(cs)) = self;
  348 + cs[v]
  349 + }
  350 +
  351 + fn next_y(&self, c :usize, d :Direction) -> Option<usize> {
  352 + fn inner<T>( p :&Polygon<T>
  353 + , c :usize
  354 + , n :usize
  355 + , d :Direction) -> Option<usize>
  356 + where T: Copy + Debug {
  357 + if c == n {
  358 + None
  359 + } else {
  360 + let Coordinate(_, cy, _) = p.vertex(c);
  361 + let Coordinate(_, ny, _) = p.vertex(n);
  362 +
  363 + match ny.cmp(&cy) {
  364 + cmp::Ordering::Less => None,
  365 + cmp::Ordering::Equal => inner(p, c, p.step(n, d), d),
  366 + cmp::Ordering::Greater => Some(n),
  367 + }
  368 + }
  369 + }
  370 +
  371 + inner(self, c, self.step(c, d), d)
  372 + }
  373 +}
  374 +
326 impl<T> Drawable<T> for Polygon<T> 375 impl<T> Drawable<T> for Polygon<T>
327 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> 376 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
328 + Debug + Clone + Copy + From<i32> { 377 + Debug + Clone + Copy + From<i32> {
@@ -356,70 +405,45 @@ impl<T> Fillable<T> for Polygon<T> @@ -356,70 +405,45 @@ impl<T> Fillable<T> for Polygon<T>
356 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> 405 where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
357 + Debug + Clone + Copy + From<i32> { 406 + Debug + Clone + Copy + From<i32> {
358 fn fill(&self) -> Coordinates<T> { 407 fn fill(&self) -> Coordinates<T> {
359 -  
360 - fn next_y<T>( cs :&[Coordinate<T>]  
361 - , c :usize  
362 - , f :&dyn Fn(usize) -> usize) -> Option<usize> {  
363 - fn inner<T>( cs :&[Coordinate<T>]  
364 - , c :usize  
365 - , n :usize  
366 - , f :&dyn Fn(usize) -> usize) -> Option<usize> {  
367 - if c == n {  
368 - None  
369 - } else {  
370 - let Coordinate(_, cy, _) = cs[c];  
371 - let Coordinate(_, ny, _) = cs[n];  
372 -  
373 - match ny.cmp(&cy) {  
374 - cmp::Ordering::Less => None,  
375 - cmp::Ordering::Equal => inner(cs, c, f(n), f),  
376 - cmp::Ordering::Greater => Some(n),  
377 - }  
378 - }  
379 - }  
380 -  
381 - inner(cs, c, f(c), f)  
382 - }  
383 -  
384 let Polygon(Coordinates(cs)) = self; 408 let Polygon(Coordinates(cs)) = self;
385 409
386 - let vert_min = cs.iter().enumerate()  
387 - . fold( None  
388 - , |acc, x| match acc {  
389 - None => Some(x),  
390 - Some(a) => {  
391 - let Coordinate(_, ay, _) = a.1;  
392 - let Coordinate(_, xy, _) = x.1;  
393 - if xy < ay {Some(x)} else {Some(a)} } } )  
394 - . unwrap().0;  
395 -  
396 - println!("== vert_min: [{:?}] - {:?}", vert_min, cs[vert_min]); 410 + let vert_min = self.vert_min();
397 411
398 - let right = |x :usize| (x + 1) % cs.len();  
399 - let left = |x :usize| if x == 0 { cs.len() - 1 } else { x - 1 }; 412 + println!("== vert_min: [{}] {:?}", vert_min, cs[vert_min]);
400 413
401 - let mut r = (vert_min, next_y(cs, vert_min, &right));  
402 - let mut l = (vert_min, next_y(cs, vert_min, &left)); 414 + let mut r = (vert_min, self.next_y(vert_min, Direction::Right));
  415 + let mut l = (vert_min, self.next_y(vert_min, Direction::Left));
403 416
404 let mut l_edge :Vec<Coordinate<T>> = Vec::new(); 417 let mut l_edge :Vec<Coordinate<T>> = Vec::new();
405 let mut r_edge :Vec<Coordinate<T>> = Vec::new(); 418 let mut r_edge :Vec<Coordinate<T>> = Vec::new();
406 419
407 let append_edge = | v :&mut Vec<Coordinate<T>> 420 let append_edge = | v :&mut Vec<Coordinate<T>>
408 - , e :&(usize, Option<usize>) | {  
409 - match *e {  
410 - (_, None) => *e, 421 + , e :(usize, Option<usize>)
  422 + , f :Direction | {
  423 + match e {
  424 + (_, None) => e,
411 (a, Some(b)) => { 425 (a, Some(b)) => {
412 - println!("== l: [{:?}] - {:?}", e, cs[b]);  
413 let mut edge = cs[a].edge(&cs[b]); 426 let mut edge = cs[a].edge(&cs[b]);
414 v.append(&mut edge); 427 v.append(&mut edge);
415 - (b, next_y(cs, b, &left)) 428 + (b, self.next_y(b, f))
416 }, 429 },
417 } 430 }
418 }; 431 };
419 432
  433 + let print_current = |s :&str, e :(usize, Option<usize>)| {
  434 + match e.1 {
  435 + None => println!( "== {}: [{:?}] - {:?}"
  436 + , s, e.1, "None"),
  437 + Some(e) => println!( "== {}: [{:?}] - {:?}"
  438 + , s, e, cs[e]),
  439 + }
  440 + };
  441 +
420 while l.1 != None || r.1 != None { 442 while l.1 != None || r.1 != None {
421 - l = append_edge(&mut l_edge, &l);  
422 - r = append_edge(&mut r_edge, &r); 443 + print_current("l", l);
  444 + l = append_edge(&mut l_edge, l, Direction::Left);
  445 + print_current("r", r);
  446 + r = append_edge(&mut r_edge, r, Direction::Right);
423 } 447 }
424 448
425 println!("== [{}] {:?}", l_edge.len(), l_edge); 449 println!("== [{}] {:?}", l_edge.len(), l_edge);
Please register or login to post a comment