Avatar of Neil_Bradley
Neil_Bradley
Flag 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
PHPGIS/GPS ProgrammingWeb Development

Avatar of undefined
Last Comment
Ray Paseur

8/22/2022 - Mon
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 ;
Neil_Bradley

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

N
Ray Paseur

...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!
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Ray Paseur

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

Anwar Saiah

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);
Neil_Bradley

ASKER
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
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Ray Paseur

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Neil_Bradley

ASKER
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
Neil_Bradley

ASKER
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
Ray Paseur

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!
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes