Calculating distance between addresses

The use of geolocation services in enterprise apps is common. One of the most common geolocation requirements is to calculate the distance between two points. This is helpful in planning routes, determining mileage, forecasting delivery schedules, and more.

The following recipe demonstrates how to calculate the distance between two addresses. This distance measurement is done using a direct distance, not a routing calculation such as those used for walking or driving. The following screenshots illustrate this recipe running on both an iPhone and an Android device.

Calculating distance between addresses

Getting ready

This recipe uses both CommonJS and native modules. These can be downloaded from the source code provided by the book, or individually through the links provided in the See also section at the end of this recipe. Simply copy the forwardGeo.js file into the Resources folder of your project and then copy the modules folder into your project as shown in the following screenshot:

Getting ready

After copying the file and folder mentioned here, you will need to click on your tiapp.xml file in Titanium Studio and add a reference to the bencoding.basicgeo module as shown in the following screenshot:

Getting ready

How to do it...

Once you have added native and CommonJS modules to your project, you next need to create your application namespaces in the app.js file and use require to import the module into your code as the following code snippet demonstrates:

//Create our application namespace
var my = {
  forward : require('forwardGeo')
};

Adding address information

The following startAddress and endAddress objects are added to the app namespace. These objects will be used to create the address information and coordinate state for this recipe.

my.startAddress  = {
  needRefresh:true,lat:40.748433, lng:-73.985656,
  address:'350 5th Ave  New York, NY 10118'
};

my.endAddress = {
  needRefresh:false, lat:40.75773, lng:-73.985708,
  address:'1560 Broadway, New York, NY 10036'
};

Building the recipe UI

The following code snippet describes how to create the UI shown in this recipe's earlier screenshots:

  1. The first step is to create the Ti.UI.Window to which all visual elements will be attached.
    var win = Ti.UI.createWindow({
      backgroundColor: '#fff', title: 'Geo Distance Recipe', 
      barColor:'#000',fullscreen:false
    });
  2. Next the txtStartAddress Ti.UI.TextField is created to allow the user to enter a starting address.
    var txtStartAddress = Ti.UI.createTextField({
      hintText:'enter starting address', 
      value: my.startAddress.address,
      height:40, left:5, right:5, top:55,
      borderStyle:Ti.UI.INPUT_BORDERSTYLE_ROUNDED
    });
    win.add(txtStartAddress);
  3. Next the txtEndAddress Ti.UI.TextField is created to allow the user to enter a destination address.
    var txtEndAddress = Ti.UI.createTextField({
      hintText:'enter destination address', 
      value: my.endAddress.address,
      height:40, left:5, right:5, top:125,
      borderStyle:Ti.UI.INPUT_BORDERSTYLE_ROUNDED
    });
    win.add(txtEndAddress);
  4. The findButton Ti.UI.Button is then added to the Ti.UI.Window later in this recipe. This button will be used to perform the distance calculation.
    var findButton = Ti.UI.createButton({
      title:'Calculate Distance between', height:40,
      left:5, right:5, top:180
    });
    win.add(findButton);

Distance and address methods

This recipe uses the geo object to perform distance and address lookup operations.

var geo ={
  1. The distanceInUnits uses the Haversine formula and computes the direct distance in kilometers or meters between two sets of coordinates.
    distanceInUnits: function(lat1, lng1, lat2, lng2){
      var rOfEarth = 6371; 
      var dLat = (lat2-lat1)*Math.PI/180;  
      var dLon = (lng2-lng1)*Math.PI/180;   
      var a = Math.sin(dLat/2) * Math.sin(dLat/2) +  
      Math.cos(lat1*Math.PI/180) *
      Math.cos(lat2*Math.PI/180) *   
      Math.sin(dLon/2) * Math.sin(dLon/2);   
      var c = 2 * Math.asin(Math.sqrt(a));   
      var distance = rOfEarth * c;
  2. If the distance is less than 1 kilometer, the unit returned is converted to meters.
      return {
        distance: ((distance < 1) ? 
        (distance * 1000) : distance),
        unit: ((distance < 1) ? 'm' : 'km')
      };
    },
  3. The findLocations method is used to obtain the coordinates for the addresses provided.
    findLocations : function(callback){
  4. The onFinish function is the callback method provided to the forwardGeo function. The e parameter provides the starting and ending address coordinates.
      function onFinish(e){
        if(!e.success){
          alert(e.message);
          return;
        }

    The forwardGeo e.start and e.end results are assigned to the my.startAddress and my.endAddress properties. The callback method is then executed, so the distance calculation can be performed.

        my.startAddress = e.start;
        my.endAddress = e.end;
        callback();
      };
  5. The forwardGeo method is called to obtain the coordinates for the my.startAddress and my.endAddress objects. As discussed earlier, the geolocation results are provided to the onFinish callback method as the following code snippet demonstrates:
        my.forward.forwardGeo(my.startAddress,
        my.endAddress,onFinish);
      }	
    };

Finding the distance between the two addresses

When the user presses the findButton and the click event is fired, the recipe will perform a distance calculation between the two addresses entered.

findButton.addEventListener('click',function(e){
  1. The first step in this process is to determine if forward geolocation is supported. The coordinates for each address is required for the distance calculation. A forward geolocation lookup is performed to obtain this information.
      if(!my.forward.isSupported()){
        alert('Forward Geocoding is not supported'),
        return;
      }	
  2. The findDistance method is used to make the distance calculation method call and format the provided results.
      function findDistance(){
  3. The first step in this section of the recipe is to call the distanceInUnits method using the latitude and longitude information for each address.
        var result = geo.distanceInUnits(
        my.startAddress.lat,my.startAddress.lng,
        my.endAddress.lat,my.endAddress.lng);
  4. Next the distance calculation results need to be formatted. If the results are in kilometres, the distance variable is rounded to the first three decimal places. If it is in meters, the full value will be displayed.
        if(result.unit=='km'){
          result.distance = 	
          result.distance.toFixed(3);
        }
        distanceLabel.text = result.distance + " " + 
        result.unit + " between addresses";
      };
  5. If either of the address information objects needs to be refreshed, the geo.findLocation method is called. The findDistance method is provided as the callback method to the findLocations function so that the distance calculation can be performed after the coordinates are obtained.
      if(my.startAddress.needRefresh || 
      my.endAddress.needRefresh){
        geo.findLocations(findDistance);
      }else{
  6. If the address information objects do not need to be refreshed, the findDistance method is called directly to perform the distance calculation.
        findDistance();
      }	
    });
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.20.224.107