I have a geolocation field setup on an object and want to be able to display the distance from another location in miles on a Visualforce page. I see with the new geolocation fields you can use DISTANCE in the WHERE clause combined with <, >, and other operators but I'd like to see the actual distance not just filter the results, is this possible without using an outside API?


You can use the DISTANCE and GEOLOCATION formula functions to create a custom field that will calculate the distance in miles to a fixed location. Then you can use this field in your Visualforce pages as required.

DISTANCE(acme_distribution__c, GEOLOCATION(37.775,-122.418), "mi")

Failing that, you can do the haversine formula calculation yourself in Apex:

public Decimal calculateHaversineDistance(Decimal lat1, Decimal lon1, Decimal lat2, Decimal lon2){
    // Earth's radius varies from 6356.752 km at the poles to 6378.137 km at the equator
    Double radius = 6371.00;
    Double dLat = toRadians(lat2-lat1);
    Double dLon = toRadians(lon2-lon1);
    Double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
    Double c = 2 * Math.asin(Math.sqrt(a));

    double kmToMiles = 0.621371;
    return radius * c * kmToMiles;

private Double toRadians(Decimal degree){
    return degree * 3.1415926 / 180;

Note that this includes the conversion from kilometres to miles in case you are in one of the three countries in the world that don't use the metric system :)

You may want to work to, say, 4 significant figures, as there are a number of simplifications in this approach.

  • Unfortunately the custom field option won't work since I need to display the distance between a selected event and other events so it needs to be more dynamic. I also learned I need the driving distance not 'as the crow flies' distance so I'll need to use an API anyway. It looks like the haversine formula would work for actual distance. It'd be nice if they'd expose the logic that DISTANCE uses in the MATH or perhaps a GEOLOCATION class. – Phil B May 28 '14 at 15:14

Yes, this is possible without an external API using the Location class, which can be instantiated with a latitude and longitude or queried from the database. Here's the example from the documentation.

// Select and access the Location field. MyLocation__c is the name of a geolocation field on Account.
Account[] records = [SELECT id, MyLocation__c FROM Account LIMIT 10];
for(Account acct : records) {
   Location loc = acct.MyLocation__c;
   Double lat = loc.latitude;
   Double lon = loc.longitude;

// Instantiate new Location objects and compute the distance between them in different ways.
Location loc1 = Location.newInstance(28.635308,77.22496);
Location loc2 = Location.newInstance(37.7749295,-122.4194155);
Double dist = Location.getDistance(loc1, loc2, 'mi');
Double dist2 = loc1.getDistance(loc2, 'mi');

As of Spring '16 release, you can now use the DISTANCE function in SOQL SELECT clause so you can easily display distance in your query results. Do note, this is the haversine distance that @Daniel Ballinger already mentioned in his answer instead of "driving distance".

From the release notes...

DISTANCE() Support with Location-based SOQL Queries

The DISTANCE function is now supported with location-based queries. DISTANCE() now works with location and address fields. You can retrieve a specific distance (say, of a store from a contact’s location) and display it to the user. For example:

SELECT Id, Name, Location, DISTANCE(Location, GEOLOCATION(latitude, longitude), 'mi') FROM CONTACT;

Sample Apex Code

// Assuming your accounts have their billing address geocoded
// such that BillingLatitude and BillingLongitude are not null
// then this query finds the nearest 3 accounts to a particular location
Decimal latitude = 10;
Decimal longitude = 10;

List<Account> accounts = new List<Account>([
        id, name, billingStreet, billingCity, billingState, billingPostalCode,
        // Using DISTANCE function in SELECT statement, aliasing field as 'dist'
        DISTANCE( BillingAddress, GEOLOCATION( :latitude, :longitude ), 'mi' ) dist
    LIMIT 3

// To display the distance value from SELECT statement
// use the 'get' function instead of dot notation.
// This is similar to retrieving field results from aggregate queries.
for ( Account acct : accounts ) {
    System.debug( acct.get('dist' ) );

Your Answer

