如何在PHP中解压缩MySQL Multipoint几何数据?

时间:2018-10-10 14:41:43

标签: php mysql unpack mysql-spatial

好的,我想我已经很接近了,但是我对二进制数据的理解受到了限制。

我正在使用PHP的unpack()作为解析器来解析一些作为几何类型插入的MySQL数据,并且一切都进行得很顺利,直到我开始尝试解压缩复杂的几何类型(例如MULTIPOINT)为止。 / p>

对于POINT数据类型,我使用了一个简单的无包模式就获得了成功,该模式不理会第一个块,然后给我一个typeorder,{ {1}}和lat

lon

自然地,将完全相同的图案应用于$coords = unpack('x/x/x/x/corder/Ltype/dlat/dlon', $point); // >>> [ // 'order' => 1, // 'type' => 1, // 'lat' => (expected value), // 'lon' => (expected value) // ]; 几何体是行不通的。它得到MULTIPOINT,而order变成4,但是typelat的值根本不是我期望的。因此,很好奇整个外观,我更改了模式,将其全部喷出为“ double(与机器有关的大小和表示形式)”类型:

lon

解包的内容实际上包括 5 个额外的数组项,而不是我期望的具有两个点(2x2)的多点的4个,并且这些值完全是错误的。例如,我希望该值在40左右点的任何范围内,似乎读取的是$coords = unpack('x/x/x/x/corder/Ltype/d*', $multipoint); // >>> mayhem

解压缩-1.0977282851114052e-218的正确方法是什么?我的直觉是我将不应该分割的字节切成薄片或将其转换为不合适的类型,但是我不确定应该是什么。

1 个答案:

答案 0 :(得分:1)

花点时间看一下,但是我发现a reference是各种几何的WKB格式。正如我通过查看

的输出所猜到的
SELECT HEX(ST_GeomFromText('MULTIPOINT(1 1, 2 2, 3 3)'))

在顺序和类型后面有一个点数。挑战在于,为每个点重新声明顺序和类型,并且unpack没有重复一组字节的概念。因此,您需要为每个点提取字节,然后再次对它们运行unpack。显然,一旦您尝试考虑更多的空间类型,这将开始涉及更多。

<?php
$multipoint_wkb = hex2bin("000000000104000000030000000101000000000000000000F03F000000000000F03F010100000000000000000000400000000000000040010100000000000000000008400000000000000840");

function unpack_multipoint($multipoint)
{
    $data = unpack("x4/corder/Ltype/Lcount", $multipoint);
    for ($i = 0; $i < $data["count"]; $i++) {
        // the header is 1+4+8 bytes and each point record is 1+4+8+8 bytes
        $offset = ($i * 21) + 13;
        $return[] = unpack("corder/Ltype/dlat/dlon", $multipoint, $offset);
    }
    return $return;
}

print_r(unpack_multipoint($multipoint_wkb));

值得注意的是,这4个NUL字节由MySQL插入,但不属于实际的几何对象。我根据您的问题将它们保留在原处,但是如果您使用ST_AsWKB函数检索数据:

SELECT HEX(ST_AsWKB(ST_GeomFromText('MULTIPOINT(1 1, 2 2, 3 3)')))

多余的字节不作前缀。