简化数组中的数据以平滑PHP中的曲线

时间:2015-07-23 16:35:18

标签: php arrays draw easing

我使用API​​获取GPX点的高程数据,并尝试创建它的图形表示。我的问题是,API中的每个点相隔90米,我的GPX点相隔5米,导致连续几个点的高度相同,然后突然变为新的高度。

基本上,我得到一个像这样的数组:

[0,0,0,0,0,10,10,10,10,10,15,15,15,15,15 ......]

如何在缓和曲线的同时将其绘制为高度的PNG图像表示?我需要能够改变输出图像的大小。

我试图将我的阵列更改为类似的内容,但我不知道该怎么做以及这是否是最佳解决方案:

[0,0,0,0,5,5,10,10,10,12,13,15,15,15,15 ......]

感谢任何提示,我不习惯处理图片和数据缓和。

1 个答案:

答案 0 :(得分:2)

这是平滑"平均值"的基本方法。基础:

<?php
$points = [0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15];
$refined = [];

foreach($points as $index => $point) {
  // make sure we don't divide by 0
  $prev = isset($points[$index - 1]) ? $points[$index - 1] : false;
  $next = isset($points[$index + 1]) ? $points[$index + 1] : false;

  if($point > 0 || ($prev && $prev > 0) || ($next && $next > 0)) {
    $total = $point;
    if($prev) {
      $total += $prev;
      $total = $total / 2;
    } 

    if($next) {
      $total += $next;
      $total = $total / 2;
    }

    $refined[] = round($total, 0);
  } else {
    $refined[] = $point;
  }
}

echo implode(" ", $points);
echo "<hr>";
echo implode(" ", $refined);

结果:

0 0 0 0 0 10 10 10 10 10 15 15 15 15 15
---------------------------------------
0 0 0 0 5 10 10 10 10 13 14 15 15 15 15

为了增加平滑度,您需要一个更精细的方法,具有超前预测,后视和更高的采样量...您可能还需要在两者之间进行插值积分 - 但我在上面的示例中排除了这一点。要进行插值,您可以执行以下操作:

<?php
$points = [0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15];
$refined = [];

foreach($points as $index => $point) {
  $prev = isset($points[$index - 1]) ? $points[$index - 1] : false;
  $next = isset($points[$index + 1]) ? $points[$index + 1] : false;

  if($point > 0 || ($prev && $prev > 0) || ($next && $next > 0)) {
    $refined[] = $point;

    while($next && $point < $next) {
      $point++;
      $refined[] = $point;
    }
  } else {
    $refined[] = $point;
  }
}

echo implode(" ", $points);
echo "<hr>";
echo implode(" ", $refined);

将产生:

0 0 0 0 0 10 10 10 10 10 15 15 15 15 15
---------------------------------------------------------------------------
0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 11 12 13 14 15 15 15 15 15 15

要绘制图像,我们需要更多信息。数组中的点不是2D ...意味着没有X或Y,除非我们假设每个点将X轴增加一个像素?如果是这样,这是一个粗略的镜头:

$width = count($refined);
$height = max($refined);

$gd = imagecreatetruecolor($width, $height);

// Allocate a color
$red = imagecolorallocate($gd, 255, 0, 0); 

foreach($refined as $x => $y) {
  imagesetpixel($gd, $x, $height-$y, $red);
}

header('Content-Type: image/png');
imagepng($gd);

请参阅:http://codepad.viper-7.com/VsuD1G