简化数组中的数据以平滑PHP中的曲线
I'm using an API to get elevation data for GPX points, and try to create a graphic representation of it. My problem is that each point in the API is separated by 90meters, and my GPX points are separated by 5meters, causing several points in a row to have the same altitude before changing abruptly to a new altitude.
Basically, I obtain an array like this one:
[0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15...]
How would you draw it as a PNG image representation of the altitudes while easing the curves? I need to be able to change the size of the output picture.
I'm trying to change my array to something like that but I'm not sure how to do it and if this is the best solution:
[0, 0, 0, 0, 5, 5, 10, 10, 10, 12, 13, 15, 15, 15, 15...]
Thanks for any hints, I'm not used to work on pictures and data easing.
我正在使用API来获取GPX点的高程数据,并尝试创建它的图形表示。 我的问题是API中的每个点相隔90米,我的GPX点相隔5米,导致连续几个点在突然变为新的高度之前具有相同的高度。 p>
基本上,我得到一个像这样的数组: p>
[0,0,0,0,0,10,10,10,10,10,15,15,15 ,15,15 ......] p>
如何在缓和曲线的同时将其绘制为高度的PNG图像表示? 我需要能够改变输出图像的大小。 p>
我正在尝试将我的阵列更改为类似的东西,但我不知道该怎么做,如果这样 是最好的解决方案: p>
[0,0,0,0,5,5,10,10,10,12,13,15,15,15,15 ......] p>
感谢任何提示,我不习惯处理图片和数据缓和。 p> div>
Here's a basic way to smooth the points on an "average" basis:
<?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);
Results in:
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
To increase smoothing, you'll need a more elaborate method that has look-ahead's, look-behind's, and a higher amount of sampling... you could probably also interpolate between points -- but I excluded that in the sample above. To do interpolation, you could do the below:
<?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);
Which will yield:
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
To draw an image, we'll need more info. The points in the array are not 2D... meaning there's no X or Y, unless we assume that each point increases the X axis by one pixel? If so, here's a rough shot:
$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);