Skip to content

Commit 25a8e1a

Browse files
committed
PoygonScanning.MD
1 parent 8798c4a commit 25a8e1a

3 files changed

Lines changed: 77 additions & 1 deletion

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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

src/ImageSharp.Drawing/Shapes/Rasterization/ScanEdgeCollection.Build.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public static void ApplyVertexCategory(
177177
// Since PolygonScanner does not process vertices, only edges, we need to define arbitrary rules
178178
// about WHERE (on which edge) do we emit the vertex intersections.
179179
// For visualization of the rules see:
180-
// VertexCategoriesAndEmitRules.jpg
180+
// PoygonScanning.MD
181181
// For an example, see:
182182
// ImageSharp.Drawing.Tests/Shapes/Scan/SimplePolygon_AllEmitCases.png
183183
switch (vertexCategory)
Binary file not shown.

0 commit comments

Comments
 (0)