php - 如何在 PHP 中解压 MySQL 多点几何数据?

标签 php mysql unpack mysql-spatial

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

我正在解析一些作为几何类型插入的 MySQL 数据,使用 PHP 的 unpack() 作为我的解析器,一切进展顺利,直到我开始尝试解压复杂的几何类型(例如 多点).

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

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

自然地,将完全相同的模式应用于 MULTIPOINT 几何体的效果并不相同。它得到了order并且type变成了4,但是latlon的值根本不是什么我希望。因此,出于好奇想看看整个事情是什么样子,我改变了模式,将其全部吐出为“双(机器相关的大小和表示)”类型:

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

解包的内容实际上包括 五个 个额外的数组项,而不是我期望的 4 个多点(2x2),而且这些值完全是古怪的。例如,我希望某个值在 40 点左右范围内的某个位置,无论范围如何,它看起来都像 -1.0977282851114052e-218

解压 MULTIPOINT 的正确方法是什么?我的直觉告诉我我在不应该分割字节或将它们转换为不合适的类型,但是我不确定那些应该是什么。

最佳答案

看了一下,但我找到了 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)')))

额外的字节不在前面。

关于php - 如何在 PHP 中解压 MySQL 多点几何数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52742813/

相关文章:

php - 恢复解压 ('C*' , "string")

Python - 将二进制解码为 boolean 值

javascript - Ajax 联系表单中的文件上传不起作用

mysql - RDS 与 EC2 for MySQL 在故障转移/复制设置方面有何区别?

mysql - 在 MySQL 中使用单个查询从多个表中删除

mysql - 如何在mysql中使用case语句将3列数据合并到一个中

r - 在 R 中解压 rar 文件

php - 在php和mysql中显示每个组的成员数

php - 使用 preg_match() 连接正则表达式字符串中的变量

php - 是否可以计算数组中的键数?