在 PHP 中从多边形二进制数据中提取纬度和经度

问题描述 投票:0回答:1

我正在开发一个项目,需要使用 PHP 将多边形二进制数据转换为纬度和经度值数组。我尝试解压二进制数据并将其组织成纬度和经度对,但结果似乎不正确或意外。

[
{
"lat": 1664102448,
"lng": 1717986098
},
{
"lat": 7.786440148571508e-71,
"lng": 1.0408844853708164e-42
},
{
"lat": 4.018325444174134e-57,
"lng": 3.759239572441829e+179
},
{
"lat": 1.3705601230760044e-71,
"lng": 2.1264453324229065e+160
},
{
"lat": 2.3429384547438525e-56,
"lng": 1.657195585293228e-76
},
{
"lat": 1.4844049716462333e-76,
"lng": 1.4864290736513336e-76
},
]

我拥有的多边形二进制数据代表地理坐标,我正在尝试从该数据中提取有意义的纬度和经度对。这是我尝试过的代码片段:

$wkbHex = '0001e6100000c2cff1357b2a1040af677f02539941403617e48e38781140b738adcb82bb41407c03000000010000006100000a3617e48e387811409111365a67aa414098e4b38b087811400cec49133eab4140fa454eb671771140c8ab4d4c14ac414096d2686574761140f1c11781e9ac4140cafb0a2f117511403028172ebdad414072d940e848731140cdb3a4d08eae414007aea6a41c711140aaeb53e75daf41408145cdb58d6e1140dc2e43f229b04140296b77aa9d6b114092f96a73f2b04140bfcbb04d4e6811408116eceeb6b1414058b4bea5a16411405a8b5ceb76b241409b36ebf299601140b80f13f231b34140e9552bae395c11405ade708fe7b34140d3faa08783571140ccb1295397b441407482f9647a52114044be89d040b541407bd9a95f214d1140c67bb99ee3b54140582c09c37b4711400015ff587fb64140424b4b0a8d4111407950fd9e13b74140affc5bde583b114067cbef14a0b74140e48b9c13e3341140f75ee46324b84140c3fa84a72f2e1140a88af139a0b8414051512abe4227114041c0694a13b94140a69aab9f20201140a66f0b4e7db94140cd3287b5cd18114029b32d03deb94140e81ada874e111140e17ee92d35ba4140b0198bbaa7091140fe373f9882ba4140287f630ade011140199b3812c6ba41403270174af6f9104053db0672ffba4140a9ab3f5ff5f1104035e61c942ebb41406dc6463fe0e91040d2ba455b53bb4140f7e54becbbe1104091c5b6b06dbb4140c708fd718dd9104034341e847dbb41407ef36ae259d11040b738adcb82bb414036ded85226c9104034341e847dbb414005018ad8f7c0104091c5b6b06dbb41408e208f85d3b81040d2ba455b53bb4140523b9665beb0104035e61c942ebb4140c776be7abda8104054db0672ffba4140d56772bad5a01040189b3812c6ba41404bcd4a0a0c991040ff373f9882ba414013ccfb3c65911040e17ee92d35ba414032b44e0fe689104029b32d03deb94140594c2a2593821040a56f0b4e7db94140ac95ab06717b104040c0694a13b9414033ec501d84741040a88af139a0b841401c5b39b1d06d1040f65ee46324b841404eea79e65a67104068cbef14a0b74140bb9b8aba266110407950fd9e13b74140a7bacc01385b10400015ff587fb64140790d2c6592551040c67bb99ee3b541408264dc5f3950104044be89d040b5414017ec343d304b1040ccb1295397b441400591aa167a4610405ade708fe7b341405fb0ead119421040b70f13f231b341409c32171f123e10405a8b5ceb76b24140301b2577653a10407f16eceeb6b14140d07b5e1a1637104090f96a73f2b041406fa1080f26341040d92e43f229b04140f1382f2097311040a8eb53e75daf4140820d95dc6a2f1040ccb3a4d08eae41402bebca95a22d10402f28172ebdad414068146d5f3f2c1040f1c11781e9ac4140ffa0870e422b1040c8ab4d4c14ac414060022239ab2a10400aec49133eab4140c2cff1357b2a10409111365a67aa4140eebeb2c34f2b1040432a9579baa84140f7b74679bd2d10401df983cb11a74140cf6e7529be311040ca4a446671a541405e3767c947371040c6d9344bdda34140dcd11a8b4c3e1040ba76fd5c59a241400c12ea00bb4610406cf50a56e9a04140fb82b7497e5010402db371bf909f41404c8c4c457e5b1040636e4ce8529e4140338f5ed09f671040d7daabdd329d4140e306a207c574104079e92963339c41409aea4491cd821040511e32ec569b4140a66b1dec96911040ed920e969f9a4140a69ccfc3fca01040b468c7220f9a4140caa12349d9b01040e77ae0f4a699414068a5be8d05c110400217ff0b689941407ef36ae259d11040af677f025399414093411737aee110400117ff0b689941402e45b27bdaf11040e77ae0f4a6994140534a0601b7011140b368c7220f9a41404e7bb8d81c111140ef920e969f9a414057fc9033e61f1140501e32ec569b414017e033bdee2d114077e92963339c4140b75777f4133b1140d7daabdd329d4140a95a897f35471140636e4ce8529e4140f9631e7b355211402db371bf909f4140ead4ebc3f85b11406bf50a56e9a041401315bb3967641140ba76fd5c59a241409aaf6efb6b6b1140c6d9344bdda341402078609bf5701140ca4a446671a54140032f8f4bf67411401df983cb11a741400728230164771140432a9579baa841403617e48e387811409111365a67aa4140fe
'; 

$unpack = unpack("VSRID/corder/ltype/Lnum_rings/Lnum_points/d*", $wkbHex, 0);
array_shift($unpack);
array_shift($unpack);

if (count($unpack)%2) {
    array_shift($unpack);
}

$data = array_chunk($unpack, 2);
$return = [];

for ($i = 0; $i < count($data); $i++) {
    $return[] = [
        'lat' => $data[$i][0],
        'lng' => $data[$i][1],
    ];
}

return $return;

但是,从此过程中获得的纬度和经度对未与预期坐标正确对齐。我怀疑我对二进制数据的解释或处理可能不正确。

php binary geometry
1个回答
0
投票

您应该将多边形的 WKB 格式解码为纬度和经度坐标,考虑字节顺序并从二进制数据中读取多边形结构(环和点的数量),如下所示

$wkbHex = ''; // add your WKB here

$wkbBinary = hex2bin($wkbHex);

//Check endianness
$endianness = unpack('C', $wkbBinary[0])[1];
$isLittleEndian = ($endianness === 1);

$format = $isLittleEndian ? 'Vtype/Lnum_rings/Lnum_points' : 'Ntype/Nnum_rings/Nnum_points';

$header = unpack($format, $wkbBinary);

$offset = 9;

$coordinates = [];
for ($ring = 0; $ring < $header['num_rings']; $ring++) {
    // Number of points in the ring
    $num_points = unpack('L', substr($wkbBinary, $offset, 4))[1];
    $offset += 4;

    for ($point = 0; $point < $num_points; $point++) {
        $latLng = unpack('d2', substr($wkbBinary, $offset, 16));
        $offset += 16;

        $coordinates[] = [
            'lat' => $latLng[1],
            'lng' => $latLng[2]
        ];
    }
}

return $coordinates;
© www.soinside.com 2019 - 2024. All rights reserved.