Link to home
Start Free TrialLog in
Avatar of gplana
gplanaFlag 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.
Avatar of COBOLdinosaur
COBOLdinosaur
Flag of Canada image

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&
Avatar of 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?
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.
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

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
Avatar of 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?
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?
Avatar of 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
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
Avatar of gplana

ASKER

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

Many thanks.
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