|
|
|
@ -1,5 +1,30 @@
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/* Copyright 2021 Netsyms Technologies.
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
|
|
|
|
provided that the following conditions are met:
|
|
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
|
|
|
and the following disclaimer.
|
|
|
|
|
|
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
|
|
|
|
conditions and the following disclaimer in the documentation and/or other materials provided with
|
|
|
|
|
the distribution.
|
|
|
|
|
|
|
|
|
|
3. Neither the name of the copyright holder nor the names of its contributors may be used to
|
|
|
|
|
endorse or promote products derived from this software without specific prior written permission.
|
|
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
|
|
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
|
|
|
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
|
|
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class FixPhrase {
|
|
|
|
|
|
|
|
|
|
private const WORDLIST = [
|
|
|
|
@ -7638,41 +7663,58 @@ class FixPhrase {
|
|
|
|
|
$lon = str_pad($lon, 7, "0", STR_PAD_LEFT);
|
|
|
|
|
|
|
|
|
|
// Split up coordinates into chunks, add offsets so no two words will be the same and order won't matter
|
|
|
|
|
$lat1dec = (int) substr($lat, 0, 4);
|
|
|
|
|
$lon1dec = (int) substr($lon, 0, 4);
|
|
|
|
|
$latlon2dec = (int) (substr($lat, 4, 2) . substr($lon, 4, 1));
|
|
|
|
|
$latlon4dec = (int) (substr($lat, 6, 1) . substr($lon, 5, 2));
|
|
|
|
|
|
|
|
|
|
$groups = [
|
|
|
|
|
(int) substr($lat, 0, 4) + 0,
|
|
|
|
|
((int) substr($lon, 0, 4)) + 2000,
|
|
|
|
|
((int) substr($lat, 4, 3)) + 5610,
|
|
|
|
|
((int) substr($lon, 4, 3)) + 6610
|
|
|
|
|
$lat1dec + 0,
|
|
|
|
|
$lon1dec + 2000,
|
|
|
|
|
$latlon2dec + 5610,
|
|
|
|
|
$latlon4dec + 6610
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return implode(" ", [self::WORDLIST[$groups[0]], self::WORDLIST[$groups[1]], self::WORDLIST[$groups[2]], self::WORDLIST[$groups[3]]]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert a phrase into coordinates.
|
|
|
|
|
* @param string $words
|
|
|
|
|
* @return array [latitude, longitude, accuracy (degrees), phrase]
|
|
|
|
|
* @throws Exception If the phrase is not valid.
|
|
|
|
|
*/
|
|
|
|
|
public static function decode(string $words): array {
|
|
|
|
|
$indexes = [-1, -1, -1, -1];
|
|
|
|
|
|
|
|
|
|
$words = explode(" ", $words);
|
|
|
|
|
$words = explode(" ", strtolower($words));
|
|
|
|
|
|
|
|
|
|
$canonicalphrase = ["", "", "", ""];
|
|
|
|
|
|
|
|
|
|
if (count($words) < 2) {
|
|
|
|
|
throw new Exception("Not enough words!");
|
|
|
|
|
} else if (count($words) > 4) {
|
|
|
|
|
throw new Exception("Too many words!");
|
|
|
|
|
//throw new Exception("Too many words!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert words back into indices and do the math to make them coordinate chunks
|
|
|
|
|
foreach ($words as $word) {
|
|
|
|
|
$index = array_search($word, self::WORDLIST);
|
|
|
|
|
if ($index === false) {
|
|
|
|
|
throw new Exception("Unrecognized word found!");
|
|
|
|
|
//throw new Exception("Unrecognized word found!");
|
|
|
|
|
}
|
|
|
|
|
if ($index >= 0 && $index < 2000) {
|
|
|
|
|
$indexes[0] = $index;
|
|
|
|
|
$canonicalphrase[0] = self::WORDLIST[$index];
|
|
|
|
|
} else if ($index >= 2000 && $index < 5610) {
|
|
|
|
|
$indexes[1] = $index - 2000;
|
|
|
|
|
$canonicalphrase[1] = self::WORDLIST[$index];
|
|
|
|
|
} else if ($index >= 5610 && $index < 6610) {
|
|
|
|
|
$indexes[2] = $index - 5610;
|
|
|
|
|
$canonicalphrase[2] = self::WORDLIST[$index];
|
|
|
|
|
} else if ($index >= 6610 && $index < 7610) {
|
|
|
|
|
$indexes[3] = $index - 6610;
|
|
|
|
|
$canonicalphrase[3] = self::WORDLIST[$index];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -7684,18 +7726,43 @@ class FixPhrase {
|
|
|
|
|
$lat = str_pad((string) $indexes[0], 4, "0", STR_PAD_LEFT);
|
|
|
|
|
$lon = str_pad((string) $indexes[1], 4, "0", STR_PAD_LEFT);
|
|
|
|
|
|
|
|
|
|
// Get the last three digits of each coordinate
|
|
|
|
|
// Get second decimal for latitude and longitude
|
|
|
|
|
if ($indexes[2] != -1) {
|
|
|
|
|
$divby = 100.0;
|
|
|
|
|
$latlon2dec = str_pad((string) $indexes[2], 3, "0", STR_PAD_LEFT);
|
|
|
|
|
$lat .= substr($latlon2dec, 0, 1);
|
|
|
|
|
$lon .= substr($latlon2dec, 2, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get third and fourth latitude and fourth longitude
|
|
|
|
|
if ($indexes[2] != -1 && $indexes[3] != -1) {
|
|
|
|
|
$divby = 10000.0;
|
|
|
|
|
$lat .= str_pad((string) $indexes[2], 3, "0", STR_PAD_LEFT);
|
|
|
|
|
$lon .= str_pad((string) $indexes[3], 3, "0", STR_PAD_LEFT);
|
|
|
|
|
$latlon4dec = str_pad((string) $indexes[3], 3, "0", STR_PAD_LEFT);
|
|
|
|
|
$lat .= substr($latlon2dec, 1, 1) . substr($latlon4dec, 0, 1);
|
|
|
|
|
$lon .= substr($latlon4dec, 1, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make them normal coordinates again with +/- and 0-90 or 0-180
|
|
|
|
|
$latitude = round((((int) $lat) / $divby) - 90.0, 4);
|
|
|
|
|
$longitude = round((((int) $lon) / $divby) - 180.0, 4);
|
|
|
|
|
|
|
|
|
|
return [$latitude, $longitude];
|
|
|
|
|
switch ($divby) {
|
|
|
|
|
case 10.0:
|
|
|
|
|
$latitude += 0.05;
|
|
|
|
|
$longitude += 0.05;
|
|
|
|
|
$accuracy = 0.1;
|
|
|
|
|
break;
|
|
|
|
|
case 100.0:
|
|
|
|
|
$latitude += 0.005;
|
|
|
|
|
$longitude += 0.005;
|
|
|
|
|
$accuracy = 0.01;
|
|
|
|
|
break;
|
|
|
|
|
case 10000.0:
|
|
|
|
|
$accuracy = 0.0001;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [round($latitude, 4), round($longitude, 4), $accuracy, trim(implode(" ", $canonicalphrase))];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|