The MapAPI 1.0 is deprecated. Please use the new MapAPI 1.1.





« Previous chapter 1: Mapping   Back to Index   Next chapter 3: Mapping and Geocoding »

Chapter 2: Geocoding and Reverse-Geocoding

This chapter gives you a short introduction in geocoding and reverse-geocoding. Geocoding is important, if you want to get the coordinate for a specified address. After the address is geocoded, the coordinate can be used for map positioning. The map requires meter coordinates for correct positioning. Further, the geocoder client supports reverse geocoding which can be used to find possible addresses for a specified coordinate.


Fig. 2.1: UML class diagram: Geocoder Client

Lets start with our first geocoding example. Fill out the input fields below and press the geocode button. After receiving the response from the geocoder server, the example displays a list of possible coordinates for the entered address.

 Geocoding example 2a (view example) or

 Source code example 2a:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
	<head>
		<title>Chapter 2: Geocoding example 2a</title>
		<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
		<link type="text/css" rel="stylesheet" href="http://iw.mapandroute.de/MapAPI-1.0/css/screen.css">
		<script type="text/javascript" src="http://iw.mapandroute.de/MapAPI-1.0/js/mapping.js"></script>		
	</head>

	<body class="tutorial" onload="initFields()">
			
		<script type="text/javascript">
				
			var geocoder = new IWGeocoderClient();
			IWEventManager.addListener(geocoder, 'ongeocode', function(event) { return showGeocodingResults(event); });
					
			/**
			 * Calls the geocode method.
			 * @private
			 * @param {String} inputAddress the address string
			 * @param {String} countryCode the country code
			 * @param {Number} maximumHits the maximum hits returned by the geocoder
			 * @return {void}
			 */							
			function doGeocoding(inputAddress, countryCode, maximumHits)
			{					
				geocoder.geocodeAddressString(inputAddress, countryCode, maximumHits);
			}	
			
			/**
			 * Callback method for geocode events.
			 * @private
			 * @param {IWGeocodingEvent} event the geocoding event
			 * @return {void}
			 */			
			function showGeocodingResults(event)
			{
				var results = event.results;
				var table = document.getElementById('resultTable');								

				for (var i = table.rows.length-1; i > 0; i--)
				{
					table.deleteRow(i);
				}

				if (results.length > 0)
				{	
					var rows = results.length;
					
					for(var i = 0; i < rows; i++) 
					{					
						var result = results[i];	
						var tr = table.insertRow(i+1);
						
						tr.className = (i % 2 ? 'even' : 'odd');
						
						tr.insertCell(0).innerHTML = i+1;

						var text = '';
						var address = result.getAddress();
						
						if (address.getStreet())
						{
							text = address.getStreet()
						}
						if (address.getHouseNumber()) 
						{
							text += ' ' + address.getHouseNumber();
						}
						if (address.getZipCode())
						{
							text += ' ' + address.getZipCode();
						}
						if (address.getCity())
						{
							text += ' ' + address.getCity();
						}
						if (address.getCountry())
						{
							text += ' ' + address.getCountry();
						}
						if (address.getCountryCode())
						{
							text += ' ' + address.getCountryCode();
					 	}
					 	
					 	var wgs84 = address.getCoordinate().toWGS84();
					 	
						tr.insertCell(1).innerHTML = text;
						tr.insertCell(2).innerHTML = address.getCoordinate().getX() + ', ' + address.getCoordinate().getY();
						tr.insertCell(3).innerHTML = wgs84.getX() + ', ' +	wgs84.getY();
						tr.insertCell(4).innerHTML = result.getHitProbability();
						tr.insertCell(5).innerHTML = (typeof result.getQuality() == 'undefined' ? '????' : result.getQuality());
					}						
				}		
			}
			
			/**
			 * Fills out the input fields with default values.
			 * @private
			 * @return {void}
			 */			
			function initFields()
			{
				var form = document.forms['geocodeForm'];
				form.inputAddress.value = 'Riemenschneiderstr. 11, 53175 Bonn';
			}			
		</script>
		
		<form id="geocodeForm" action="">
			<table>
				<tr>
					<td width="150">Address phrase</td>
					<td><input type="text" size="35" name="inputAddress"></td>
				</tr>
				<tr>
					<td width="150">Country code</td>
					<td><input type="text" size="35" name="countryCode" value="D"></td>
				</tr>				
				<tr>
					<td width="150">Maximum hits</td>
					<td><input type="text" size="35" name="maximumHits" value="30"></td>
				</tr>
			</table>			
			<input type="reset" value="reset form">
			<input type="button" value="geocode" onClick="doGeocoding(this.form.inputAddress.value, 
				this.form.countryCode.value, this.form.maximumHits.value)">
		</form>
		
		<br>

		<div style="position: relative; left: -1px; width: 100%; height: 145px; overflow: auto; padding: 1px;">
			<table id="resultTable">
				<tr>
					<th>No.</th>
					<th>Address</th>
					<th>meter coordinate</th>
					<th>degree coordinate</th>										
					<th>Hit probability</th>
					<th>Quality</th>
				</tr>					
			</table>
		</div>		
	</body>
</html>

The previous example looks a little bit more complex than our first mapping example. The reason is, that we have to handle the server response by ourselves. But a closer look at the code will show, that using the API for geocoding is also very easy. Let us take the code apart and have a look what it does.

2.1.1 Creating the geocoder client

At first we need a new geocoder client, so we instantiate the IWGeocoderClient class. Then we add a new listener to the IWEventManager object. With the IWEventManager we can add so called "event listeners". Listeners can be used to determine when a request comes in. In this case, we catch the geocoding event and call the showGeocodingResults() method to display the result after the geocoder server has sent an answer.

var geocoder = new IWGeocoderClient();
IWEventManager.addListener(geocoder, 'ongeocode', function(event) { return showGeocodingResults(event); });

2.1.2 Calling the geocodeAddressString method

We define two javascript methods, doGeocoding() and showGeocodingResults(). In doGeocoding() we just forward the values from the HTML form to the geocoder server by calling the geocodeAddressString method. The second parameter has to be a country code. This is necessary, because the address search would by to complex without localizing it to a country. In our example we want to search in Germany.

function doGeocoding(inputAddress, countryCode, maximumHits)
{					
	geocoder.geocodeAddressString(inputAddress, countryCode, maximumHits);
}

The complete list of supported country codes is specified in the configration file of your geocoder server. The following table shows only some example codes.

Code Country Code Country
D Deutschland A Österreich
CH Schweiz B Belgien
NL Niederlande F Frankreich
E Spanien L Luxemburg
I Italien GB Großbritannien
N Norwegen DK Dänemark
S Schweden P Portugal
AND Andorra RSM San Marino
FIN Finnland PL Polen
CZ Tschechien IRL Irland
GRC Griechenland HUN Ungarn
SVK Slowakei ALB Albanien
BIH Bosnien-Herzegowina HRV Kroatien
MDA Moldawien ROU Rumänien
SRB Serbien SVN Slowenien
MNE Montenegro BGR Bulgarien
BLR Weißrussland EST Estland
LTU Litauen LVA Lettland
MKD Makedonien MLT Malta
RUS Russland TUR Türkei
UKR Ukraine UAE Vereinigte Arabische Emirate

The server will now process our geocoding request and will send an answer back to the geocoder client. The answer will then be caught by our event listener and delegated to the showGeocodingResults() method. The method writes the result from the geocoder server into the resultTable that we defined at the bottom of our HTML code. For this, the method gets as parameter the event object from the geocoder client. We know that this event is an instance of IWGeocodingEvent, so we grab the geocoding results from the results attribute. The results attribute contains an array of IWGeocodingResult objects. We can now iterate over all results and print them in our table. The geocoded address can be access by calling the getAddress() method. We use the getter methods from the address object to create a formatted address string.

function showGeocodingResults(event)
{
	var results = event.results;
	
	for (var i = table.rows.length-1; i > 0; i--)
	{
  		table.deleteRow(i);
	}
		
	if (results.length > 0)
	{	
  		var rows = results.length;
		
  		for(var i = 0; i < rows; i++) 
  		{					
	  		var result = results[i];	
	  		tr = table.insertRow(i+1);
	  		tr.className = (i % 2 ? 'even' : 'odd');  
      		tr.insertCell(0).innerHTML = i+1;
      		  	
			var text = '';
			var address = result.getAddress();
						
			if (address.getStreet())
			{
				text = address.getStreet()
			}
			if (address.getHouseNumber()) 
			{
				text += ' ' + address.getHouseNumber();
			}
			if (address.getZipCode())
			{
				text += ' ' + address.getZipCode();
			}
			if (address.getCity())
			{
				text += ' ' + address.getCity();
			}
			if (address.getCountry())
			{
				text += ' ' + address.getCountry();
			}
			if (address.getCountryCode())
			{
				text += ' ' + address.getCountryCode();
			}
			
			var wgs84 = address.getCoordinate().toWGS84();
			
			tr.insertCell(1).innerHTML = text;
			tr.insertCell(2).innerHTML = address.getCoordinate().getX() + ', ' + address.getCoordinate.getY();
			tr.insertCell(3).innerHTML = wgs84.getX() + ', ' +	wgs84.getY();
			tr.insertCell(4).innerHTML = result.getHitProbability();
		}
	}
}

2.1.3 Sending our request

This is a simple HTML form, the only interesting line is the input tag at the bottom, where we send our form content to the doGeocoding() method.

<form id="geocodeForm" action="">
	<table>
		<tr>
			<td width="150">Address phrase</td>
			<td><input type="text" size="35" name="inputAddress"></td>
		</tr>
		<tr>
			<td width="150">Country code</td>
			<td><input type="text" size="35" name="countryCode" value="D"></td>
		</tr>				
		<tr>
			<td width="150">Maximum hits</td>
			<td><input type="text" size="35" name="maximumHits" value="30"></td>
		</tr>
	</table>			
	<input type="reset" value="reset form">
	<input type="button" value="geocode" onClick="doGeocoding(this.form.inputAddress.value, 
		this.form.countryCode.value, this.form.maximumHits.value)">
</form>

2.1.4 A place for the results

In this table we want to present the results. We just define the "hull" here, the main part is done by the showGeocodingResults() method. Therefore it is important that the table id here matches with the id we use in that method.

<div style="position: relative; left: -1px; width: 100%; height: 145px; overflow: auto; padding: 1px;">
	<table id="resultTable">
		<tr>
			<th>No.</th>
			<th>Address</th>
			<th>meter coordinate</th>
			<th>degree coordinate</th>										
			<th>Hit probability</th>
			<th>Quality</th>
		</tr>					
	</table>
<div>

The first example shows you a simple way to geocode a free address search. This is very powerful feature but in some cases it is necessary for you to set the address attributes explicit. The following example uses an IWAddress object for setting this attributes. You can set the street, house number, zipcode, city and countrycode attribute. The structure of the next example is very similar to our first, so we explain only the main different part.

 Geocoding example 2b (view example):

 Source code example 2b:

2.2.1 Calling the geocodeAddress method

The doGeocoding() method gets now all address attributes from the HTML form separately. The only thing that we must do is to create an IWAddress object and set its properties. After this, we can call the geocodeAddress() method which takes the address object as parameter. The geocoding event is also caught by the event listener and automatically forwarded to the showGeocodingResult() method which prints the geocoding result in the table.

function doGeocoding(street, houseNumber, zipCode, city, countryCode, maximumHits)
{					
	var address = new IWAddress();
			
	address.setStreet(street);
	address.setHouseNumber(houseNumber);
	address.setZipCode(zipCode);
	address.setCity(city);
	address.setCountryCode(countryCode);
				
	geocoder.geocodeAddress(address, maximumHits);
}

The following reverse geocoding examples demonstrates the use of the reverse geocoding methods. The examples are very similar to the previous examples at the top of the page.

 Reverse-Geocoding example 2c (view example):

 Source code example 2c:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
	<head>
		<title>Chapter 2: Reverse-Geocoding example 2c</title>
		<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
		<link type="text/css" rel="stylesheet" href="http://iw.mapandroute.de/MapAPI-1.0/css/screen.css">
		<script type="text/javascript" src="http://iw.mapandroute.de/MapAPI-1.0/js/mapping.js"></script>
	</head>

	<body class="tutorial">
			
		<script type="text/javascript">
				
			var geocoder = new IWGeocoderClient();
			IWEventManager.addListener(geocoder, 'onreversegeocode', function(event) { return showReverseGeocodingResults(event); });
							
			/**
			 * Calls the reverse geocode method.
			 * @private
			 * @param {String} projection the name of the projection: 'WGS84' or 'MERCATOR'
			 * @param {Number} x the x coordinate
			 * @param {Number} y the y coordinate
			 * @param {Number} radius
 			 * @return {void}
			 */									
			function doReverseGeocoding(projection, x, y, radius)
			{					
				geocoder.reverseGeocodeByRadius(new IWCoordinate(x, y, projection), radius);
			}	

			/**
			 * Callback method for reverse geocode events.
			 * @private
			 * @param {IWReverseGeocodingEvent} event the reverse geocoding event
			 * @return {void}
			 */			
			function showReverseGeocodingResults(event)
			{
				var results = event.results;
				var table = document.getElementById('resultTable');								

				for (var i = table.rows.length-1; i > 0; i--)
				{
					table.deleteRow(i);
				}

				if (results.length > 0)
				{	
					var rows = results.length;
					
					for(var i = 0; i < rows; i++) 
					{					
						var result = results[i];
						var address = result.getAddress();
						
						var tr = table.insertRow(i+1);
						
						tr.className = (i % 2 ? 'even' : 'odd');
						
						tr.insertCell(0).innerHTML = i+1;
						
						tr.insertCell(1).innerHTML = address.getCoordinate().getX() + ', ' + address.getCoordinate().getY();

						var wgs84 = address.getCoordinate().toWGS84();
						tr.insertCell(2).innerHTML = wgs84.getX() + ', ' + wgs84.getY();
						
						var text = '';
						var address = result.getAddress();
					
						if (address.getStreet())
						{
							text = address.getStreet()
						}
						if (address.getHouseNumber()) 
						{
							text += ' ' + address.getHouseNumber();
						}
						if (address.getZipCode())
						{
							text += ' ' + address.getZipCode();
						}
						if (address.getCity())
						{
							text += ' ' + address.getCity();
						}
						if (address.getCountry())
						{
							text += ' ' + address.getCountry();
						}						
						if (address.getCountryCode())
						{
							text += ' ' + address.getCountryCode();
					 	}

						tr.insertCell(3).innerHTML = text;													
						tr.insertCell(4).innerHTML = result.getDistance();
					}						
				}		
			}
		</script>

		<form action="">
			<table>
				<tr>
					<td width="150">Projection</td>
					<td>
						<select name="projection">
							<option value="meter" selected>meter</option>
							<option value="degree">degree</option>
						</select>			
					</td>
				</tr>
				<tr>
					<td width="150">X coordinate</td>
					<td><input type="text" size="35" name="x" value="786332"></td>
				</tr>
				<tr>
					<td width="150">Y coordinate</td>
					<td><input type="text" size="35" name="y" value="6572310"></td>
				</tr>
				<tr>
					<td width="150">Radius in meter</td>
					<td>
						<input type="text" size="35" name="radius" value="1000">
					</td>
				</tr>
			</table>
			<input type="button" value="reverse geocode" 
				onClick="doReverseGeocoding(this.form.projection.value, this.form.x.value, this.form.y.value, this.form.radius.value)">
		</form>

		<br>

		<div style="position: relative; left: -1px; width: 100%; height: 145px; overflow: auto; padding: 1px;">
			<table id="resultTable">
				<tr>
					<th>No.</th>
					<th>meter coordinate</th>
					<th>degree coordinate</th>				
					<th>Address</th>										
					<th>Distance in meters</th>				
				</tr>					
			</table>
		</div>
	</body>
</html>

 Reverse-Geocoding example 2d (view example) or

The difference between to the first and the second reverse geocoding example is, that we call in the first the reverseGeocodeByRadius method from the geocoder client and in the second the reverseGeocodeByHits method.

« Previous chapter 1: Mapping   Back to Index   Next chapter 3: Mapping and Geocoding »