You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多边形像素坐标转网格参考:替代GD库的高效优化方案

680x680多边形坐标转68x68网格编号的高性能实现方案

需求与痛点

需要将大量680x680像素坐标系下的多边形顶点线段,转换为该多边形覆盖的68x68网格编号(网格编号按行排列:1,2,3,4;5,6,7,8…)。原方案采用GD库绘制多边形后检测像素亮度完成转换,但每分钟需处理数千组多边形,性能无法满足需求,需寻找更高效的实现方式。

运行示例及输出

$p = [];
$r = [];
$p['segments'] = [[144, 637], [225, 516], [85, 460], [30, 482]];
$r = segments_to_grid($p, $r);
print_r($r['grid']);

输出结果:

Array
(
    [0] => 3133
    [1] => 3134
    ...
    [163] => 4229
)

原有GD库实现

/**
 * Convert a list of x/y coordinates to grid references
 *
 * @param array $p
 * @param array $r
 *
 * @return array augmented $r
 */
function segments_to_grid($p, $r) {
  $p['segments'] = isset($p['segments']) ? $p['segments'] : [];
  // e.g, [[144,637],[225,516],[85,460],[30,482]]

  // Return array
  $r['grid'] = [];


  // Define base dimensions
  $w = 680;
  $h = 680;
  $poly_coords = [];
  $min_x = $min_y = 680;
  $max_x = $max_y = 0;

  // Build an imagefilledpolygon compatible array and extract minimum and maximum for bounding box
  foreach ($p['segments'] as $segment) {
    $poly_coords[] = $segment[0];
    $poly_coords[] = $segment[1];
    $min_x = min($min_x, $segment[0]);
    $min_y = min($min_y, $segment[1]);
    $max_x = max($max_x, $segment[0]);
    $max_y = max($max_y, $segment[1]);
  }

  // check we have something useful
  if (!empty($poly_coords)) {
    $r['code'] = 40;

    // create image
    $img = imagecreatetruecolor($w, $h);

    // allocate colors (white background, black polygon)
    $bg   = imagecolorallocate($img, 255, 255, 255);
    $black = imagecolorallocate($img, 0, 0, 0);

    // fill the background
    imagefilledrectangle($img, 0, 0, $w, $h, $bg);

    // draw a polygon
    if (imagefilledpolygon($img, $poly_coords, count($p['segments']), $black)) {
      $r['code'] = 0;

      // loop through the image and find the points that are black
      for ($y = $min_y; $y < $max_y; $y = $y + 10) {
        for ($x = $min_x; $x < $max_x; $x = $x + 10) {
          $rgb = imagecolorat($img, $x, $y);
          if (intval($rgb) < 16777215) {
            $r['grid'][] = xy6802g68($x, $y);
          }
        }
      }
    } else {
      $r['error'] = 'poly fail';
      $r['code'] = 10;
    }
    imagedestroy($img);
  } else {
    $r['error'] = 'no coordinates';
    $r['code'] = 20;
  }
  return ($r);
}


/**
 * Converts X/Y 680x680 to 68x68 grid reference number.
 *
 * @param int $cX pixel x positon
 * @param int $cY pixel y positon
 * @return int grid reference number
 */

function xy6802g68($cX, $cY) {
  $calcX = ceil($cX / 10) - 1;
  $calcY = ceil($cY / 10) - 1;
  $grid68 = $calcX + ($calcY * 68);
  return ($grid68);
}

优化方案(基于inpoly算法)

将inpoly点-in-多边形检测算法移植到PHP后,性能比GD库版本提升168倍,且输出结果完全一致。

function segments_to_grid2($p, $r) {

  // Define base dimensions
  $vertx = $verty = [];
  $min_x = $min_y = 680;
  $max_x = $max_y = 0;

  foreach ($p['segments'] as $segment) {
    $vertx[] = $segment[0];
    $verty[] = $segment[1];
    $min_x = min($min_x, $segment[0]);
    $min_y = min($min_y, $segment[1]);
    $max_x = max($max_x, $segment[0]);
    $max_y = max($max_y, $segment[1]);
  }

  if (!empty($vertx)) {
    $nvert = count($vertx);
    for ($y = $min_y; $y < $max_y; $y = $y + 10) {
      for ($x = $min_x; $x < $max_x; $x = $x + 10) {
        if (inpoly($nvert, $vertx, $verty, $x, $y)) {
          $r['grid'][] = xy6802g68($x, $y);
        }
      }
    }
  }
  return $r;
}

function inpoly($nvert, $vertx, $verty, $testx, $testy) {
  $i = $j = $c = 0;
  for ($i = 0, $j = $nvert - 1; $i < $nvert; $j = $i++) {
    if ((($verty[$i] > $testy) != ($verty[$j] > $testy)) && ($testx < ($vertx[$j] - $vertx[$i]) * ($testy - $verty[$i]) / ($verty[$j] - $verty[$i]) + $vertx[$i])) {
      $c = !$c;
    }
  }
  return $c;
}

性能测试结果

对两个版本各运行100次的耗时统计:

  • GD库版本:[segments_to_grid] => 0.0027089119 seconds
  • inpoly版本:[segments_to_grid2] => 0.0001449585 seconds

inpoly版本性能提升168倍,完全满足高并发处理需求。


内容的提问来源于stack exchange,提问作者Andy Gee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 15:24:23