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