From b894c8c73df04cb9ee2dc7b2e858278c59ece1be Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 21 Jan 2022 11:55:59 +1100 Subject: [PATCH] Connected discontiguous polygon corners --- .../discontiguous_corners_polygon.png | Bin 0 -> 486 bytes Tests/test_imagedraw.py | 12 +++++ src/libImaging/Draw.c | 47 +++++++++++++++--- 3 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 Tests/images/imagedraw/discontiguous_corners_polygon.png diff --git a/Tests/images/imagedraw/discontiguous_corners_polygon.png b/Tests/images/imagedraw/discontiguous_corners_polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..509c42b26e0cbc5e01853915b083d367c1587579 GIT binary patch literal 486 zcmV@P)`!#sE^rA`<@Y%+RkqV?!_A|y&2pY*8)6=f4VlpVwn5}t^A6YuX03S#Y#g)7 zJQ^F#EHsbC_F-n5M`L?3Gt8s0{h7DSqp_oy7v|B}vCOaL^=6`p{x-yW@%sX@;oL`>6ss&}tQP{jy7s{L0??ngmnl7|5FWZZ5<^^5oX`ZzgZO!j@p}F~;z36X#*@aWg zPxj&<^KY|ooO$-7geQocksJTt*qn7e|89Ry{mlcOoKl@{@N4rK(#!8NvH9v#u!Q36 zd^nGC&Ywovw|zL9#`fS+c-x0_%4~m^#QgC7qU2=tJzr(chtir4_K?>8 z*}eohL7(jt&iOMT_E%jt+e0>wUv+tG52<#O=|9Yqe0QdtH`8R!&C>dOKMmcHy=s1@ cdrJ2_KmNq&!9TB{#sB~S07*qoM6N<$f>{CjhyVZp literal 0 HcmV?d00001 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index b661494c733..3df4e7ca1db 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -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) diff --git a/src/libImaging/Draw.c b/src/libImaging/Draw.c index 0e4899b5b49..86cd6c3a058 100644 --- a/src/libImaging/Draw.c +++ b/src/libImaging/Draw.c @@ -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; @@ -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);