|
| 1 | +# Polygon Scanning with Active Edge List |
| 2 | + |
| 3 | +Scanning is done with a variant of the ["Active Edge Table" algorithm](https://en.wikipedia.org/wiki/Scanline_rendering#Algorithm), that doesn't build a table beforehand, just maintains the list of currently active edges. |
| 4 | + |
| 5 | +After rasterizing polygons a collection of non-horizontal edges (ScanEdge) is extracted into ScanEdgeCollection. These are then sorted by minimum and maximum Y coordinate, which enables the maintanance of the Active Edge List as we traverse the collection from `minY` to `maxY`. |
| 6 | + |
| 7 | +When intersecting a ScanEdge start (Y0) and end (Y1) intersections have special handling. Since these belong to vertices (connection points) sometimes we need to emit the intersection point 2 times. In other cases we do not want to emit it at all. |
| 8 | + |
| 9 | +### Illustration |
| 10 | + |
| 11 | +Consider the following polygon with 4 non-horizontal ScanEdge-s, being intersected by scanlines `SCANLINE 1` and `SCANLINE 2`: |
| 12 | + |
| 13 | +``` |
| 14 | + + - - - - - - - - - - - - - - - - + |
| 15 | + | (1) (1)\ |
| 16 | + | \ B |
| 17 | + | \ |
| 18 | + | (0) \ |
| 19 | +SCANLINE 1 >>>> | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | (1) >>>>>>>>> |
| 20 | + | | |
| 21 | + | A C | |
| 22 | + | | |
| 23 | + | (2) | (1) |
| 24 | +SCANLINE 2 >>>> | >>>>>>>>>>>>>> + - - - - - - - - - - + >>>>>>>>> |
| 25 | + | | |
| 26 | + | | |
| 27 | + | D | |
| 28 | + | | |
| 29 | + | | |
| 30 | + + - - - - - - - + |
| 31 | +
|
| 32 | +``` |
| 33 | + |
| 34 | + |
| 35 | +#### Scanning SCANLINE 1 |
| 36 | + |
| 37 | +- Intersection with edge A is trivial, since it's being intersected on an internal point |
| 38 | +- The second intersection is more tricky: the intersection point is at the connection (vertex) between edges B and C, but we do not want to emit the intersection 2 times. |
| 39 | + - To avoid this, when checking the collision with edge B we emit 0 intersections for edge B, when checking against edge C we emit 1 point |
| 40 | + |
| 41 | +#### Scanning SCANLINE 2 |
| 42 | + |
| 43 | +- Intersection with edge A is trivial, since it's being intersected on an internal point |
| 44 | +- However the rest is tricky: We want to to emulate the intersection with the collinear edge not being listed in `ScanEdgeCollection`. |
| 45 | + - The easies we want to do so is to emit a point pair for the line part between A-D and a second point pair for D-C |
| 46 | + - To achieve this, we should emit the start point (Y0) intersection of the D edge 2 times! |
| 47 | + |
| 48 | +### Edge emit rules |
| 49 | + |
| 50 | +The emit rules are here to provide a consistent way for intersecting stuff as described in the previous "Illustration" part. |
| 51 | +These rules only work well, when: |
| 52 | +- The outline polygons are Clockwise in screen-space (= "has positive orientation" according to the terminlogy used in the repository) |
| 53 | +- Holes have Counter-Clockwise ("negative") orientation. |
| 54 | + |
| 55 | +Most real-world inputs tend to follow these rules, however intersecting polygons which do not do so, leads to inaccuracies around horizontal edges. These inaccuracies are visually acceptable. |
| 56 | + |
| 57 | +The rules apply to vertices (edge connections). `⟶` and `⟵` edges are horizontal, `↑` and `↓` edges are non-horizontal. |
| 58 | + |
| 59 | +Edge In | Edge Out | Emit on "Edge In" | Emit on "Edge out" |
| 60 | +-- | -- | -- | -- |
| 61 | +↑ | ↑ | 0 | 1 |
| 62 | +↑ | ↓ | 1 | 1 |
| 63 | +↑ | ⟵ | 2 | 0 |
| 64 | +↑ | ⟶ | 1 | 0 |
| 65 | +↓ | ↑ | 1 | 1 |
| 66 | +↓ | ↓ | 0 | 1 |
| 67 | +↓ | ⟵ | 1 | 0 |
| 68 | +↓ | ⟶ | 2 | 0 |
| 69 | +⟵ | ↑ | 0 | 1 |
| 70 | +⟵ | ↓ | 0 | 2 |
| 71 | +⟵ | ⟵ | 0 | 0 |
| 72 | +⟵ | ⟶ | 0 | 0 |
| 73 | +⟶ | ↑ | 0 | 2 |
| 74 | +⟶ | ↓ | 0 | 1 |
| 75 | +⟶ | ⟵ | 0 | 0 |
| 76 | +⟶ | ⟶ | 0 | 0 |
0 commit comments