Reputation: 339
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.
Upvotes: 0
Views: 1378
Reputation: 9142
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);
See: http://codepad.viper-7.com/VsuD1G
Upvotes: 2