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