I recently had to calculate the distance between a large number of co-ordinates. I could have used one of the many Ruby Gems that are available but due to business limitations had to develop the code myself. After some research I came across the haversine formula.
The haversine formula is an equation important in navigation, giving great-circle distances between two points on a sphere from their longitudes and latitudes. It is a special case of a more general formula in spherical trigonometry, the law of haversines, relating the sides and angles of spherical triangles.
You can read the full details on the maths here. For those who just want the code here is the implemenation I came up with:
moduleGPSclassDistanceRAD_PER_DEG=Math::PI/180GREAT_CIRCLE_RADIUS_MILES=3956GREAT_CIRCLE_RADIUS_KILOMETERS=6371# some algorithms use 6367GREAT_CIRCLE_RADIUS_FEET=GREAT_CIRCLE_RADIUS_MILES*5280GREAT_CIRCLE_RADIUS_METERS=GREAT_CIRCLE_RADIUS_KILOMETERS*1000GREAT_CIRCLE_RADIUS_NAUTICAL_MILES=GREAT_CIRCLE_RADIUS_MILES/1.15078attr_accessor:great_circle_distanceattr_accessor:point1attr_accessor:point2definitialize(great_circle_distance=0)@great_circle_distance=great_circle_distance@point1=[0,0]@point2=[0,0]enddefto_milescalculate@great_circle_distance*GREAT_CIRCLE_RADIUS_MILESendalias_method:to_mi,:to_milesdefto_kilometerscalculate@great_circle_distance*GREAT_CIRCLE_RADIUS_KILOMETERSendalias_method:to_km,:to_kilometersdefto_meterscalculate@great_circle_distance*GREAT_CIRCLE_RADIUS_METERSendalias_method:to_m,:to_metersdefto_feetcalculate@great_circle_distance*GREAT_CIRCLE_RADIUS_FEETendalias_method:to_ft,:to_feetdefto_nautical_milescalculate@great_circle_distance*GREAT_CIRCLE_RADIUS_NAUTICAL_MILESendalias_method:to_nm,:to_nautical_milesprivate# Radians per degreedefrpd(num)num*RAD_PER_DEGenddefcalculate# Accept two arrays of points in addition to four coordinatesifpoint1.is_a?(Array)&&point2.is_a?(Array)lat2,lon2=point2lat1,lon1=point1elsifraiseArgumentErrorenddlon=lon2-lon1dlat=lat2-lat1a=(Math.sin(rpd(dlat)/2))**2+Math.cos(rpd(lat1))*Math.cos((rpd(lat2)))*(Math.sin(rpd(dlon)/2))**2@great_circle_distance=2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a))endendend