用户可以输入不同形式的坐标:有或没有度数符号(分、秒)、点后有不同数量的数字和不同数量的空格。 UTM 格式中的坐标也可能会被错误地指定。 目标是将字符串转换为 WGS84 格式的两度值。 为简单起见,我们假设纬度和经度字母不会变化,因为坐标位于同一国家/地区。
这里的示例展示了一种从字符串获取坐标的可能方法:
<?php
// https://ru.wikipedia.org/wiki/. Преобразование_геодезических_систем_координат
// Online converter https://coordinates-converter.com/
function convert_DMS_2_deg($coord)
{
$coord = str_replace(',', '.', $coord);
preg_match_all('/\d+\.?\d{0,6}/', $coord, $mtch);
if (count($mtch[0]) === 1) return $mtch[0][0];
elseif (count($mtch[0]) === 2) return round($mtch[0][0]+((($mtch[0][1]*60))/3600), 6);
elseif (count($mtch[0]) >= 3) return round($mtch[0][0]+((($mtch[0][1]*60)+($mtch[0][2]))/3600), 6);
return false;
}
$patterns = array();
$patterns['lat'] = array();
$patterns['lng'] = array();
$wgs = <<<'WGS84'
World Geodetic System 1984 (WGS84)
Latitude: 48.8584° N, Longitude: 2.2945° E
Latitude: 66.84° S, Longitude: 36.5° W
72.123456, 66.123456
Decimal Degrees (DD)
40.446° N 79.982° W
Precede South latitudes and West longitudes with a minus sign.
Latitude (vertical axis) between -90° and +90°,
Longitude (horizontal axis) between -180° and +180°.
Up to 6 decimal places
The geographic coodinate system = horizontal datum + prime meridian + angular unit.
WGS84;
$patterns['lat']['wgs'] = '/^[^\d\+-]*[\+-]?(([1-8]?[0-9])([\.,]\d{1,6})?|90)\D*[NS]?\s*$/i';
$patterns['lng']['wgs'] = '/^[^\d\+-]*[\+-]?((1[0-7][0-9]|[1-9]?[0-9])([\.,]\d{1,6})?|180)\D*[EW]?\s*$/i';
// =====================================
$dms = <<<'DMS'
Degrees Minutes Seconds (DMS)
40° 26′ 46″ N 79° 58′ 56″ W
40° 26′ 46″ S 79° 58′ 56″ E
90° 0′ 0″ S 180° 0′ 0″ E
40° 26′ 45.9996″ N 79° 58′ 55.2″ E
Latitudes range from 0 to 90.
Longitudes range from 0 to 180.
Minutes & Seconds range from 0-60
Use N, S, E or W as either the last character,
which represents a compass direction North, South, East or West.
D & M must be intergers, S may be an interger or float.
DMS;
$patterns['lat']['dms'] = '/^[^\d]*(([1-8]?[0-9])\D+([1-5]?[0-9]|60)\D+([1-5]?[0-9]|60)([\.,][0-9]+)?|90\D+0\D+0)\D*[NS]*\s*$/i';
$patterns['lng']['dms'] = '/^[^\d]*((1[0-7][0-9]|[1-9]?[0-9])\D+([1-5]?[0-9]|60)\D+([1-5]?[0-9]|60)([\.,][0-9]+)?|180\D+0\D+0)\D*[EW]*\s*$/i';
// =====================================
$ddm = <<<'DDM'
Degrees Decimal Minutes (DDM)
40° 26.767′ N 79° 58.933′ W
90° 0′ N 180° 0′ W
90° N 180° W
Latitudes range from 0 to 90.
Longitudes range from 0 to 180.
Use N, S, E or W as either the last character,
which represents a compass direction North, South, East or West.
The last degree, minute, or second of a latitude or longitude
may contain a decimal portion.
DDM;
$ddm_pattern = '/^(\d{1,2})°\s+(\d{1,2})′\s+(\d{1,2})″\s+([NS])*';
$patterns['lat']['ddm'] = '/^[^\d]*(([1-8]?[0-9])\D+[1-6]?[0-9]([\.,]\d{1,3})?|90(\D+0)?)\D+([NSns])$/';
$patterns['lng']['ddm'] = '/^[^\d]*((1[0-7][0-9]|[1-9]?[0-9])\D+[1-6]?[0-9]([\.,]\d{1,3})?|180(\D+0)?)\D+([EWew])$/';
$mockings = [
['Latitude: 48.8584° N', 'Longitude: 2.2945° E'],
[ '66.84° S', '36.5° W'],
[ '72.123456', '66.123456'],
[ '71,456°', '62,6'],
['40° 26′ 46″ N', '79° 58′ 56″ W'],
['40° 26′ 46″ S', '79° 58′ 56″ E'],
['90° 0′ 0″ S', '180° 0′ 0″ E'],
['40° 26′ 45.9996″', '79° 58′ 55.2″ '],
['40° 26.767′ N', '79° 58.933′ W'],
['90° 26′ S', '180° 58′ E'],
['72° 12′ ', '120° 22′ '],
['89 12′ N', '179° 58′ '],
];
// var_dump($mockings);
foreach ($mockings as $mocking => $coords)
{
$lat = $coords[0];
$lng = $coords[1];
echo "_________________________\n";
// echo 'Mocking: '.($mocking+1)."\n";
echo "Lat: $lat\n";
echo "Lng: $lng\n";
// if (preg_match($patterns['lat']['wgs'], $lat) && preg_match($patterns['lng']['wgs'], $lng))
// {
// echo "===WGS\n";
// }
// if (preg_match($patterns['lat']['ddm'], $lat) && preg_match($patterns['lng']['ddm'], $lng))
// {
// echo "===DDM\n";
// }
// if (preg_match($patterns['lat']['dms'], $lat) && preg_match($patterns['lng']['dms'], $lng))
// {
// echo "===DMS\n";
// }
preg_match_all('/\d+[\.,]?\d{0,6}/', $lat, $matches_lat);
preg_match_all('/\d+[\.,]?\d{0,6}/', $lng, $matches_lng);
if (count($matches_lat[0]) === 1 && count($matches_lng[0]) === 1)
{
// echo "---WGS\n";
echo '>Lat: '.$matches_lat[0][0].' ('.convert_DMS_2_deg($lat).')'."\n";
echo '>Lng: '.$matches_lng[0][0].' ('.convert_DMS_2_deg($lng).')';
echo "\n";
}
elseif (count($matches_lat[0]) === 2 && count($matches_lng[0]) === 2)
{
// echo "---DDM\n";
// echo 'Lat: '.$matches_lat[0][0].' '.$matches_lat[0][1]."\n";
echo '>Lat_WGS: '.$matches_lat[0][0]+((($matches_lat[0][1]*60))/3600).' ('.convert_DMS_2_deg($lat).')'."\n";
// echo 'Lng: '.$matches_lng[0][0].' '.$matches_lng[0][1]."\n";
echo '>Lng_WGS: '.$matches_lng[0][0]+((($matches_lng[0][1]*60))/3600).' ('.convert_DMS_2_deg($lng).')';
echo "\n";
}
elseif (count($matches_lat[0]) === 3 && count($matches_lng[0]) === 3)
{
// echo "---DMS\n";
// echo 'Lat: '.$matches_lat[0][0].' '.$matches_lat[0][1].' '.$matches_lat[0][2]."\n";
echo '>Lat_WGS: '.$matches_lat[0][0]+((($matches_lat[0][1]*60)+($matches_lat[0][2]))/3600).' ('.convert_DMS_2_deg($lat).')'."\n";
// echo 'Lng: '.$matches_lng[0][0].' '.$matches_lng[0][1].' '.$matches_lng[0][2]."\n";
echo '>Lng_WGS: '.$matches_lng[0][0]+((($matches_lng[0][1]*60)+($matches_lng[0][2]))/3600).' ('.convert_DMS_2_deg($lng).')';
echo "\n";
}
unset($matches_lat);
unset($matches_lng);
echo "\n";
}