如何在 PHP 中解压 MySQL 多点几何数据?
Posted
技术标签:
【中文标题】如何在 PHP 中解压 MySQL 多点几何数据?【英文标题】:How to unpack MySQL Multipoint geometry data in PHP? 【发布时间】:2018-10-10 14:41:42 【问题描述】:好的,我想我已经接近了,但我对二进制数据的理解遇到了限制。
我正在解析一些作为几何类型插入的 mysql 数据,使用 php 的 unpack()
作为我的解析器,一切都顺利进行,直到我开始尝试解压缩复杂的几何类型(例如 MULTIPOINT
)。
对于POINT
数据类型,我使用一种简单地忽略第一个块然后给我一个type
、order
、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
和type
变为4,但lat
和lon
的值根本不是我所期望的。所以,好奇地想看看整个东西是什么样子的,我改变了模式,把它全部吐出来作为“双(机器依赖的大小和表示)”类型:
$coords = unpack('x/x/x/x/corder/Ltype/d*', $multipoint);
// >>> mayhem
解包的内容实际上包括 五个 额外的数组项,而不是我期望的 4 个,用于具有两个点 (2x2) 的多点,而且这些值完全是古怪的。例如,我希望在 40-something-point-whatever 范围内的某个值看起来像是 -1.0977282851114052e-218
。
解压MULTIPOINT
的正确方法是什么? 我的直觉告诉我,我在不应该的地方分割字节,或者将它们转换为不合适的类型,但我不确定这些应该是什么。
【问题讨论】:
我假设你已经熟悉SELECT ST_AsText(points) FROM mytable
?
我是,谢谢。手动将点解析为文本是我最后的手段,因为可用的几何类型的广度将使用文本解析创建大量的正则表达式样板代码。图书馆感觉有点矫枉过正,但这也是最后的手段。我选择尝试从二进制文件中解包,因为它干净且高效,并且可以通过一行代码得到我想要的东西。至少在 POINT
类型上。
【参考方案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)')))
额外的字节不会被添加。
【讨论】:
经过测试和确认,这绝对有效,在这两个方面!感谢关于额外 4 个字节的额外提示,感觉真的很臭。现在我认为挑战将是决定构建这些实用函数 is 实际上是否会比字符串解析工作更少。很多东西要咀嚼。问题得到了很好的回答,+ 参考引导。 很高兴提供帮助,总是很高兴看到来自低代表用户的 PHP 问题,而不仅仅是“give teh codez”;) 简化了一点,假设您使用的是 2 年前发布的 PHP >= 7.1。以上是关于如何在 PHP 中解压 MySQL 多点几何数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 MySQL 中的 Multipolygon 中检索经纬度点