{"id":885,"date":"2014-01-20T11:48:51","date_gmt":"2014-01-20T16:48:51","guid":{"rendered":"http:\/\/www.jsylvest.com\/blog\/?p=885"},"modified":"2019-05-03T12:47:20","modified_gmt":"2019-05-03T16:47:20","slug":"latitude-longitude-distance","status":"publish","type":"post","link":"https:\/\/www.jsylvest.com\/blog\/2014\/01\/latitude-longitude-distance\/","title":{"rendered":"Latitude-Longitude Distance"},"content":{"rendered":"\n<p><em>Updated<\/em>: I noticed a floating point error when using this that I discuss correcting at the end of this post.<\/p>\n\n\n\n<hr class=\"wp-block-separator is-style-dots\"\/>\n\n\n\n<p>I thought I would post some of the bite-sized coding pieces I've done recently. To lead off, here's&nbsp;Ruby function to find the distance between two points given their latitude and longitude.<\/p>\n\n\n\n<p>Latitude is given in degrees north of the equator (use negatives for the Southern Hemisphere) and longitude is given in degrees east of the Prime Meridian (optionally use negatives for the Western Hemisphere).<\/p>\n\n\n\n<pre class=\"wp-block-preformatted code\">include Math\nDEG2RAD = PI\/180.0\ndef lldist(lat1, lon1, lat2, lon2)\n  rho = 3960.0\n  theta1 = lon1*DEG2RAD\n  phi1 = (90.0-lat1)*DEG2RAD\n  theta2 = lon2*DEG2RAD\n  phi2 = (90.0-lat2)*DEG2RAD\n  val = sin(phi1)*sin(phi2)*cos(theta1-theta2)+cos(phi1)*cos(phi2)\n  val = [-1.0, val].max\n  val = [ val, 1.0].min\n  psi = acos(val)\n  return psi*rho\nend<\/pre>\n\n\n\n<p>A couple of notes:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Everything with <code>val<\/code> at the bottom is to deal with an edge case that can crop up when you try to get the distance between a point and itself. In that case <code>val<\/code> should be equal to 1.0, but on my systems some floating-point errors creep in and I get 1.0000000000000002, which is out of range for the <code>acos()<\/code> function.<\/li><li>This returns the distance in miles. If you want some other unit, redefine <code>rho<\/code> with the appropriate value for the radius of the earth in your desired unit (6371\u2009km, 1137&nbsp;leagues, 4304730\u2009passus, or what have you).<\/li><li>This assumes the Earth is spherical, which is a decent first approximation, but is still just that: a first approximation. ((As far as I'm concerned, this is my canonical example of the difference between a first and second approximation. The Earth isn't really a oblate spheroid either, but that makes a very good second approximation \u2014 about 100\u2009m. (See John Cook <a href=\"http:\/\/www.johndcook.com\/blog\/2009\/03\/02\/what-is-the-shape-of-the-earth\/\">here<\/a> and <a href=\"http:\/\/www.johndcook.com\/blog\/2012\/03\/04\/approximating-earth-as-a-sphere\/\">here<\/a>.) ))<\/li><\/ol>\n\n\n\n<p>I am currently writing a second version to account for the difference between geographic and geocentric latitude which should do a good job of accounting for the Earth's eccentricity. The math is not hard, but finding ground truth to validate my results against is, since the online calculators I've tried to check against do not make their assumptions clear. I did find a promising suite of tools for pilots, and I'd hope if you're doing something as fraught with consequences as flying that you've accounted for these sorts of things.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i1.wp.com\/imgs.xkcd.com\/comics\/actually.png\" alt=\"Protip: You can win every exchange just by being one level more precise than whoever talked last. Eventually, you'll defeat all conversational opponents and stand alone.\" width=\"500\" height=\"539\"\/><figcaption><a href=\"http:\/\/xkcd.com\/1318\/\">xkcd #1318<\/a> \u2014 \"Protip: You can win every exchange just by being one level more precise than whoever talked last. Eventually, you'll defeat all conversational opponents and stand alone.\"<\/figcaption><\/figure><\/div>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Update:<\/h3>\n\n\n\n<p> I've been putting this to use in a new project, and I've noticed an edge case that didn't crop up before. Due to some floating-point oddities, trying to get the distance between a point and itself will throw an error. In that case the value passed to <code>acos()<\/code> should be 1.0 but ends up being 1.0000000000000002 on my system. Since <a href=\"http:\/\/ruby-doc.org\/core-2.1.0\/Math.html#method-c-acos\">the domain of <code>acos()<\/code><\/a> is [-1,1] this is <em>no good<\/em>.<\/p>\n\n\n\n<p>If you want to be on the safe side you can replace this...<\/p>\n\n\n\n<pre class=\"wp-block-preformatted code\">psi = acos(sin(phi1)*sin(phi2)*cos(theta1-theta2)+cos(phi1)*cos(phi2))\n<\/pre>\n\n\n\n<p> ...with this...<\/p>\n\n\n\n<pre class=\"wp-block-preformatted code fullWidth noSpaceAfter\">val = sin(phi1)*sin(phi2)*cos(theta1-theta2)+cos(phi1)*cos(phi2)\nval = [-1.0, val].max\nval = [ val, 1.0].min\npsi = acos(val)\n<\/pre>\n\n\n\n<p>...and that will take care of things. (Yes, this is a verbose way of doing things, but I often prefer the verbose-and-overt to the laconic-and-recondite.)<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Updated: I noticed a floating point error when using this that I discuss correcting at the end of this post. I thought I would post some of the bite-sized coding pieces I've done recently. To lead off, here's&nbsp;Ruby function to &hellip; <a href=\"https:\/\/www.jsylvest.com\/blog\/2014\/01\/latitude-longitude-distance\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[10],"tags":[23,8,22],"class_list":["post-885","post","type-post","status-publish","format-standard","hentry","category-cs","tag-mapping","tag-programming","tag-visualization","wpautop"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p3sddF-eh","jetpack-related-posts":[{"id":62,"url":"https:\/\/www.jsylvest.com\/blog\/2013\/02\/computational-cartography-part-2\/","url_meta":{"origin":885,"position":0},"title":"Computational Cartography (Part 2)","author":"jsylvest","date":"20 February 2013","format":false,"excerpt":"In the previous post I talked a bit about how one might build a system which would algorithmically divide the US into 50 states of approximately equal populations. I've messed around with the problem a bit and developed a very rough approximation. Actually, I don't even feel comfortable calling this\u2026","rel":"","context":"In &quot;CS \/ Science \/ Tech \/ Coding&quot;","block_context":{"text":"CS \/ Science \/ Tech \/ Coding","link":"https:\/\/www.jsylvest.com\/blog\/category\/cs\/"},"img":{"alt_text":"auto sized states - after","src":"https:\/\/i0.wp.com\/www.jsylvest.com\/blog\/wp-content\/uploads\/2013\/02\/auto-sized-states-after-1024x768.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.jsylvest.com\/blog\/wp-content\/uploads\/2013\/02\/auto-sized-states-after-1024x768.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.jsylvest.com\/blog\/wp-content\/uploads\/2013\/02\/auto-sized-states-after-1024x768.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.jsylvest.com\/blog\/wp-content\/uploads\/2013\/02\/auto-sized-states-after-1024x768.png?resize=700%2C400 2x"},"classes":[]},{"id":762,"url":"https:\/\/www.jsylvest.com\/blog\/2014\/03\/ousterhout-on-performance-improvements\/","url_meta":{"origin":885,"position":1},"title":"Ousterhout on Performance Improvements","author":"jsylvest","date":"22 March 2014","format":"aside","excerpt":"The best performance improvement is the transition from the nonworking state to the working state. \u2014 John Ousterhout","rel":"","context":"In &quot;Art&quot;","block_context":{"text":"Art","link":"https:\/\/www.jsylvest.com\/blog\/category\/art\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":306,"url":"https:\/\/www.jsylvest.com\/blog\/2013\/04\/lahey-on-research\/","url_meta":{"origin":885,"position":2},"title":"Lahey on Research","author":"jsylvest","date":"16 April 2013","format":"aside","excerpt":"There is one thing worse than not doing research, and that is doing research and not changing anything in response to it. \u2014 Terry Lahey, Management in 10 Words, p. 252","rel":"","context":"In &quot;Business \/ Economics&quot;","block_context":{"text":"Business \/ Economics","link":"https:\/\/www.jsylvest.com\/blog\/category\/business-2\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":711,"url":"https:\/\/www.jsylvest.com\/blog\/2013\/10\/tufte-on-reasoning\/","url_meta":{"origin":885,"position":3},"title":"Tufte on Reasoning","author":"jsylvest","date":"2 October 2013","format":"aside","excerpt":"At the heart of quantitative reasoning is a single question:Compared to what?\" \u2014 Edward Tufte, Envisioning Information, p. 67 (cf. Bastiat's What Is Seen and What Is Not Seen)","rel":"","context":"In &quot;Business \/ Economics&quot;","block_context":{"text":"Business \/ Economics","link":"https:\/\/www.jsylvest.com\/blog\/category\/business-2\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":761,"url":"https:\/\/www.jsylvest.com\/blog\/2014\/01\/davy-on-scientific-progress\/","url_meta":{"origin":885,"position":4},"title":"Davy on Scientific Progress","author":"jsylvest","date":"17 January 2014","format":"aside","excerpt":"Nothing is more fatal to the progress of the human mind than to presume that our view of science is ultimate, that our triumphs are complete, that there are no mysteries in nature, and that there are no new worlds to conquer. \u2014 Humphry Davy","rel":"","context":"In &quot;CS \/ Science \/ Tech \/ Coding&quot;","block_context":{"text":"CS \/ Science \/ Tech \/ Coding","link":"https:\/\/www.jsylvest.com\/blog\/category\/cs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":686,"url":"https:\/\/www.jsylvest.com\/blog\/2013\/07\/knuth-on-tools\/","url_meta":{"origin":885,"position":5},"title":"Knuth on Tools","author":"jsylvest","date":"22 July 2013","format":"aside","excerpt":"The enjoyment of one's tools is an essential ingredient of successful work. \u2014 Donald Knuth, The Art of Computer Programming Vol. II, \u00a74.2.2A This is the dual of \"only a poor craftsmen blames his tools.\" See John D. Cook on this dichotomy here and here.","rel":"","context":"In &quot;CS \/ Science \/ Tech \/ Coding&quot;","block_context":{"text":"CS \/ Science \/ Tech \/ Coding","link":"https:\/\/www.jsylvest.com\/blog\/category\/cs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/posts\/885","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/comments?post=885"}],"version-history":[{"count":15,"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/posts\/885\/revisions"}],"predecessor-version":[{"id":1526,"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/posts\/885\/revisions\/1526"}],"wp:attachment":[{"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/media?parent=885"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/categories?post=885"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jsylvest.com\/blog\/wp-json\/wp\/v2\/tags?post=885"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}