mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-05-08 22:53:42 -04:00
fix: scan-line polygon fill incorrectly filled non-convex polygon gaps
Image::Fill(Polygon) implements scan-line polygon fill but iterated through active edges one at a time instead of in pairs. For convex polygons (always exactly 2 active edges per scan line) this happened to work, but for non-convex polygons it would fill the gaps between concave sections. A banana-shaped zone, for example, would have its inner concave area incorrectly marked as inside the zone, causing motion detection to trigger on the area the user explicitly drew the zone to avoid. Fix by stepping the iterator by 2 to fill between pairs of edges following the standard parity rule for scan-line polygon fill. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2720,9 +2720,12 @@ void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
|
||||
std::sort(active_edges.begin(), active_edges.end(), PolygonFill::Edge::CompareX);
|
||||
|
||||
if (!(scan_line % density)) {
|
||||
for (auto it = active_edges.begin(); it < active_edges.end() - 1; ++it) {
|
||||
// Fill between pairs of active edges (parity rule). Stepping one
|
||||
// edge at a time would incorrectly fill the gaps between arms of
|
||||
// a non-convex polygon (e.g. a banana shape).
|
||||
for (auto it = active_edges.begin(); it + 1 < active_edges.end(); it += 2) {
|
||||
int32 lo_x = static_cast<int32>(it->min_x);
|
||||
int32 hi_x = static_cast<int32>(std::next(it)->min_x);
|
||||
int32 hi_x = static_cast<int32>((it + 1)->min_x);
|
||||
if (colours == ZM_COLOUR_GRAY8) {
|
||||
uint8 *p = &buffer[(scan_line * width) + lo_x];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user