dow46218 2015-07-23 16:35
浏览 106
已采纳

简化数组中的数据以平滑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.

  • 写回答

1条回答 默认 最新

  • douyan4470 2015-07-23 16:52
    关注

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)