Archive forMaps

Geocoder.us API

Another solution to get latitudes and longitudes for US addresses is geocoder.us. They also have some web APIs to call this service online. Full help files are available here.

You can choose from a few solutions: XML-RPC, SOAP, REST or even RDF or CSV. All of them are ok, as long as they works for you. I'll show you here two solutions: SOAP & CVS, one server side with PHP, the latter client side with XMLHTTPRequest and CVS.

Entry point pages are:

http://geocoder.us/service/xmlrpc
http://geocoder.us/service/soap
http://geocoder.us/service/rest/geocode
http://geocoder.us/service/csv/geocode

Here's PHP sample:

<?php
if($_POST['addr']!='') {
  include 'nusoap.php';
  $soapclient = new soapclient('http://geocoder.us/service/soap');
  $results = $soapclient->call('geocode',array($_POST['addr']));
  if(is_array($results))
    echo "Latitude: {$results[0]['lat']} -
 Longitude: {$results[0]['long']}";
}
?>
<form method=post name=frmgeous >
Address: <input name=addr>
<input type=submit value=Submit name=submit>
</form> 

This page is very basic: just display a form with a text-box for full address and a submit button. When clicked, values are passed to the server, interogating Geocoder.us and display results, if returned. This sample also uses Nusoap.php.

Client-side we can use only JavaScript to achieve the same results. Just add in the form above a simple button that call JavaScript function from a separate include file (uses the same text-box for address), before closing form tag:

<script language="JavaScript" src="/geocoder.us.js" mce_src="/geocoder.us.js" ></script>
<input type=button value=JavaScript onclick="javascript:geocode_us();"> 

Here's the JavaScript code, available for download:

 function geocode_us() {
var xmlhttp=null;
if(window.XMLHttpRequest) {
   xmlhttp = new XMLHttpRequest();
} else if(window.ActiveXObject) {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

if(xmlhttp) {
  xmlhttp.open("GET", "./load.php?url="+
    escape("geocoder.us/service/csv/geocode?address="+
    document.forms['frmgeous'].addr.value), false);
  xmlhttp.send("");
  arr=xmlhttp.responseText.split(',');
  alert('Latitude: '+arr[0]+'\nLongitude: '+arr[1]);
  }
}

This uses the same loader (load.php) to overcome security limits when accessing pages from another domain, client-side. It uses XMLHTTPRequest() on Firefox and ActiveX XML for IE when interrogating Geocoder.us server. See it at work:

Address:

For commercial requests see their website for prices and terms. This is also simple, isn't it?

Comments

Geocoder.ca API

When comes to Canadian geocoding first option you have is geocoder.ca. You can get longitude & latitude, as well as postal codes online from their website, but also, programmatically, using Geocoder.ca API.

You can request values both by HTTP GET or POST using a few combinations: address + city, or free text location or postal code. Result is returned as XML.

Try this:

http://geocoder.ca/?stno=&addresst=&city=&prov=&locate=1+Yonge+St.%2C+Toronto%2C+CA&postal=&geoit=GeoCode+it%21

As you can see, there are only a few parameters: stno, addressst, city & prov if you want to use full address, or locate for free text search, or postal for postal code. There are the same with POST.

To transform this in a web API you only have to include geoit=XML in your requests. The result is an XML file.

See this PHP sample:

 $location="1 Yonge St., Toronto, ON";
$req=implode('',file(
 'http://geocoder.ca/?geoit=XML&locate='.
 urlencode($location)));

$p = xml_parser_create();
xml_parse_into_struct($p, $req, $vals);
xml_parser_free($p);

if (count($vals)==19) // error occured
{
   $er = $vals[2]['value']." - ".
 $vals[5]['value'];
   $lat = 0;
   $long = 0;
} else { // get values
   $er = '';
   $lat = $vals[1]['value'];
   $long = $vals[4]['value'];
}

echo "Error:{$er}<br>
   Latitude: {$lat}<br>
   Longitude: {$long}";

We are getting the results from strict result format, returned as XML file:

<?xml version="1.0″ encoding="UTF-8″ ?>
<geodata>
        <latt>43.642321123</latt>
        <longt>-79.374806219</longt>
</geodata>

You even don't need to register. There is a limitation per IP address of about 1000 requests per day. For more requests they have commercial licenses.

Comments

Yahoo Geocoding API

There are some mapping APIs that accept only geocode coordinates (longitudes & latitudes). You need a solution to get them for all addresses you want. One of the best solution is to use Yahoo Geocoding API. You need to register first then you can request it with your custom parameters and get the results as XML, JSON or serialized PHP.

You can use the form below to get your values:

Street:
City:
State:
Zip:
or
Free Text:

- city, state
- city, state, zip
- zip
- street, city, state
- street, city, state, zip
- street, zip
Longitude:
Latitude:
 

This sample is using JSON and 2 extra files. One is a custom JSON library (json.js) for client side calls, plus a PHP file (load.php) which loads any URL on request based on fetchUrlWithoutHanging() from php.net/file (because XMLHTTP can't open pages from different server because of security restrictions).

The JavaScript function to interogate Yahoo service is here (Update: check new XML version below, JSON version is no more available from Yahoo):

function geocode() { 
var frm=document.forms['frm'];
if(frm.f.value!='')
  tmp="/load.php?url="+escape("api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street=&city=&state=&location="+frm.f.value+"&output=json");
else
  tmp="/load.php?url="+escape("api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street="+frm.s.value+"&city="+frm.c.value+"&state="+frm.p.value+"&output=json");
tmp2=json_load(tmp);
var obj=eval('('+tmp2+')');
if(obj) {
  frm.l1.value=obj.ResultSet.Result[0].Longitude;
  frm.l2.value=obj.ResultSet.Result[0].Latitude;
  }
else {
  frm.l1.value="";
  frm.l2.value="";
  }
obj=null;
}

Here's a simple request to Yahoo service: http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street=701+First+Street&city=Sunnyvale&state=CA
This call return JavaScript code to build an object with all requested values as properties.

There may be some problems with this scripts, but generally it should work.

The Yahoo Geocoding service is limited to 50,000 queries per IP address per day. Combined with Yahoo Maps or Google Maps could be a very powerful online tool.

Update (March 22nd): JSON results are no more available from Yahoo Geocoding API, so, we've changed the scripts to use XML files, directly from your browser (IE or FF):

function geocode() { 
var frm=document.forms['frm'];

if(frm.f.value!='')
   tmp="/load.php?format=xml&url="+
       escape("api.local.yahoo.com/MapsService/V1/geocode?appid=cod_xx2006&street=&city=&state=&location="+frm.f.value+"&output=xml");
else
   tmp="/load.php?format=xml&url="+
       escape("api.local.yahoo.com/MapsService/V1/geocode?appid=cod_xx2006&street="+frm.s.value+"&city="+frm.c.value+"&state="+
frm.p.value+"&output=xml");

var xmlDocument=null;

if(window.XMLHttpRequest) {
     // Firefox, Mozilla
     xmlDocument = document.implementation.createDocument("","",null);
     xmlDocument.async = false; 
     xmlDocument.load(tmp);
     lat=xmlDocument.getElementsByTagName("Latitude").item(0).firstChild.nodeValue;
     long=xmlDocument.getElementsByTagName("Longitude").item(0).firstChild.nodeValue;
     err=xmlDocument.getElementsByTagName("Result").item(0).attributes.getNamedItem("warning").firstChild.nodeValue;
} else if(window.ActiveXObject) {
     // IE/Windows ActiveX version
     xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
     xmlDocument.async = false;
     xmlDocument.load(tmp);
     xmlDocument.setProperty("SelectionLanguage", "XPath");
     xmlDocument.setProperty("SelectionNamespaces", "xmlns:my='urn:yahoo:maps'");
     var objNode=xmlDocument.selectSingleNode("//my:Result/@warning");
     err=objNode.text;
     var objNode=xmlDocument.selectSingleNode("//my:Result/my:Latitude");
     lat=objNode.text;
     var objNode=xmlDocument.selectSingleNode("//my:Result/my:Longitude");
     long=objNode.text;
}

if(xmlDocument) {
  frm.l1.value=lat;
  frm.l2.value=long;
  if(err!="") alert('Err: '+err);
  }

You can download YahooGeocode.js file with all client side process (the code above). It uses XML DOM to load Yahoo page using a local proxy (load.php) and then uses different methods to get data: getElementsByTagName() for Firefox & XPath for Internet Explorer.

Comments (1)

New MapQuest OpenAPI

MapQuest has just released their OpenAPI for mapping and routing (press release here). Registration and details are at http://www.mapquest.com/features/main.adp?page=developer_tools_oapi 

Of course, we registered and tried them. See their demos hosted here (popup window). To use them, you need an access key obtained after free registration (be careful to register exactly the domain name AND the folder where you want to use them, otherwise you'll get an invalid key error). You need to use this key in all requests from MapQuest.

Here's a simple demo (see it in popup window):

<html>
<head>
<script src="http://web.openapi.mapquest.com/oapi/transaction?request=script&key=mjtd%7Clu6z2l612h%2Cbx%3Do5-d6z2q" mce_src="http://web.openapi.mapquest.com/oapi/transaction?request=script&key=mjtd%7Clu6z2l612h%2Cbx%3Do5-d6z2q"   type="text/javascript"></script>
<title>OpenAPI Sample - Single Map</title>
</head>
<body style="background-color:rgb(244, 246, 229)" id='body' >
<div id='myMap' class='myMap' style="height:400;width:300″>
</div>

<script type="text/javascript">
 var mq = new MQMap("myMap");
 var loc1 = new MQLocation();
 loc1.setName("poi1″);
 loc1.setAddress("1 Yonge Street");
 loc1.setCity("Toronto");
 loc1.setStateProvince("ON");
 loc1.setPostalCode("M5E1W7″);
 loc1.setCountry("CA");
 loc1.setIconId(244);
 mq.locations.add(loc1);
 mq.setRolloverPopups(false);//To disable the popups
 mq.getMap();
</script>
</body>
</html>

Don't forget to change your access key.
Good news is that you can use full addresses, not only geocodes. 

Documentation and support forums are available after registration.

They are available for non-commercial use for 50,000 combined maps and geocodes and 5,000 routes per day. Business solutions are also available.

Comments

Google Maps API

A well-know service, used by many people is Google Maps API. See them at work at maps.google.com.

You can integrate all these maps directly in your websites or applications. Google Maps API is based on JavaScript. You also need to register your ID key used in all map web pages. First thing, is to include Google JavaScript page from http://maps.google.com/maps :

<script src="http://maps.google.com/maps?file=api&v=1&key= … key ID …" type="text/javascript">
 </script>

Then you can use all JavaScript objects and functions provided by this API, documented here. Here's a small example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8″/>

 <title>Google Maps JavaScript API Example: simple</title>
 <script src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAEfCuQGsNiSWxRgf_vfNWaRQjskl1-YgiA_BGX2yRrf7htVrbmBTEB0IH-F489GrwP8-dHLib7cKKIQ" mce_src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAEfCuQGsNiSWxRgf_vfNWaRQjskl1-YgiA_BGX2yRrf7htVrbmBTEB0IH-F489GrwP8-dHLib7cKKIQ"
   type="text/javascript">
 </script>

 <script type="text/javascript">
 function onLoad() {
   if (GBrowserIsCompatible()) {
   var map = new GMap(document.getElementById("map"));
   map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
   }
 }
</script>
</head>
<body onload="onLoad()">
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html> 

Idea is simple: create an GMap object based on a GPoint object created from longitude and latitude. Then you can add more objects as layers (GMarker) with their own events (GEvent).

Let's see a little bit more complicated demo with more functionality (popup window). This sample will work only from our website because of the ID key (unless you change it). As you can see, after loading, the maps are independent from your webpage, with their own navigation. All points must be specified by their longitude and latitude, you can't use full addresses. To get this geocodes you can use other websites like www.infosports.com/m/map.htm or www.geocoder.us.

Google API offers much more functionality. You can add markers to the map, with their own events and HTML content. Let's see such an example, with a marker and custom text displayed when click it.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAMWlN5S_pnUghkzaCL6OMMhRPit09n3FXh9HBeHPLQkDYD-WLrxTsecUOe9Urm4gtthzKpsI0hcmToA" mce_src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAAMWlN5S_pnUghkzaCL6OMMhRPit09n3FXh9HBeHPLQkDYD-WLrxTsecUOe9Urm4gtthzKpsI0hcmToA" type="text/javascript"></script>
  </head>
  <body>
    <div id="map" style="width: 400px; height: 300px"></div>
    <script type="text/javascript">
   
    var map = new GMap(document.getElementById("map"));
    map.addControl(new GSmallMapControl());
    var point = new GPoint(-79.3763, 43.6458);
    map.centerAndZoom(point, 8 );
    var marker = new GMarker(point);
    GEvent.addListener(marker, "click", function() {
      marker.openInfoWindowHtml("Hi there!");
    });
    map.addOverlay(marker);
    </script>
  </body>
</html> 

For a full description of the objects, their methods, events and properties see their documentation (including more complex samples).

Comments