Link to home
Start Free TrialLog in
Avatar of Neil_Bradley
Neil_BradleyFlag for New Zealand

asked on

use php to convert lat and long coordinates

I have a data feed of lat and long coordinates coming into a website I need to convert into a string that Google Maps can read.
Essentially I need to convert this: Lat N48 42.29, Long W122.54.40 into this Lat 48.4229, Long -122.5440
Cheers,
N
Avatar of Anwar Saiah
Anwar Saiah

Do you mean:
Turn this    Lat N48.42.29, Long W122.54.40
into this     Lat -48.42.29, Long -122.54.40
Meaning, instead of N/W use -
?
if so, do this:
$ouput = str_replace("N", "-", $input);
$ouput = str_replace("W", "-", $output);

where $input=Lat N48.42.29, Long W122.54.40 ;
Avatar of Neil_Bradley

ASKER

Turn this N48 42.29 into 48.4229
and this W122.54.40 into  -122.5440

N
...Lat N48 42.29, Long W122.54.40 into this Lat 48.4229, Long -122.5440
I'm not sure that is a true conversion.  There are standards for the representation of these things.  Let me see if I can find an example, since I've done this before and researched it pretty thoroughly!
Check the EarthPoint reference - it shows the commonly understood formats for geolocation data.  The question about Lat N48 42.29 goes to the nature of the format / notation.  Does this mean 48 Degrees, 42.29 Minutes?  Or 48 Degrees, 42 Minutes, 29 Seconds?  That feels like ambiguity to me, and I wouldn't want to land an airplane unless I knew where the runway was located!

Please see: http://iconoun.com/demo/normalize_geocodes.php
<?php // demo/normalize_geocodes.php
/**
 * http://www.experts-exchange.com/questions/28931418/use-php-to-convert-lat-and-long-coordinates.html
 *
 * Lat N48 42.29, Long W122.54.40 into this Lat 48.4229, Long -122.5440
 *
 * http://en.wikipedia.org/wiki/Geographic_coordinate_conversion
 * http://www.earthpoint.us/Convert.aspx
 * https://en.wikipedia.org/wiki/IERS_Reference_Meridian
 *
 * Latitude Distance from the Equator
 *  90 N   =   90 North Pole
 *  90 S   =  -90 South Pole
 *
 * Longitude Distance from Prime Meridian (Greenwich)
 *  180 W   = -180
 *  180 E   =  180
 */
error_reporting(E_ALL);
echo '<pre>';


// A COLLECTION OF GATHERED TEST DATA
$testdata = array
( '40:26:46N,079:56:55W'
, '40:26:46.302N, 079:56:55.903W'
, '-40°26\'47"N, 079°58\'36"W'        // SOUTHERN HEMISPHERE
, '40d 26\' 47" N, 079d 58\' 36" W'
, '40.446195N, 79.948862W'
, '40.446195, -79.948862'
, '40.446195,-79.948862'
, '40° 26.7717, -79° 56.93172'
, '38.930434,-77.147772'              // MY HOUSE
, '45.55252525134013,-122.607421875'  // PORTLAND, OREGON

, 'Lat N48 42.29, Long W122.54.40'    // FROM THE QUESTION AT E-E
, '48° 42\'29"N, 122° 54\'40"W'
)
;


// PROCESS EACH OF THE TEST DATA STRINGS
foreach ($testdata as $ll)
{
    // SHOW WHAT WE'RE WORKING WITH
    echo PHP_EOL . "RAW DATA: $ll";
    echo PHP_EOL;

    $llp = explode(',', $ll);
    $lat = trim($llp[0]);
    $lon = trim($llp[1]);
    $llo = new Geocode($lat, $lon);
    print_r($llo);
    echo PHP_EOL;
}


Class Geocode
{
    public $lat, $lon, $geo;   // DECIMAL VALUES
    public $lat_dms, $lon_dms; // DEGREES, MINUTES, SECONDS

    public function __construct($lat, $lon)
    {
        // INITIALIZE THE RETURN OBJECT
        $this->lat
        = $this->lon
        = $this->geo
        = $this->lat_dms
        = $this->lon_dms
        = FALSE
        ;

        // DETERMINE IF THIS IS SOUTHERN LATITUDE
        $lat_sign = NULL;
        $lat_char = 'N';
        if ( (strpos($lat, 'S') !== FALSE) || (strpos($lat, '-') !== FALSE) )
        {
            $lat_sign = '-';
            $lat_char = 'S';
        }

        // DETERMINE IF THIS IS WESTERN LONGITUDE
        $lon_sign = NULL;
        $lon_char = 'E';
        if ( (strpos($lon, 'W') !== FALSE) || (strpos($lon, '-') !== FALSE) )
        {
            $lon_sign = '-';
            $lon_char = 'W';
        }

        // NORMALIZE TO DECIMAL
        $this->lat = $this->normalize_dec($lat);
        $this->lon = $this->normalize_dec($lon);

        // NORMALIZE TO D°M'S"
        $this->lat_dms = $this->normalize_dms($this->lat, $lat_char);
        $this->lon_dms = $this->normalize_dms($this->lon, $lon_char);

        // COMPLETE THE GEOCODE
        $this->geo
        = $lat_sign
        . $this->lat
        . ','
        . $lon_sign
        . $this->lon
        ;

        // COMPLETE THE LAT AND LON
        $arr = explode(',', $this->geo);
        $this->lat = $arr[0];
        $this->lon = $arr[1];

        return $this;
    }

    // COMPLETE THE DDD.ddddddd
    protected function normalize_dec($lxx)
    {
        $lxx = trim($lxx);
        $lxx = html_entity_decode($lxx, ENT_QUOTES);
        $lxx = strtoupper($lxx);

        // SPLIT INTO DEGREES, MINUTES, SECONDS
        $arr = preg_split('/[^0-9\.]/', $lxx, -1, PREG_SPLIT_NO_EMPTY);

        // COMPUTE THE DECIMAL VALUE
		$sec = isset($arr[2]) ? $arr[2] : 0;
		$min = isset($arr[1]) ? $arr[1] : 0;
		$sec = $sec + $min * 60.0;
		$sec = $sec / 3600.0;
		$dms = $arr[0] + $sec;

        $lxx = number_format($dms,7);
        $lxx = rtrim($lxx, '0');
        $lxx = rtrim($lxx, '.');

        return $lxx;
    }

    // COMPLETE THE D°M'S"
    protected function normalize_dms($lxx, $lxx_char)
    {
        $lat_d  = intval($lxx);
        $lat_ms = $lxx - $lat_d;
        $lat_m  = $lat_ms * 60.0;
        $lat_m  = intval($lat_m);
        $lat_s  = $lat_ms * 60.0 - $lat_m;
        $lat_s  = $lat_s * 60.0;
        $lat_s  = number_format($lat_s,3);
        $lat_s  = rtrim($lat_s, '0');
        $lat_s  = rtrim($lat_s, '.');
        $dms
        = $lat_d
        . '&deg;'
        . $lat_m
        . '&#039;'
        . $lat_s
        . '&quot;'
        . $lxx_char;
        ;

        return $dms;
    }
}

Open in new window

Turn this N48 42.29 into 48.4229

$input1="N48 42.29";
$ouput1= str_replace("N", "", $input1);
$ouput1= str_replace(".", "", $output1);
$ouput1 = str_replace(" ", ".", $output1);

and this W122.54.40 into  -122.5440
$input2="W122.54.40";
$ouput2= str_replace("W", "-", $input2);
$arr=explode(".",$output2);
$arr2=array($arr[0], ".", $arr[1],$arr[2]);
$output2=implode("",$arr2);
Thank you both for your input. Ray, as always extremely thorough and I will take time today to go through what you have both suggested.
The crux of my problem is that I have data that looks like this:
N47 37.42  W122 20.22 which needs to re formatted so that it will work in my Google Map development..
N
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for this Ray, accessing the FromLat and FromLon in the object made from the JSON string makes the most sense. The geocodes.php is gold thank you.
Neil
aboo_s thanks for your input on this one. There was value in your suggestion and I could have updated it to make it work however correcting the data in this was would have caused me some issues when it came to applying to the fix to southern hemisphere locations. Rays solution was extremely robust and gave me a long term fix.
Thanks again.
Neil
Thanks for the points and apologies for the awkward indenting in the sample script.  No matter how many times we beg Experts-Exchange to use 4-character tab indents, they just never listen!