Distance calculation between 2 Geopoint by Haversine formula

Quickly share your Android Code Snippets here...

Distance calculation between 2 Geopoint by Haversine formula

Postby William Wen » Tue Oct 07, 2008 4:24 pm

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. import com.google.android.maps.GeoPoint;
  2.  
  3.  
  4.  
  5. public class DistanceCalculator {
  6.  
  7.  
  8.  
  9.    private double Radius;
  10.  
  11.  
  12.  
  13.    // R = earth’s radius (mean radius = 6,371km)
  14.  
  15.    // Constructor
  16.  
  17.    DistanceCalculator(double R) {
  18.  
  19.       Radius = R;
  20.  
  21.    }
  22.  
  23.  
  24.  
  25.    public double CalculationByDistance(GeoPoint StartP, GeoPoint EndP) {
  26.  
  27.       double lat1 = StartP.getLatitudeE6()/1E6;
  28.  
  29.       double lat2 = EndP.getLatitudeE6()/1E6;
  30.  
  31.       double lon1 = StartP.getLongitudeE6()/1E6;
  32.  
  33.       double lon2 = EndP.getLongitudeE6()/1E6;
  34.  
  35.       double dLat = Math.toRadians(lat2-lat1);
  36.  
  37.       double dLon = Math.toRadians(lon2-lon1);
  38.  
  39.       double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
  40.  
  41.       Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
  42.  
  43.       Math.sin(dLon/2) * Math.sin(dLon/2);
  44.  
  45.       double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  46.  
  47.       return Radius * c;
  48.  
  49.    }
  50.  
  51. }
Parsed in 0.033 seconds, using GeSHi 1.0.8.4
William Wen
William Wen
Junior Developer
Junior Developer
 
Posts: 11
Joined: Tue Sep 23, 2008 4:28 pm

Top

Postby plusminus » Tue Oct 07, 2008 5:53 pm

Hi William,

I'd suggest making the method static and setting the Radius as a final.
That would increase performance, decrease memory footprint but would work only for earth(or any other sphere the [font=Courier New]Radius[/font] is set to)

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby MrSnowflake » Tue Oct 07, 2008 8:43 pm

plusminus wrote:Hi William,

I'd suggest making the method static and setting the Radius as a static final.
User avatar
MrSnowflake
Moderator
Moderator
 
Posts: 1439
Joined: Sat Feb 16, 2008 3:11 pm
Location: Flanders, Belgium

Postby plusminus » Tue Oct 07, 2008 8:46 pm

MrSnowflake wrote:
plusminus wrote:Hi William,

I'd suggest making the method static and setting the Radius as a static final.


Oops yes, because otherwise it would not work :P
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby William Wen » Wed Oct 08, 2008 4:29 am

Got it. Thank you, MrSnowflake and +-

plusminus wrote:
MrSnowflake wrote:
plusminus wrote:Hi William,

I'd suggest making the method static and setting the Radius as a static final.


Oops yes, because otherwise it would not work :P
William Wen
William Wen
Junior Developer
Junior Developer
 
Posts: 11
Joined: Tue Sep 23, 2008 4:28 pm

Postby SchlaWiener » Sun Feb 22, 2009 7:42 pm

Just one silly question,
what is the result I get? meters? or something else?

And one thing to mention,
when I use the class I get a VerifyException:

LogCat prints:
Code: Select all
dalvikvm: VFY:  unable to find class referenced in signature (Lcom/google/android/maps/GeoPoint;)

I am fairly new to Java/Android development. Any suggestion how to fix it?

I rewrote the code to accept 2 location objects and it works for me, but I am intrested in fixing this error. Maybe I need to add another reference, or is this a bug in the 1.1 sdk?
SchlaWiener
Freshman
Freshman
 
Posts: 4
Joined: Sun Feb 15, 2009 6:28 pm

Top

Postby SchlaWiener » Mon Feb 23, 2009 12:33 am

btw:
The Location object offers the ability to calculate the distance between 2 locations, too.

Code: Select all
Location location1 = new Location(...
Location location2 = new Location(...

float dist = location1.distanceTo(location2);


the results differ a little (about 0.5 m / 100 m).

Don't know which of both methods is more accurate or uses less resources.
SchlaWiener
Freshman
Freshman
 
Posts: 4
Joined: Sun Feb 15, 2009 6:28 pm

Postby William Wen » Mon Feb 23, 2009 1:51 am

what is the result I get? meters? or something else?
-->It depends on which unit you apply to 'R', km or m.

dalvikvm: VFY: unable to find class referenced in signature (Lcom/google/android/maps/GeoPoint;)
-->You must sign up maps api. check http://code.google.com/intl/zh-CN/andro ... ignup.html

Don't know which of both methods is more accurate or uses less resources.[/quote]
-->I think location.distanceTo is better. You know when I wrote the class I didn't find such api :-)
William Wen
William Wen
Junior Developer
Junior Developer
 
Posts: 11
Joined: Tue Sep 23, 2008 4:28 pm

Postby SchlaWiener » Mon Feb 23, 2009 12:29 pm

William Wen wrote:-->You must sign up maps api. check http://code.google.com/intl/zh-CN/andro ... ignup.html


thx for the info,
I heard that there is need for an google api key, while using the mapview control.
But I didn't thought in that direction, beacuse I expected a error saying that I have no api key or something.

Thats a bit off-topic but I maybe you can help me with this, too:
This error (and others) are hard to track down, because when I debug my app with eclipse and an error in a superclass occures the debugger holds at a position outside of my code, requesting for the source of the class.
as a NET developer I am used to have the option "only debug my code" which would stop and show the error at the line I wrote.
Is there a similar option in Java/Android development with eclipse?
SchlaWiener
Freshman
Freshman
 
Posts: 4
Joined: Sun Feb 15, 2009 6:28 pm

Postby metachris » Sun Mar 29, 2009 10:15 am

Here is another function to get the distance between two gps points in meter:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. private double gps2m(float lat_a, float lng_a, float lat_b, float lng_b) {
  2.  
  3.     float pk = (float) (180/3.14169);
  4.  
  5.  
  6.  
  7.     float a1 = lat_a / pk;
  8.  
  9.     float a2 = lng_a / pk;
  10.  
  11.     float b1 = lat_b / pk;
  12.  
  13.     float b2 = lng_b / pk;
  14.  
  15.  
  16.  
  17.     float t1 = FloatMath.cos(a1)*FloatMath.cos(a2)*FloatMath.cos(b1)*FloatMath.cos(b2);
  18.  
  19.     float t2 = FloatMath.cos(a1)*FloatMath.sin(a2)*FloatMath.cos(b1)*FloatMath.sin(b2);
  20.  
  21.     float t3 = FloatMath.sin(a1)*FloatMath.sin(b1);
  22.  
  23.     double tt = Math.acos(t1 + t2 + t3);
  24.  
  25.    
  26.  
  27.     return 6366000*tt;
  28.  
  29. }
Parsed in 0.034 seconds, using GeSHi 1.0.8.4


- Chris
metachris
Junior Developer
Junior Developer
 
Posts: 24
Joined: Sat Feb 07, 2009 11:40 am

Postby keylimepai » Fri May 29, 2009 3:23 pm

I was working with pretty much this exact thing, so I created this class to do the work in arbitrary units.
I did a couple quick tests and it seemed to produce reasonable results, but let me know if I've completely screwed something up.

(And yes, I absolutely reused metachris's temp variable names ^^v )

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. import android.location.Address;
  2. import android.location.Location;;
  3.  
  4. /**
  5.  * Class to calculate the distance between two points
  6.  * in arbitrary units
  7.  *
  8.  */
  9. public class Distance
  10. {
  11.         /** Names for the units to use */
  12.         public final static int KILOMETERS = 0;
  13.         public final static int STATUTE_MILES = 1;
  14.         public final static int NAUTICAL_MILES = 2;
  15.        
  16.         /** Radius of the Earth in the units above */
  17.         private final static double EARTHS_RADIUS[] =
  18.                                                                 {
  19.                                                                         6378.1, // Kilometers
  20.                                                                         3963.1676, // Statue miles
  21.                                                                         3443.89849 // Nautical miles
  22.                                                                 };
  23.        
  24.         /** Conversion factor to convert from degrees to radians */
  25.     private static final double DEGREES_TO_RADIANS = (double)(180/Math.PI);
  26.        
  27.     /**
  28.      * Calculates the "length" of an arc between two points on a sphere
  29.      * given the latitude & longitude of those points.
  30.      * @param aLat Latitude of point A
  31.      * @param aLong Longitude of point A
  32.      * @param bLat Latitude of point B
  33.      * @param bLong Longitude of point B
  34.      * @return
  35.      */
  36.         private static double calclateArc(double aLat, double aLong, double bLat, double bLong)
  37.         {
  38.                 /*
  39.                  * Convert location a and b's lattitude and longitude
  40.                  * from degrees to radians
  41.                  */
  42.                 double aLatRad = aLat / DEGREES_TO_RADIANS;
  43.             double aLongRad = aLong / DEGREES_TO_RADIANS;
  44.             double bLatRad = bLat / DEGREES_TO_RADIANS;
  45.             double bLongRad = bLong / DEGREES_TO_RADIANS;
  46.  
  47.             // Calculate the length of the arc that subtends point a and b
  48.             double t1 = Math.cos(aLatRad)*Math.cos(aLongRad)*Math.cos(bLatRad)*Math.cos(bLongRad);
  49.             double t2 = Math.cos(aLatRad)*Math.sin(aLongRad)*Math.cos(bLatRad)*Math.sin(bLongRad);
  50.             double t3 = Math.sin(aLatRad)*Math.sin(bLatRad);
  51.             double tt = Math.acos(t1 + t2 + t3);
  52.            
  53.             // Return a "naked" length for the calculated arc
  54.             return tt;
  55.         }
  56.  
  57.         /**
  58.          * Calculates the distance between two addresses
  59.          * @param pointA Address of point A
  60.          * @param pointB Address of point B
  61.          * @param units Desired units
  62.          * @return Distance between the two points in the desired units
  63.          */
  64.         public static double calculateDistance(Address pointA, Address pointB, int units)
  65.         {
  66.                 return calclateArc(pointA.getLatitude(),
  67.                            pointA.getLongitude(),
  68.                            pointB.getLatitude(),
  69.                            pointB.getLongitude()) * EARTHS_RADIUS[units];
  70.         }
  71.        
  72.         /**
  73.          * Calculates the distance between two locations
  74.          * @param pointA Location of point A
  75.          * @param pointB Location of point B
  76.          * @param units Desired units
  77.          * @return Distance between the two points in the desired units
  78.          */
  79.         public static double calculateDistance(Location pointA, Location pointB, int units)
  80.         {
  81.                 return calclateArc(pointA.getLatitude(),
  82.                 pointA.getLongitude(),
  83.                 pointB.getLatitude(),
  84.                 pointB.getLongitude()) * EARTHS_RADIUS[units];
  85.         }
  86. }
Parsed in 0.043 seconds, using GeSHi 1.0.8.4
keylimepai
Junior Developer
Junior Developer
 
Posts: 14
Joined: Wed May 27, 2009 7:14 pm

Top

Return to Code Snippets for Android

Who is online

Users browsing this forum: No registered users and 8 guests