From a90a3bcceac524b02165a64e61546809ff9927f2 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 27 Feb 2026 17:49:14 -0500 Subject: [PATCH] fix: auto-detect and convert pixel zone coordinates to percentages in web layer When zone coordinates are stored as pixel values (e.g. from a missed DB migration), the web layer now detects values > 100 and converts them to percentages using the monitor's dimensions, mirroring the existing C++ detection logic in zm_zone.cpp. This prevents limitPoints() from clamping pixel values to 0-100 and zones rendering incorrectly in SVG overlays. - Add convertPixelPointsToPercent() helper in functions.php - Call conversion before limitPoints() in zone.php and zones.php - Update Zone::svg_polygon() to accept monitor dimensions and convert - Pass ViewWidth/ViewHeight to svg_polygon() from Monitor::getStreamHTML() Co-Authored-By: Claude Opus 4.6 --- web/includes/Monitor.php | 4 ++-- web/includes/Zone.php | 23 +++++++++++++++++++++-- web/includes/functions.php | 18 ++++++++++++++++++ web/skins/classic/views/zone.php | 3 +++ web/skins/classic/views/zones.php | 1 + 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/web/includes/Monitor.php b/web/includes/Monitor.php index 8d593e92d..d23fea47d 100644 --- a/web/includes/Monitor.php +++ b/web/includes/Monitor.php @@ -1214,13 +1214,13 @@ class Monitor extends ZM_Object { foreach ($options['zones'] as $zone_id) { $zone = new Zone($zone_id); if ($zone->Id() and $zone->MonitorId() == $this->Id()) { - $html .= $zone->svg_polygon(); + $html .= $zone->svg_polygon($this->ViewWidth(), $this->ViewHeight()); } } } else { // true: render all zones for this monitor foreach (Zone::find(array('MonitorId'=>$this->Id()), array('order'=>'Area DESC')) as $zone) { - $html .= $zone->svg_polygon(); + $html .= $zone->svg_polygon($this->ViewWidth(), $this->ViewHeight()); } } if (isset($options['zones_extra'])) { diff --git a/web/includes/Zone.php b/web/includes/Zone.php index c7a67cecd..eba3af4d9 100644 --- a/web/includes/Zone.php +++ b/web/includes/Zone.php @@ -59,8 +59,27 @@ class Zone extends ZM_Object { return preg_replace('/\s+/', ',', $this->Coords()); } - public function svg_polygon() { - return ''.$this->Name().''; + public function svg_polygon($width=0, $height=0) { + $areaCoords = $this->AreaCoords(); + if ($width && $height) { + $points = coordsToPoints($this->Coords()); + $isPixel = false; + foreach ($points as $point) { + if ($point['x'] > 100 || $point['y'] > 100) { + $isPixel = true; + break; + } + } + if ($isPixel) { + foreach ($points as &$point) { + $point['x'] = round($point['x'] / $width * 100, 2); + $point['y'] = round($point['y'] / $height * 100, 2); + } + unset($point); + $areaCoords = preg_replace('/\s+/', ',', pointsToCoords($points)); + } + } + return ''.$this->Name().''; } } # end class Zone ?> diff --git a/web/includes/functions.php b/web/includes/functions.php index 6d9954bea..5b4eb9cf7 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -1466,6 +1466,24 @@ function limitPoints(&$points, $min_x, $min_y, $max_x, $max_y) { } // end foreach point } // end function limitPoints( $points, $min_x, $min_y, $max_x, $max_y ) +function convertPixelPointsToPercent(&$points, $width, $height) { + if (!$width || !$height) return; + $isPixel = false; + foreach ($points as $point) { + if ($point['x'] > 100 || $point['y'] > 100) { + $isPixel = true; + break; + } + } + if ($isPixel) { + foreach ($points as &$point) { + $point['x'] = round($point['x'] / $width * 100, 2); + $point['y'] = round($point['y'] / $height * 100, 2); + } + unset($point); + } +} + function scalePoints(&$points, $scale) { foreach ( $points as &$point ) { $point['x'] = reScale($point['x'], $scale); diff --git a/web/skins/classic/views/zone.php b/web/skins/classic/views/zone.php index a9b89aa23..112b4b767 100644 --- a/web/skins/classic/views/zone.php +++ b/web/skins/classic/views/zone.php @@ -94,6 +94,9 @@ if ( !isset($zone) ) { $zone['AreaCoords'] = preg_replace('/\s+/', ',', $zone['Coords']); } # end if new Zone +# Auto-detect pixel coordinates and convert to percentages +convertPixelPointsToPercent($zone['Points'], $monitor->ViewWidth(), $monitor->ViewHeight()); + # Ensure Zone fits within the limits of the Monitor limitPoints($zone['Points'], $minX, $minY, $maxX, $maxY); diff --git a/web/skins/classic/views/zones.php b/web/skins/classic/views/zones.php index 105eb455c..0304cb382 100644 --- a/web/skins/classic/views/zones.php +++ b/web/skins/classic/views/zones.php @@ -73,6 +73,7 @@ echo getNavBarHTML(); } } + convertPixelPointsToPercent($row['Points'], $monitor->ViewWidth(), $monitor->ViewHeight()); limitPoints($row['Points'], $minX, $minY, $maxX, $maxY); $row['Coords'] = pointsToCoords($row['Points']); $row['AreaCoords'] = preg_replace('/\s+/', ',', $row['Coords']);