Pass any longitude/latitude coordinate to function arrDecimalDegrees() and it will return an array with the coordinate in decimal degrees. Pass the longitude/latitude in decima degrees to function arrLatLonFmtsFromDecDeg() and it will return an array with all of the various latitude/longitude formats as both strings, and float numbers.
// The main function arrDecimalDegrees() returns
// decimal degrees from a variety of lat/long string
// formats.
// Alternative formats are returned by passing Decimal Degrees
// to the function arrLatLonFmtsFromDecDeg().
// Demonstration of function arrDecimalDegrees() and arrLatLonFmtsFromDecDeg().
$arrStrLatLon = arrStrLatLonFmts();
foreach ($arrStrLatLon as $sLatLonFmt) {
$arrDecDeg = arrDecimalDegrees($sLatLonFmt,false);
if ($arrDecDeg == false) {
echo '"'.$sLatLonFmt.'" ERROR - arrDecimalDegrees() invalid format or characters
';
} else {
echo ''.$arrDecDeg['src'].' '.$sLatLonFmt.' -> '.number_format($arrDecDeg['lat'],4).','.number_format($arrDecDeg['lon'],4).'
';
$arrLatLonFormats = arrLatLonFmtsFromDecDeg($arrDecDeg['lat'],$arrDecDeg['lon'], false);
if ($arrLatLonFormats === false) {
echo 'ERROR - unable to extract formats via arrLatLonFmtsFromDecDeg() from '.number_format($arrDecDeg['lat'],4).','.number_format($arrDecDeg['lon'],4).' '.$arrDecDeg['src'].'
';
} else {
foreach ($arrLatLonFormats as $key => $dLatLon) {
echo ' '.$key.' '.$dLatLon.'
';
} // foreach
}
}
//die();
} // foreach
// Sample of output:
//DegMinSec 37 31 56.4, -80 45 30.6 -> 37.5323,-80.7585
// DecimalDegrees 37.5323, -80.7585
// DegMinSec 37 31 56, -80 45 31
// Garmin N37 31.9400, W, -80 45.5100
// DegMinDecSec 37 31 56.400, -80 45 30.600
// DegDecMin 37 31.9400, -80 45.5100
// NMEA 3731.9400, -8045.5100
// dDeg 37, -80
// dMin 31, 45
// dSec 56, 31
// dDecMin 31.94, 45.51
// dDecSec 56.4, 30.6
function arrLatLonFmtsFromDecDeg($dLat, $dLon, $bVerbose) {
// Return an array with all of the various latitude and
// longitude formats derived from $dLat and $dLon in
// decimal degrees.
// Returns FALSE on error.
if ((is_float($dLat) === false) || (is_float($dLon) === false)) return false;
if (($dLat > 90.0) || ($dLat < -90.0) || ($dLon > 180.0) || ($dLon < -180.0)) {
if ($bVerbose == true) echo 'ERROR - lat &/or long out of range '.$sLatLon.' -> '.number_format($arrLatLon['lat'],1).','.number_format($arrLatLon['lon'],1).'
';
return false;
}
// DecimalDegrees 37.5324,-80.7585
// Garmin N37 31 56.4,W80 45 30.6
// DegMinDecSec 37 31 56.4,-80 45 30.6
// DegDecMin 37 31.9404,-80 45.5100
// DegMinSec 37° 31' 56",-80° 45' 31"
// NMEA 3731.9404,-8045.51
unset($dSign,$dDeg,$dMin,$dSec,$dDeg,$arrReturn);
// latitude
$dSign = 1.0;
if ($dLat < 0) $dSign = -1.0;
$dDeg = intval(abs($dLat));
$dMin = intval(60.0*(abs($dLat)-$dDeg));
$dSec = 3600.0*(abs($dLat)-$dDeg-$dMin/60);
$dDeg = $dDeg * $dSign;
$arrReturn['DecimalDegrees'] = number_format($dLat,4);
$arrReturn['DegMinSec'] = number_format($dDeg,0).' '.number_format($dMin,0).' '.number_format(round($dSec,0,PHP_ROUND_HALF_UP),0);
if ($dSign > 0.0) {
$arrReturn['Garmin'] = 'N';
} else {
$arrReturn['Garmin'] = 'S';
}
$arrReturn['Garmin'] .= number_format(abs($dDeg),0).' '.number_format($dMin,0).' '.number_format($dSec,3);
$arrReturn['DegMinDecSec'] = number_format($dDeg,0).' '.number_format($dMin,0).' '.number_format($dSec,3);
$arrReturn['DegDecMin'] = number_format($dDeg,0).' '.number_format($dMin+$dSec/60.0,4);
$arrReturn['NMEA'] = number_format($dDeg,0).number_format($dMin+$dSec/60.0,4);
$arrReturn['dDeg'] = round($dDeg,0,PHP_ROUND_HALF_UP);
$arrReturn['dMin'] = round($dMin,0,PHP_ROUND_HALF_UP);
$arrReturn['dSec'] = round($dSec,0,PHP_ROUND_HALF_UP);
$arrReturn['dDecMin'] = round($dMin+$dSec/60,4,PHP_ROUND_HALF_UP);
$arrReturn['dDecSec'] = round($dSec,4,PHP_ROUND_HALF_UP);
// longitude
unset($dSign,$dDeg,$dMin,$dSec,$dDeg);
$dSign = 1.0;
if ($dLon < 0) $dSign = -1.0;
$dDeg = intval(abs($dLon));
$dMin = intval(60.0*(abs($dLon)-$dDeg));
$dSec = 3600.0*(abs($dLon)-$dDeg-$dMin/60);
$dDeg = $dDeg * $dSign;
$arrReturn['DecimalDegrees'] .= ', '.number_format($dLon,4);
$arrReturn['DegMinSec'] .= ', '.number_format($dDeg,0).' '.number_format($dMin,0).' '.number_format(round($dSec,0,PHP_ROUND_HALF_UP),0);
if ($dSign > 0.0) {
$arrReturn['Garmin'] .= ', E';
} else {
$arrReturn['Garmin'] .= ', W';
}
$arrReturn['Garmin'] .= number_format(abs($dDeg),0).' '.number_format($dMin,0).' '.number_format($dSec,3);
$arrReturn['DegMinDecSec'] .= ', '.number_format($dDeg,0).' '.number_format($dMin,0).' '.number_format($dSec,3);
$arrReturn['DegDecMin'] .= ', '.number_format($dDeg,0).' '.number_format($dMin+$dSec/60.0,4);
$arrReturn['NMEA'] .= ', '.number_format($dDeg,0).number_format($dMin+$dSec/60.0,4);
$arrReturn['dDeg'] .= ', '.round($dDeg,0,PHP_ROUND_HALF_UP);
$arrReturn['dMin'] .= ', '.round($dMin,0,PHP_ROUND_HALF_UP);
$arrReturn['dSec'] .= ', '.round($dSec,0,PHP_ROUND_HALF_UP);
$arrReturn['dDecMin'] .= ', '.round($dMin+$dSec/60,4,PHP_ROUND_HALF_UP);
$arrReturn['dDecSec'] .= ', '.round($dSec,4,PHP_ROUND_HALF_UP);
return $arrReturn;
} // arrLatLonFmtsFromDecDeg()
/*
// Demonstration of function arrDecimalDegrees().
$arrStrLatLon = arrStrLatLonFmts();
foreach ($arrStrLatLon as $sLatLonFmt) {
$arrDecDeg = arrDecimalDegrees($sLatLonFmt,false);
if ($arrDecDeg == false) {
echo '"'.$sLatLonFmt.'" ERROR - arrDecimalDegrees() invalid format or characters
';
//if ($arrDecDeg == false) die('ERROR - arrDecimalDegrees() "'.$sLatLonFmt.'" invalid format or characters');
} else {
echo ''.$sLatLonFmt.' -> '.number_format($arrDecDeg['lat'],4).','.number_format($arrDecDeg['lon'],4).' '.$arrDecDeg['src'].'
';
}
}
*/
function arrDecimalDegrees($sLatLon, $bVerbose) {
// Convert $sLatLon consisting of any of the following
// latitude/longitude formats into Decimal Degrees and
// return them in an array:
// 37.5324,-80.7585 Decimal Degrees (google)
// N37 31 56.4,W80 45 30.6 Garmin
// 37 31 56.4,-80 45 30.6 Degrees Minutes Decimal Seconds
// 37 31.9404,-80 45.5100 Degrees Decimal Minutes
// 37° 31' 56",-80° 45' 31" Degrees Minutes Seconds
// 3731.9404,-8045.51 GPS NMEA sentence
//
// Strip any bad characters out of $sLatLon..
if (strlen($sLatLon) != strlen(filter_var($sLatLon, FILTER_SANITIZE_STRING))) return false;
$sLatLon = utf8_decode($sLatLon);
$sLatLon = preg_replace("/[^A-Za-z0-9\+\.\,\-[:space:]]/", " ", $sLatLon);
$sLatLon = strtoupper($sLatLon);
// Must have a comma to delimit lat/lon..
if (strpos($sLatLon,',') === false) return false;
// Divide string into lat and lon
$arrStrLatLon = Explode(',',$sLatLon);
if (count($arrStrLatLon) < 2) return false;
// Get lat degrees (only)..
$arrStrLat = Explode('.',$arrStrLatLon[0]);
$arrStrLat[0] = trim($arrStrLat[0]);
if ((strpos($sLatLon,'N') !== false) || (strpos($sLatLon,'S') !== false) || (strpos($sLatLon,'E') !== false) || (strpos($sLatLon,'W') !== false)) {
// Garmin N37 31 56.4, W80 45 30.6
// Latitude ..
$dLatSign = 1.0;
if (strpos($sLatLon,'S') !== false) $dLatSign = -1.0;
$arrStrLatLon[0] = str_replace('N','',$arrStrLatLon[0]);
$arrStrLatLon[0] = str_replace('S','',$arrStrLatLon[0]);
// Split lat string by space
$arrStr = Explode(' ',trim($arrStrLatLon[0]));
if (count($arrStrLatLon) < 2) return false;
$dDeg = floatval(trim($arrStr[0])) * $dLatSign;
$dMin = floatval(trim($arrStr[1]));
$dSec = floatval(trim($arrStr[2]));
$arrLatLon['lat'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
// Longitude ..
$dLonSign = 1.0;
if (strpos($sLatLon,'W') !== false) $dLonSign = -1.0;
$arrStrLatLon[1] = str_replace('E','',$arrStrLatLon[1]);
$arrStrLatLon[1] = str_replace('W','',$arrStrLatLon[1]);
// Split lat string by space
$arrStr = Explode(' ',trim($arrStrLatLon[1]));
if (count($arrStrLatLon) < 2) return false;
$dDeg = floatval(trim($arrStr[0])) * $dLonSign;
$dMin = floatval(trim($arrStr[1]));
$dSec = floatval(trim($arrStr[2]));
$arrLatLon['lon'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
$arrLatLon['src'] = 'Garmin';
} elseif ((stripos($sLatLon,'.') > 3) && (StrLen($arrStrLat[0])>3) && (substr_count($arrStrLat[0],' ') == 0)) {
// NMEA
// ddmm.mmmm format for latitude and in dddmm.mmmm for longitude
// Latitude
// Split lat string by decimal point
$arrStr = Explode('.',$arrStrLatLon[0]);
$arrStr[0] = trim($arrStr[0]);
// as amall as 0105.02 and as large as +8959.9834
if ((strlen($arrStr[0]) < 4) || (strlen($arrStr[1]) != 4)) return false;
$dDeg = floatval(substr($arrStr[0],0,2)); // dd
$dMin = floatval(substr($arrStr[0],2,2)); // mm
$sDecMin = substr($arrStr[0],2,2).'.'.$arrStr[1]; // mm.mmmm
$dDecMin = floatval($sDecMin);
$dSec = fmod($dDecMin,1.0) * 60.0;
$arrLatLon['lat'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
// longitude
// Split lat string by decimal point
$arrStr = Explode('.',$arrStrLatLon[1]);
$arrStr[0] = trim($arrStr[0]);
// as amall as 00105.02 and as large as +17959.9834
$dDeg = floatval(substr($arrStr[0],0,3)); // ddd
$dMin = floatval(substr($arrStr[0],3,2)); // mm
$sDecMin = substr($arrStr[0],3,2).'.'.$arrStr[1]; // mm.mmmm
$dDecMin = floatval($sDecMin);
$dSec = fmod($dDecMin,1.0) * 60.0;
$arrLatLon['lon'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
$arrLatLon['src'] = 'NMEA';
} elseif ((substr_count($arrStrLat[0],' ') == 1)) {
// DegDecMin 37 31.9404,-80 45.5100
// Split lat string by space
$arrStr = Explode(' ',trim($arrStrLatLon[0]));
if (count($arrStrLatLon) < 2) return false;
$dDeg = floatval(trim($arrStr[0]));
$sDecMin = $arrStr[1];
$dDecMin = floatval($sDecMin);
$dSec = fmod($dDecMin,1.0) * 60.0;
// Split lat string by decimal point
$arrStr = Explode('.',$arrStr[1]);
$arrStr[0] = trim($arrStr[0]);
$dMin = floatval($arrStr[0]);
$arrLatLon['lat'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
// Longitude ..
// Split lat string by space
$arrStr = Explode(' ',trim($arrStrLatLon[1]));
if (count($arrStrLatLon) < 2) return false;
$dDeg = floatval(trim($arrStr[0]));
$sDecMin = $arrStr[1];
$dDecMin = floatval($sDecMin);
$dSec = fmod($dDecMin,1.0) * 60.0;
// Split lat string by decimal point
$arrStr = Explode('.',$arrStr[1]);
$arrStr[0] = trim($arrStr[0]);
$dMin = floatval($arrStr[0]);
$arrLatLon['lon'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
$arrLatLon['src'] = 'DegDecMin';
} elseif (substr_count($arrStrLat[0],' ') == 2) {
// DegMinSec 37 31 56.4, -80 45 30.6
// Latitude ..
// Split lat string by space
$arrStr = Explode(' ',trim($arrStrLatLon[0]));
if (count($arrStrLatLon) < 2) return false;
$dDeg = floatval(trim($arrStr[0]));
$dMin = floatval(trim($arrStr[1]));
$dSec = floatval(trim($arrStr[2]));
$arrLatLon['lat'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
// Longitude ..
// Split lat string by space
$arrStr = Explode(' ',trim($arrStrLatLon[1]));
if (count($arrStrLatLon) < 2) return false;
$dDeg = floatval(trim($arrStr[0]));
$dMin = floatval(trim($arrStr[1]));
$dSec = floatval(trim($arrStr[2]));
$arrLatLon['lon'] = floatval(sign($dDeg)*(abs($dDeg)+$dMin/60.0+$dSec/3600.0));
$arrLatLon['src'] = 'DegMinSec';
} elseif ((substr_count($arrStrLat[0],' ') === 0) && (substr_count($arrStrLatLon[0],'.') === 1)) {
// DecimalDegrees
if ((floatval($arrStrLatLon[0]) === false) || (floatval($arrStrLatLon[1]) === false)) return false;
$arrLatLon['lat'] = floatval($arrStrLatLon[0]);
$arrLatLon['lon'] = floatval($arrStrLatLon[1]);
$arrLatLon['src'] = 'DecimalDegrees';
} else {
echo '"'.$sLatLon.'" "unrecognized lat/long format
';
return false;
}
unset($arrStrLatLon,$dSec,$dMin,$dDeg,$arrStr);
// validate lat and long values..
if (($arrLatLon['lat'] > 90.0) || ($arrLatLon['lat'] < -90.0) || ($arrLatLon['lon'] > 180.0) || ($arrLatLon['lat'] < -180.0)) {
if ($bVerbose == true) echo 'ERROR - lat &/or long out of range '.$sLatLon.' -> '.number_format($arrLatLon['lat'],1).','.number_format($arrLatLon['lon'],1).'
';
return false;
}
return $arrLatLon;
} // arrDecimalDegrees()
function arrStrLatLonFmts() {
// Returns an associative array of strings with all of the
// latitude/longitude formats.
//
// Latitude +/- 90 deg, Longitude +/- 180 deg
$arrStrLatLon['Garmin'] = 'N37 31 56.4, W80 45 30.6';
$arrStrLatLon['DegDecMin'] = '37 31.9404,-80 45.5100';
$arrStrLatLon['DegMinDecSec'] = '37 31 56.4, -80 45 30.6';
$arrStrLatLon['DecimalDegrees'] = '37.5324,-80.7585';
$arrStrLatLon['NMEA'] = '3731.9404,-8045.51';
// Greenland N76 58 10.6 W66 04 00.5 -> 76.969611, -66.066806
// New Zealand S43 03 53.6 E174 56 57.7 -> -43.064889, 174.949361
//$arrStrLatLon['validB'] = '37 31 56.4, W80 45 30.6';
//$arrStrLatLon['validC'] = '37 31 56.4, E80 45 30.6';
//$arrStrLatLon['validD'] = 'S37 31 56.4, -80 45 30.6';
//$arrStrLatLon['validE'] = '-3731.9404,-8045.51';
//$arrStrLatLon['validF'] = '37 31.9404,-80 45.5100'; // has unknown character in it for the space
//$arrStrLatLon['validG'] = '+38.1389, -76.632';
//$arrStrLatLon['validH'] = '76.969611, -66.066806';
//$arrStrLatLon['validI'] = '-43.064889, 174.949361';
//$arrStrLatLon['invalidA'] = '3731.9404 -8045.51';
//$arrStrLatLon['invalidB'] = '37° 31\' 56", -80° 45\' 31"';
//$arrStrLatLon['invalidF'] = '37° 31\' 56", -80° 45\' 31"';
//$arrStrLatLon['invalidG'] = '-91.064889, -181.949361';
//$arrStrLatLon['invalidH'] = '+91.064889, +181.949361';
return $arrStrLatLon;
} // arrStrLatLonFmts()
function sign($n){
return ($n > 0) - ($n < 0);
}
//
// ===========================================================================
//
// MIT License
//
// Copyright (c) 2018 Mechatronic Solutions LLC (www.http://mechatronicsolutionsllc.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// ===========================================================================
Sitemap | Copyright © 2017 - 2024 Mechatronic Solutions LLC
Web site by www.MechatronicSolutionsLLC.com | | 5.2390 ms