Облегчить данные в массиве, чтобы сгладить кривую в переполнении стека

Я использую 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 …]

Спасибо за любые подсказки, я не привык работать с фотографиями и смягчением данных.

0

Решение

Вот основной способ сглаживания точек на «средней» основе:

<?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

Чтобы нарисовать изображение, нам нужно больше информации. Точки в массиве не являются двумерными … то есть нет 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

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]