1use crate::fixed::F26Dot6;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct Edge {
17 pub x: F26Dot6,
19
20 pub x_increment: F26Dot6,
22
23 pub direction: i8,
25
26 pub y_max: i32,
28
29 pub y_min: i32,
31}
32
33impl Edge {
34 pub fn new(x1: F26Dot6, y1: F26Dot6, x2: F26Dot6, y2: F26Dot6) -> Option<Self> {
50 let dy = y2 - y1;
51
52 if dy == F26Dot6::ZERO {
53 return None;
54 }
55
56 let (x_start, y_start, x_end, y_end, direction) = if dy > F26Dot6::ZERO {
58 (x1, y1, x2, y2, 1i8)
59 } else {
60 (x2, y2, x1, y1, -1i8)
61 };
62
63 let dy_abs = y_end - y_start;
64 let dx = x_end - x_start;
65
66 let x_increment = dx.div(dy_abs);
68
69 let y_min = y_start.ceil().to_int();
73 let y_max = y_end.ceil().to_int() - 1;
74
75 if y_min > y_max {
76 return None;
77 }
78
79 let delta_y = F26Dot6::from_int(y_min) - y_start;
82 let x = x_start + delta_y.mul(x_increment);
83
84 Some(Edge {
85 x,
86 x_increment,
87 direction,
88 y_max,
89 y_min,
90 })
91 }
92
93 #[inline]
98 pub fn step(&mut self) {
99 self.x = self.x + self.x_increment;
100 }
101
102 #[inline]
107 pub fn is_active(&self, y: i32) -> bool {
108 y <= self.y_max
109 }
110}
111
112#[derive(Debug, Clone, Default)]
119pub struct EdgeList {
120 edges: Vec<Edge>,
121}
122
123impl EdgeList {
124 pub fn new() -> Self {
126 Self { edges: Vec::new() }
127 }
128
129 pub fn with_capacity(capacity: usize) -> Self {
131 Self {
132 edges: Vec::with_capacity(capacity),
133 }
134 }
135
136 pub fn insert_sorted(&mut self, edge: Edge) {
141 let pos = self
142 .edges
143 .binary_search_by(|e| e.x.cmp(&edge.x))
144 .unwrap_or_else(|e| e);
145 self.edges.insert(pos, edge);
146 }
147
148 pub fn sort_by_x(&mut self) {
150 self.edges.sort_by(|a, b| a.x.cmp(&b.x));
151 }
152
153 pub fn remove_inactive(&mut self, y: i32) {
155 self.edges.retain(|edge| edge.is_active(y));
156 }
157
158 pub fn step_all(&mut self) {
160 for edge in &mut self.edges {
161 edge.step();
162 }
163 }
164
165 pub fn clear(&mut self) {
167 self.edges.clear();
168 }
169
170 #[inline]
172 pub fn len(&self) -> usize {
173 self.edges.len()
174 }
175
176 #[inline]
178 pub fn is_empty(&self) -> bool {
179 self.edges.is_empty()
180 }
181
182 #[inline]
184 pub fn as_slice(&self) -> &[Edge] {
185 &self.edges
186 }
187
188 #[inline]
190 pub fn as_mut_slice(&mut self) -> &mut [Edge] {
191 &mut self.edges
192 }
193
194 pub fn push(&mut self, edge: Edge) {
196 self.edges.push(edge);
197 }
198
199 pub fn extend(&mut self, other: &EdgeList) {
201 self.edges.extend_from_slice(&other.edges);
202 }
203
204 pub fn iter(&self) -> std::slice::Iter<'_, Edge> {
206 self.edges.iter()
207 }
208
209 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Edge> {
211 self.edges.iter_mut()
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn test_edge_new_vertical() {
221 let e = Edge::new(
222 F26Dot6::from_int(10),
223 F26Dot6::from_int(5),
224 F26Dot6::from_int(10),
225 F26Dot6::from_int(15),
226 )
227 .unwrap();
228
229 assert_eq!(e.x, F26Dot6::from_int(10));
230 assert_eq!(e.x_increment, F26Dot6::ZERO);
231 assert_eq!(e.direction, 1);
232 assert_eq!(e.y_min, 5);
233 assert_eq!(e.y_max, 14); }
235
236 #[test]
237 fn test_edge_new_horizontal_returns_none() {
238 let e = Edge::new(
239 F26Dot6::from_int(10),
240 F26Dot6::from_int(5),
241 F26Dot6::from_int(20),
242 F26Dot6::from_int(5),
243 );
244
245 assert!(e.is_none());
246 }
247
248 #[test]
249 fn test_edge_new_diagonal() {
250 let e = Edge::new(
251 F26Dot6::from_int(0),
252 F26Dot6::from_int(0),
253 F26Dot6::from_int(10),
254 F26Dot6::from_int(10),
255 )
256 .unwrap();
257
258 assert_eq!(e.x, F26Dot6::from_int(0));
259 assert_eq!(e.direction, 1);
260 assert_eq!(e.y_min, 0);
261 assert_eq!(e.y_max, 9); assert_eq!(e.x_increment.raw(), 64);
264 }
265
266 #[test]
267 fn test_edge_new_swaps_if_downward() {
268 let e = Edge::new(
269 F26Dot6::from_int(20),
270 F26Dot6::from_int(15),
271 F26Dot6::from_int(10),
272 F26Dot6::from_int(5),
273 )
274 .unwrap();
275
276 assert_eq!(e.x, F26Dot6::from_int(10));
278 assert_eq!(e.y_min, 5);
279 assert_eq!(e.y_max, 14); assert_eq!(e.direction, -1);
281 }
282
283 #[test]
284 fn test_edge_step() {
285 let mut e = Edge::new(
286 F26Dot6::from_int(0),
287 F26Dot6::from_int(0),
288 F26Dot6::from_int(10),
289 F26Dot6::from_int(10),
290 )
291 .unwrap();
292
293 assert_eq!(e.x.to_int(), 0);
294 e.step();
295 assert_eq!(e.x.to_int(), 1);
296 e.step();
297 assert_eq!(e.x.to_int(), 2);
298 }
299
300 #[test]
301 fn test_edge_is_active() {
302 let e = Edge::new(
303 F26Dot6::from_int(0),
304 F26Dot6::from_int(5),
305 F26Dot6::from_int(10),
306 F26Dot6::from_int(15),
307 )
308 .unwrap();
309
310 assert!(e.is_active(5));
311 assert!(e.is_active(10));
312 assert!(e.is_active(14));
313 assert!(!e.is_active(15));
314 }
315
316 #[test]
317 fn test_edgelist_new() {
318 let list = EdgeList::new();
319 assert!(list.is_empty());
320 assert_eq!(list.len(), 0);
321 }
322
323 #[test]
324 fn test_edgelist_push() {
325 let mut list = EdgeList::new();
326 let e = Edge::new(
327 F26Dot6::from_int(10),
328 F26Dot6::from_int(0),
329 F26Dot6::from_int(10),
330 F26Dot6::from_int(10),
331 )
332 .unwrap();
333
334 list.push(e);
335 assert_eq!(list.len(), 1);
336 assert!(!list.is_empty());
337 }
338
339 #[test]
340 fn test_edgelist_insert_sorted() {
341 let mut list = EdgeList::new();
342
343 list.insert_sorted(
344 Edge::new(
345 F26Dot6::from_int(20),
346 F26Dot6::ZERO,
347 F26Dot6::from_int(20),
348 F26Dot6::from_int(10),
349 )
350 .unwrap(),
351 );
352
353 list.insert_sorted(
354 Edge::new(
355 F26Dot6::from_int(10),
356 F26Dot6::ZERO,
357 F26Dot6::from_int(10),
358 F26Dot6::from_int(10),
359 )
360 .unwrap(),
361 );
362
363 list.insert_sorted(
364 Edge::new(
365 F26Dot6::from_int(15),
366 F26Dot6::ZERO,
367 F26Dot6::from_int(15),
368 F26Dot6::from_int(10),
369 )
370 .unwrap(),
371 );
372
373 assert_eq!(list.len(), 3);
374 assert_eq!(list.as_slice()[0].x.to_int(), 10);
375 assert_eq!(list.as_slice()[1].x.to_int(), 15);
376 assert_eq!(list.as_slice()[2].x.to_int(), 20);
377 }
378
379 #[test]
380 fn test_edgelist_sort_by_x() {
381 let mut list = EdgeList::new();
382
383 list.push(
384 Edge::new(
385 F26Dot6::from_int(20),
386 F26Dot6::ZERO,
387 F26Dot6::from_int(20),
388 F26Dot6::from_int(10),
389 )
390 .unwrap(),
391 );
392
393 list.push(
394 Edge::new(
395 F26Dot6::from_int(10),
396 F26Dot6::ZERO,
397 F26Dot6::from_int(10),
398 F26Dot6::from_int(10),
399 )
400 .unwrap(),
401 );
402
403 list.sort_by_x();
404
405 assert_eq!(list.as_slice()[0].x.to_int(), 10);
406 assert_eq!(list.as_slice()[1].x.to_int(), 20);
407 }
408
409 #[test]
410 fn test_edgelist_remove_inactive() {
411 let mut list = EdgeList::new();
412
413 list.push(
414 Edge::new(
415 F26Dot6::from_int(10),
416 F26Dot6::ZERO,
417 F26Dot6::from_int(10),
418 F26Dot6::from_int(5),
419 )
420 .unwrap(),
421 );
422
423 list.push(
424 Edge::new(
425 F26Dot6::from_int(20),
426 F26Dot6::ZERO,
427 F26Dot6::from_int(20),
428 F26Dot6::from_int(10),
429 )
430 .unwrap(),
431 );
432
433 assert_eq!(list.len(), 2);
434
435 list.remove_inactive(6);
436 assert_eq!(list.len(), 1);
437 assert_eq!(list.as_slice()[0].x.to_int(), 20);
438 }
439
440 #[test]
441 fn test_edgelist_step_all() {
442 let mut list = EdgeList::new();
443
444 list.push(
445 Edge::new(
446 F26Dot6::from_int(0),
447 F26Dot6::from_int(0),
448 F26Dot6::from_int(10),
449 F26Dot6::from_int(10),
450 )
451 .unwrap(),
452 );
453
454 list.push(
455 Edge::new(
456 F26Dot6::from_int(0),
457 F26Dot6::from_int(0),
458 F26Dot6::from_int(20),
459 F26Dot6::from_int(10),
460 )
461 .unwrap(),
462 );
463
464 assert_eq!(list.as_slice()[0].x.to_int(), 0);
465 assert_eq!(list.as_slice()[1].x.to_int(), 0);
466
467 list.step_all();
468
469 assert_eq!(list.as_slice()[0].x.to_int(), 1);
470 assert_eq!(list.as_slice()[1].x.to_int(), 2);
471 }
472
473 #[test]
474 fn test_edgelist_clear() {
475 let mut list = EdgeList::new();
476 list.push(
477 Edge::new(
478 F26Dot6::from_int(10),
479 F26Dot6::ZERO,
480 F26Dot6::from_int(10),
481 F26Dot6::from_int(10),
482 )
483 .unwrap(),
484 );
485
486 assert!(!list.is_empty());
487 list.clear();
488 assert!(list.is_empty());
489 }
490
491 #[test]
492 fn test_edgelist_extend() {
493 let mut list1 = EdgeList::new();
494 let mut list2 = EdgeList::new();
495
496 list1.push(
497 Edge::new(
498 F26Dot6::from_int(10),
499 F26Dot6::ZERO,
500 F26Dot6::from_int(10),
501 F26Dot6::from_int(10),
502 )
503 .unwrap(),
504 );
505
506 list2.push(
507 Edge::new(
508 F26Dot6::from_int(20),
509 F26Dot6::ZERO,
510 F26Dot6::from_int(20),
511 F26Dot6::from_int(10),
512 )
513 .unwrap(),
514 );
515
516 list1.extend(&list2);
517 assert_eq!(list1.len(), 2);
518 }
519
520 #[test]
521 fn test_edge_fractional_slope() {
522 let e = Edge::new(
524 F26Dot6::from_int(0),
525 F26Dot6::from_int(0),
526 F26Dot6::from_int(5),
527 F26Dot6::from_int(10),
528 )
529 .unwrap();
530
531 assert_eq!(e.x_increment.raw(), 32);
533
534 let mut x = e.x;
535 x = x + e.x_increment;
537 x = x + e.x_increment;
538 assert_eq!(x.to_int(), 1);
539 }
540
541 #[test]
542 fn test_edge_negative_slope() {
543 let e = Edge::new(
545 F26Dot6::from_int(10),
546 F26Dot6::from_int(0),
547 F26Dot6::from_int(0),
548 F26Dot6::from_int(10),
549 )
550 .unwrap();
551
552 assert_eq!(e.x_increment.raw(), -64);
554
555 let mut test_e = e;
556 assert_eq!(test_e.x.to_int(), 10);
557 test_e.step();
558 assert_eq!(test_e.x.to_int(), 9);
559 }
560
561 #[test]
562 fn test_edgelist_with_capacity() {
563 let list = EdgeList::with_capacity(100);
564 assert_eq!(list.len(), 0);
565 assert!(list.edges.capacity() >= 100);
566 }
567
568 #[test]
569 fn test_edge_winding_direction() {
570 let e_up = Edge::new(
572 F26Dot6::from_int(0),
573 F26Dot6::from_int(0),
574 F26Dot6::from_int(10),
575 F26Dot6::from_int(10),
576 )
577 .unwrap();
578 assert_eq!(e_up.direction, 1);
579
580 let e_down = Edge::new(
582 F26Dot6::from_int(10),
583 F26Dot6::from_int(10),
584 F26Dot6::from_int(0),
585 F26Dot6::from_int(0),
586 )
587 .unwrap();
588 assert_eq!(e_down.direction, -1);
589 }
590
591 #[test]
592 fn test_edgelist_iter() {
593 let mut list = EdgeList::new();
594 list.push(
595 Edge::new(
596 F26Dot6::from_int(10),
597 F26Dot6::ZERO,
598 F26Dot6::from_int(10),
599 F26Dot6::from_int(10),
600 )
601 .unwrap(),
602 );
603
604 let count = list.iter().count();
605 assert_eq!(count, 1);
606 }
607
608 #[test]
609 fn test_edgelist_iter_mut() {
610 let mut list = EdgeList::new();
611 list.push(
612 Edge::new(
613 F26Dot6::from_int(10),
614 F26Dot6::ZERO,
615 F26Dot6::from_int(10),
616 F26Dot6::from_int(10),
617 )
618 .unwrap(),
619 );
620
621 for edge in list.iter_mut() {
622 edge.step();
623 }
624
625 assert_eq!(list.as_slice()[0].x.to_int(), 10);
627 }
628}