1

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

我正在解析一些作为几何类型插入的 MySQL 数据,使用 PHPunpack()作为我的解析器,一切都很顺利,直到我开始尝试解压缩复杂的几何类型(例如MULTIPOINT)。

对于一种POINT数据类型,我使用一种简单地忽略第一个块然后给我一个关联数组 , 和 的解包模式取得了type很好orderlat成功lon

$coords = unpack('x/x/x/x/corder/Ltype/dlat/dlon', $point);
// >>> [
//       'order' => 1,
//       'type' => 1,
//       'lat' => (expected value),
//       'lon' => (expected value)
//     ];

自然地,将完全相同的模式应用于MULTIPOINT几何图形并不会产生相同的效果。它得到orderandtype变成 4,但是latand的值lon根本不是我所期望的。所以,好奇地想看看整个东西是什么样子的,我改变了模式,把它全部吐出来作为“双(机器依赖的大小和表示)”类型:

$coords = unpack('x/x/x/x/corder/Ltype/d*', $multipoint);
// >>> mayhem

解包的内容实际上包括五个额外的数组项,而不是我期望的具有两个点 (2x2) 的多点的 4 个,并且这些值完全是古怪的。例如,我希望在 40-something-point-whatever 范围内的某个值看起来像是-1.0977282851114052e-218.

打开包装的正确方法是MULTIPOINT什么?我的直觉告诉我,我正在对不应该的字节进行切片,或者将它们转换为不合适的类型,但我不确定那些应该是什么。

4

1 回答 1

1

看了一些,但我找到了各种几何图形的 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)')))

额外的字节不会被添加。

于 2018-10-10T16:02:50.263 回答