Avatar of gplana
gplana
Flag for Spain asked on

Why Google API returns different results than Google Maps?

Hi.

I have this function in php which uses Google API to convert an address to its GPS coordinates:

   $googleKey = 'my google key here';
   function gps_coordinates($address) {
      global $googleKey;
      $url = 'http://maps.google.com/maps/geo?q='. urlencode($address) . '&output=json&oe=utf8&sensor=false&key='.$googleKey;
//echo "$url <br />\n";
      $content = file_get_contents($url);
//echo htmlentities($content)."<br />\n";
      $json = json_decode($content);
      return $json->Placemark[0]->Point->coordinates;
   }

Open in new window


It works ok, but for some addres I'm getting innacurate coordinates. For example, if I call this function with address "calle don jaime I, 26 50001 zaragoza  Spain" this function returns coordinates 41.6524051,-0.879501 instead of 41.692248,1.745868 which are the coordinates returned by google map: https://maps.google.es/maps?q=calle+don+jaime+I,+26+%0950001+%09zaragoza+%09Spain&hl=es&sll=41.692248,1.745868&sspn=3.359188,4.938354&hnear=Calle+Don+Jaime+I,+26,+50003+Zaragoza&t=m&z=17

Why?

Thanks.
PHPGIS/GPS Programming

Avatar of undefined
Last Comment
Ray Paseur

8/22/2022 - Mon
COBOLdinosaur

Don't you think it would be more productive to ask Google? They have support forums where Google employees post all the time, and expecting to Experts to know why 2 pieces of Google software do not produce the same result is probably unreasonable.

Cd&
gplana

ASKER
Thank you for your answer. I have searched for Google forums and found that I should put my question on stackoverflow.

Here is the link:

http://stackoverflow.com/questions/15706215/why-google-api-returns-different-results-than-google-maps

Or may I post on somewhere else?
Ray Paseur

Is the question, "Why?" or is the question, "Which is the canonical geocoding service?"  I don't think we can help with "Why" unless we can spot an error in the response strings.
Your help has saved me hundreds of hours of internet surfing.
fblack61
Ray Paseur

Here is how I would go about finding the geocode.  Interestingly, these responses are quite close together, yet they do not match either answer you got!  Note also that both of the Geocoders changed 50001 zaragoza to 50003 Zaragoza
http://www.laprbass.com/RAY_temp_gplana.php

Here is the response from the Geocoders:
YAHOO! DATA FOR calle don jaime I, 26 50001 zaragoza Spain
SimpleGeoCoder Object
(
    [location] => Calle Don Jaime I 26, 50003 Zaragoza 
    [address] => Calle Don Jaime I 26
    [city] => Zaragoza
    [state] => AR
    [zip] => 50003
    [latitude] => 41.65329
    [longitude] => -0.87836
    [precision] => 87
    [warning] => 
    [geocoder] => Yahoo!
)
GOOGLE DATA FOR calle don jaime I, 26 50001 zaragoza Spain
SimpleGeoCoder Object
(
    [location] => Calle Don Jaime I, 26, 50003 Zaragoza, Spain
    [address] => 
    [city] => 
    [state] => 
    [zip] => 
    [latitude] => 41.6534376
    [longitude] => -0.8781994
    [precision] => street_address
    [warning] => 
    [geocoder] => Google
)

Open in new window

And here is the code I used to get that response.
<?php // RAY_temp_gplana.php
error_reporting(E_ALL);

$location = 'calle don jaime I, 26 50001 zaragoza Spain';

// PREPARE THE GEOCODER
$y_demo           = new SimpleGeoCoder;
$y_demo->location = $location;

// TEST THE YAHOO! GEOCODER
$y_demo->geocodeYahoo();
echo "<pre>";
echo PHP_EOL;
echo "YAHOO! DATA FOR <strong>$location</strong>";
echo PHP_EOL;
print_r($y_demo);
echo "</pre>";



// PREPARE THE GEOCODER
$g_demo           = new SimpleGeoCoder;
$g_demo->location = $location;

// TEST THE GOOGLE GEOCODER
$g_demo->geocodeGoogle();
echo "<pre>";
echo PHP_EOL;
echo "GOOGLE DATA FOR <strong>$location</strong>";
echo PHP_EOL;
print_r($g_demo);
echo "</pre>";


// ALL DONE
die();



// SIMPLE GEOCODER CLASS
class SimpleGeoCoder
{

    // DECLARE THE INPUT DATA
    public $location; // USE THIS FOR A FREEFORM QUERY, OR USE THESE PARTS
    public $address;
    public $city;
    public $state;
    public $zip;

    // DECLARE THE OUTPUT DATA
    public $latitude;
    public $longitude;
    public $precision;
    public $warning;
    public $geocoder;

    // DECLARE THE CONSTRUCTOR
    public function __construct()
    {
        $this->latitude  = 0.0;
        $this->longitude = 0.0;
        $this->precision = 0;   // HIGHER IS BETTER, BUT Y AND G USE DIFFERENT SCALES
        $this->warning   = '';
        $this->geocoder  = '';
    }

    // DECLARE THE YAHOO! VERSION OF THE WORKHORSE
    public function geocodeYahoo()
    {
        $this->geocoder = 'Yahoo!';

        // SET THE URL AND OPTIONAL API KEY
        $yahooUrl       = "http://where.yahooapis.com/geocode?gflags=Q&appid=";
        if (defined("YAHOO_API"))
        {
            $yahooUrl .= YAHOO_API;
        }

        // YOU CAN ASK FOR A FREEFORM QUERY
        if ($this->location != '')
        {
            $yahooUrl .= "&location=" . urlencode($this->location);
        }

        // YOU CAN ASK FOR INDIVIDUAL PIECES OF AN ADDRESS
        else
        {
            $loc = urlencode
            ( trim($this->address)
            . ', '
            . trim($this->city)
            . ', '
            . trim($this->state)
            . ' '
            . trim($this->zip)
            )
            ;
            $yahooUrl .= "&location=" . $loc;
        }

        // EXECUTE YAHOO GEOCODER QUERY SEE http://developer.yahoo.com/geo/placefinder/guide/requests.html
        // NOTE - USE ERROR SUPPRESSION OR IT WILL BARK OUT THE YAHOO API KEY - ON FAILURE RETURNS HTTP 400 BAD REQUEST
        if ($yfp = @fopen($yahooUrl, 'r'))
        {
            $yahooResponse = '';
            while (!feof($yfp)) { $yahooResponse .= fgets($yfp); }
            fclose($yfp);
        }
        else
        {
            return FALSE;
        }

        // EXAMINE THE RESULT
        if ($yahooResponse != '') // NOT EMPTY, WE GOT DATA
        {
            $ydata    = new SimpleXMLElement($yahooResponse);
            // echo "<pre>";var_dump($ydata);

            // CHECK FOR ANY ERROR MESSAGE, IF NONE, EXTRACT THE DATA POINTS
            $y_err    = (string)$ydata->Error;
            if ($y_err)
            {
                $this->warning   = $ydata->ErrorMessage;
                return FALSE;
            }
            else
            {
                $this->precision = (string)$ydata->Result->quality;
                $this->latitude  = (string)$ydata->Result->latitude;
                $this->longitude = (string)$ydata->Result->longitude;
                $this->address   = (string)$ydata->Result->line1;
                $this->city      = (string)$ydata->Result->city;
                $this->state     = (string)$ydata->Result->statecode;
                $this->zip       = (string)$ydata->Result->postal;

                $this->location
                = (string)$ydata->Result->line1
                . ', '
                . (string)$ydata->Result->line2
                . ' '
                . (string)$ydata->Result->line3
                ;
            }
        }

        // NO RESULT - SOMETHING IS SICK AT YAHOO
        else
        {
            return FALSE;
        }
        return TRUE;
    } // END function geocodeYahoo



    // DECLARE THE GOOGLE VERSION OF THE WORKHORSE
    public function geocodeGoogle()
    {
        $this->geocoder = 'Google';

        // SET THE URL AND OPTIONAL API KEY
        $googleUrl      = "http://maps.googleapis.com/maps/api/geocode/xml?sensor=false";
        if (defined("GOOGLE_API"))
        {
            $googleUrl .= "&key=" . GOOGLE_API;
        }

        // YOU CAN ASK FOR A FREEFORM QUERY
        if ($this->location != '')
        {
            $googleUrl .= "&address=" . urlencode(trim($this->location));
        }

        // YOU CAN ASK FOR INDIVIDUAL PIECES OF AN ADDRESS
        else
        {
            $loc = urlencode
            ( trim($this->address)
            . ', '
            . trim($this->city)
            . ', '
            . trim($this->state)
            . ' '
            . trim($this->zip)
            )
            ;
            $googleUrl .= "&address=$loc";
        }

        // EXECUTE GOOGLE GEOCODER QUERY SEE http://code.google.com/apis/maps/documentation/geocoding/
        if ($gfp = @fopen($googleUrl, 'r'))
        {
            $googleResponse = '';
            while (!feof($gfp)) { $googleResponse .= fgets($gfp); }
            fclose($gfp);
        }
        else
        {
            return FALSE;
        }

        // EXTRACT THE DATA
        $gdata    = new SimpleXMLElement($googleResponse);

        // ON FAILURE
        if ($gdata->status != 'OK') return FALSE;

        // GEOCODE ACCURACY IS A TEXT STRING NOW
        $this->location  = (string)$gdata->result->formatted_address;
        $this->precision = (string)$gdata->result->type;
        $this->latitude  = (string)$gdata->result->geometry->location->lat;
        $this->longitude = (string)$gdata->result->geometry->location->lng;
        return TRUE;
    } // END function geocodeGoogle

} // END class SimpleGeocoder

Open in new window

Ray Paseur

Also, I found that I can zoom in closer to the destination address when I start from Google Search.  When I start from Google Maps, I could not zoom as far in.  Odd, but that's what you get from a free service!  If I went to Search first, then switched to Maps, I got this map.  I did not try to compute the center point
https://maps.google.com/maps?q=Calle%2BDon%2BJaime%2BI,%2B26,%2B50003%2BZaragoza,%2BSpain&hl=en&ll=41.653439,-0.878198&spn=0.001591,0.003484&sll=38.930454,-77.148131&sspn=0.001657,0.003484&hnear=Calle+Don+Jaime+I,+26,+50003+Zaragoza,+Spain&t=m&z=19
gplana

ASKER
Thank you for your answer. Isn't the center point the value marked by ll ? i.e. ll=41.653439,-0.878198 ?

Also I didn't understand 100% your answers. What I'm doing wrong on my code?
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ray Paseur

It looks like the center point is marked by the ll=

ll=41.653439,-0.878198 seems to be pretty close to the same location identified by the (corrected) address.  How many meters off are you finding the other geocodes?
gplana

ASKER
I think it's about 100 meters.

If you put "41.6524051,-0.879501" on the search bar of maps.google.es you will see the difference between this and putting the address "calle don jaime I, 26 50001 zaragoza  Spain"
ASKER CERTIFIED SOLUTION
Ray Paseur

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
gplana

ASKER
Thank you for your answer. I tryied to put 50003 instead of 50001 and the the result is exact.

Many thanks.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Ray Paseur

Thanks for the points.  I think when the Geocoders correct the address, it should be treated as a red flag, and at least checked, if not changed in your data model.  Best regards, ~Ray