Showing
1 changed file
with
190 additions
and
166 deletions
... | ... | @@ -62,8 +62,7 @@ pub struct LineIterator<T> where T: Debug { |
62 | 62 | , b :Coordinate<T> |
63 | 63 | , dx :i32 |
64 | 64 | , dy :i32 |
65 | - , dzx :T | |
66 | - , dzy :T | |
65 | + , dz :T | |
67 | 66 | , sx :i32 |
68 | 67 | , sy :i32 |
69 | 68 | , err :i32 |
... | ... | @@ -75,41 +74,43 @@ where T: Add<Output = T> + Debug + Copy + From<i32> { |
75 | 74 | type Item = Coordinate<T>; |
76 | 75 | |
77 | 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 | 123 | let Coordinate(ax, ay, az) = self; |
123 | 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 | 129 | LineIterator { a: Some(self) |
131 | 130 | , b: *b |
132 | 131 | , dx: dx |
133 | 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 | 134 | , sx: if ax < bx { 1 } else { -1 } |
137 | 135 | , sy: if ay < by { 1 } else { -1 } |
138 | 136 | , err: dx + dy |
... | ... | @@ -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 | 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 | 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 | 221 | #[derive(Debug, Clone)] |
290 | 222 | pub struct Polyline<T>(pub Coordinates<T>); |
291 | 223 | |
... | ... | @@ -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 | 258 | #[derive(Debug, Clone)] |
324 | 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 | 375 | impl<T> Drawable<T> for Polygon<T> |
327 | 376 | where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
328 | 377 | + Debug + Clone + Copy + From<i32> { |
... | ... | @@ -356,70 +405,45 @@ impl<T> Fillable<T> for Polygon<T> |
356 | 405 | where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
357 | 406 | + Debug + Clone + Copy + From<i32> { |
358 | 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 | 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 | 417 | let mut l_edge :Vec<Coordinate<T>> = Vec::new(); |
405 | 418 | let mut r_edge :Vec<Coordinate<T>> = Vec::new(); |
406 | 419 | |
407 | 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 | 425 | (a, Some(b)) => { |
412 | - println!("== l: [{:?}] - {:?}", e, cs[b]); | |
413 | 426 | let mut edge = cs[a].edge(&cs[b]); |
414 | 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 | 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 | 449 | println!("== [{}] {:?}", l_edge.len(), l_edge); | ... | ... |
Please
register
or
login
to post a comment