Skip to content

Commit

Permalink
Connected discontiguous polygon corners
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Jan 21, 2022
1 parent 48d32fe commit b894c8c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 7 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions Tests/test_imagedraw.py
Expand Up @@ -1440,3 +1440,15 @@ def test_continuous_horizontal_edges_polygon():
assert_image_equal_tofile(
img, expected, "continuous horizontal edges polygon failed"
)


def test_discontiguous_corners_polygon():
img, draw = create_base_image_draw((84, 68))
draw.polygon(((1, 21), (34, 4), (71, 1), (38, 18)), BLACK)
draw.polygon(((71, 44), (38, 27), (1, 24)), BLACK)
draw.polygon(
((38, 66), (5, 49), (77, 49), (47, 66), (82, 63), (82, 47), (1, 47), (1, 63)),
BLACK,
)
expected = os.path.join(IMAGES_PATH, "discontiguous_corners_polygon.png")
assert_image_similar_tofile(img, expected, 1)
47 changes: 40 additions & 7 deletions src/libImaging/Draw.c
Expand Up @@ -450,7 +450,8 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
int edge_count = 0;
int ymin = im->ysize - 1;
int ymax = 0;
int i;
int i, j, k;
float adjacent_line_x, adjacent_line_x_other_edge;

if (n <= 0) {
return 0;
Expand Down Expand Up @@ -493,16 +494,48 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
return -1;
}
for (; ymin <= ymax; ymin++) {
int j = 0;
j = 0;
for (i = 0; i < edge_count; i++) {
Edge *current = edge_table[i];
if (ymin >= current->ymin && ymin <= current->ymax) {
xx[j++] = (ymin - current->y0) * current->dx + current->x0;
}
/* Needed to draw consistent polygons */
if (ymin == current->ymax && ymin < ymax) {
xx[j] = xx[j - 1];
j++;

if (ymin == current->ymax && ymin < ymax) {
// Needed to draw consistent polygons
xx[j] = xx[j - 1];
j++;
} else if (current->dx != 0 && roundf(xx[j-1]) == xx[j-1]) {
// Connect discontiguous corners
for (k = 0; k < i; k++) {
Edge *other_edge = edge_table[k];
if ((current->dx > 0 && other_edge->dx <= 0) ||
(current->dx < 0 && other_edge->dx >= 0)) {
continue;
}
// Check if the two edges join to make a corner
if (xx[j-1] == (ymin - other_edge->y0) * other_edge->dx + other_edge->x0) {
// Determine points from the edges on the next row
// Or if this is the last row, check the previous row
int offset = ymin == ymax ? -1 : 1;
adjacent_line_x = (ymin + offset - current->y0) * current->dx + current->x0;
adjacent_line_x_other_edge = (ymin + offset - other_edge->y0) * other_edge->dx + other_edge->x0;
if (ymin == current->ymax) {
if (current->dx > 0) {
xx[k] = fmax(adjacent_line_x, adjacent_line_x_other_edge) + 1;
} else {
xx[k] = fmin(adjacent_line_x, adjacent_line_x_other_edge) - 1;
}
} else {
if (current->dx > 0) {
xx[k] = fmin(adjacent_line_x, adjacent_line_x_other_edge);
} else {
xx[k] = fmax(adjacent_line_x, adjacent_line_x_other_edge) + 1;
}
}
break;
}
}
}
}
}
qsort(xx, j, sizeof(float), x_cmp);
Expand Down

2 comments on commit b894c8c

@mikedh
Copy link

@mikedh mikedh commented on b894c8c May 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, not totally sure if this change is related (it's the only polygon rasterization change I could find in the right release cycle), but in the pillow 9.0.1 -> 9.1.0 release certain rasterization started seeing a "scanline defect" type of bug. More details and a pillow-only minimal reproducible example are here: mikedh/trimesh#1569

@radarhere
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above comment has now become #6290

Please sign in to comment.