Как распаковать данные многоточечной геометрии MySQL в PHP?

Хорошо, я думаю, что я близок к этому, но я испытываю ограничение в моем понимании двоичных данных.

Я анализирую некоторые данные 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

Что это на самом деле распаковывает включает 5 дополнительные элементы массива, вместо 4 я бы ожидал для многоточечной с двумя точками (2×2), и значения совершенно ненормальные. Например, значение, которое я ожидаю, должно быть где-то в диапазоне 40 с чем-то — независимо от того, что кажется, что-то вроде -1.0977282851114052e-218,

Как правильно распаковать MULTIPOINT? Мой инстинкт говорит, что я нарезаю байты там, где я не должен, или преобразую их в неподходящий тип, но я не уверен, какими они должны быть.

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)')))

дополнительные байты не добавляются.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]