PHP中的插值

6
我正在寻找一个PHP函数,用于将一组不规则放置的数据(x,y,z)插值到网格化数据集中,以便在JPGraph的ContourPlot函数中使用。 我已经开发了一个基于简单的反距离加权的函数,但它太慢了。 我需要使用另一种方法,例如“修改后的Shepard方法”或任何其他可能具有更高精度的方法,使其更快,更平滑。
这是我的当前代码:
for($i = 0, $ij = 0; $i < $gridX; $i ++) {
    for($j = 0; $j < $gridY; $j ++, $ij ++) {
        $x = $startP->x + ($deltaX * $i);
        $y = $startP->y + ($deltaY * $j);
        $g [$ij]->i = $i;
        $g [$ij]->j = $j;
        $g [$ij]->x = ( int ) $x;
        $g [$ij]->y = ( int ) $y;
        $g [$ij]->z = IDW_U ( $x, $y, $sampleData, $sampleSize, $p );
    }
}

function IDW_U($x, $y, $data, $size, $p) {
    $idw_sum = IDWeightSum ( $x, $y, $data, $size, $p );
    $idw_u = 0.0;
    for($k = 0; $k < $size; $k ++) {
        if ($x == $data [$k]->x && $y == $data [$k]->y)
            return $data [$k]->z;
        $idw_u += IDWeight ( $x, $y, $data [$k], $p ) * $data [$k]->z / $idw_sum;
    }
    return $idw_u;
}

function IDWeightSum($x, $y, $data, $size, $p) {
    $sum = 0.0;
    for($k = 0; $k < $size; $k ++)
        $sum += IDWeight ( $x, $y, $data [$k], $p );
    return $sum;
}

function IDWeight($x, $y, $d, $p) {
    if ($x == $d->x && $y == $d->y)
        return 1.0;
    $dx = $x - $d->x;
    $dy = $y - $d->y;
    $ret = 1.0 / pow ( sqrt ( pow ( $dx, 2 ) + pow ( $dy, 2 ) ), $p );
    return $ret;
}

有人知道可用于此目的的函数或库吗?


1
发布你的运行缓慢的代码。可能有一些重要的优化可以实现... - ircmaxell
嗯,我认为 gnuplot 可以实现与 JPGraph 相同甚至更好的插值和生成效果。也许这是一个选择?不过学习曲线有点陡峭,我可以很肯定地说我不知道 gnuplot 能做到的 2%。 - Wrikken
5
这份赏金可能会帮助你获得一些答案。 - Andy E
这并没有解决真正的问题,但您可能会对 Facebook 的 HipHop 感兴趣,它通过编译成本机代码来加速 PHP。http://developers.facebook.com/blog/post/358 - Michael Mior
4个回答

3
据我所见,IDWeight被频繁调用。您可以通过以下方式计算IDW_U来减少一半的调用次数:
function IDW_U($x, $y, $data, $size, $p) {
$idw_sum = 0.0;
$idw_u = 0.0;
for($k = 0; $k < $size; $k ++) {
    if ($x == $data [$k]->x && $y == $data [$k]->y)
        return $data [$k]->z;
    $iw = IDWeight ( $x, $y, $data [$k], $p )
    $idw_u += $iw * $data [$k]->z;
    $idw_sum += $iw;
}
return $idw_u / $idw_sum;
}

我认为主要问题在于,计算一个像素时使用了所有数据集,而其中大部分数据对计算影响很小。如果将数据分成小区域并分别计算每个区域,可以真正提高性能。


1

我不确定PHP是否是处理数学密集型功能的好选择。然而,有许多图形库可用,其中代码已经过优化,放入了DLL等等。

我们使用高级软件工程ChartDirector PHP Charting 绘制一些相当复杂的图形,并且速度很快。我不确定它是否包含您感兴趣的算法,但它确实包括一些像LOWESS这样的算法。我看到的主要问题是您正在处理X,Y和Z。处理第三个维度并不是最常见的特性。我不确定这个库是否真的支持这个...


感谢您的推荐。虽然我必须有自己的代码,但我看了一下并测试了它作为替代方案。实际上它很好用。它有一个用于创建散点数据轮廓图的函数,而且速度非常快。 - Fred

0

通过引用传递数据可能会对您有所帮助:

 function IDW_U($x, $y, &$data, $size, $p) ...
 function IDWeightSum($x, $y, &$data, $size, $p) ...

0

如果你不局限于PHP,就应该尽可能地把这些密集型处理的工作从PHP上转移出来。PHP是一种较慢的语言(我上次查看时——大约一年前,Python和Ruby都比它表现出色,以及C、C++和Java)。

因此,通过切换到离线绘图工具(如评论中提到的gnuplot),重新运行性能测试,并在必要时将算法切换到Python或Ruby脚本或编译后的C或C++应用程序,可以获得性能提升。

然而,我没有找到有关PHP相对于其他语言的更多最新性能数据,自2008年末/2009年初以来——我的数据可能已经不准确了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接