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