Distance between two locations
To get the distance between two locations (in latitude and longitude) you can use the haversine formula. (31.10.2017)
Förderjahr 2016 / Projekt Call #11 / ProjektID: 1983 / Projekt: Prometheus

Distance between two locations

To get the distance between two locations (in latitude and longitude) you can use the haversine formula.

The haversine formula determines the great-circle distance between two points on a sphere given their longitudes and latitudes. Important in navigation, it is a special case of a more general formula in spherical trigonometry, the law of haversines, that relates the sides and angles of spherical triangles.

Fortunately there already exists a Clojure library that does this for us: haversine.

To use the library add [haversine "0.1.1"] to the :dependencies of your project.cljfile. Then you start your server or repl again to fetch the new dependency.

Now you can require the library in your code by adding it to your namespace macro at the top of your file or by executing this in your repl.

(ns facebook-example.core
  (:require [haversine.core :as haversine]))

Here is an example of calculating the distance from Museumsquartier to Burggarten:

(def mq {:latitude 48.2033369 :longitude 16.3564279})
(def bg {:latitude 48.2048528 :longitude 16.3650968})

(haversine/haversine mq bg); 0.6643769594161104 (kilometers)

Now let's say you are building a game with millions of treasure chests and your player owns a treasure chest detection device which reveals all treasure chests within 1km of the player's location.

One way to figure out which treasure chests the player can detect would be to compute all the distances between the player and the treasure chests.

; millions of treasure chests represented by lat/long 
(def treasure-chests [{:latitude 48.2033369 :longitude 16.3564279}, {:latitude 48.2048528 :longitude 16.3650968}, …])
; the current location of our player (Museumsquartier)
(def player-location {:latitude 48.2033369 :longitude 16.3564279})

; a helper function that tells us if a treasure chest is within 1km of our player
(defn detectable? [player-location treasure-chest]
  (<= (haversine/haversine player-location treasure-chest) 1.0))

; go through all treasure-chests and select all that are within 1km of the player (detectable)
; by calculating all the distances and comparing whether they are are <= 1km
(filter (partial detectable? player-location) treasure-chests)

Optimization for calculating a lot of distances

Depending on how your game is designed it might be quite common to check which of the treasure chests a player can detect in a given moment (or rather location).

You might want to compute this for all players over and over again as their locations change over time. Another way to think about this is to define a range (bounding box) of 1km around the player (detection-range) and to check which treasure chests are within that range.

This way you don't have to calculate all the distances between the player and all the treasure chests. Instead you can use simple comparisons to figure out if a given treasure chest is within the detection-range or not.

; calculating and defining the detection range (1km distance from our player)
(def detection-range
  (haversine/neighborhood
    (assoc player-location :distance-from 1)))

; a helper function that tells us if a treasure chest is within a given detection range
(defn in-range? [detection-range treasure-chest]
  (and
    (<= (:latitude  location) (:maxlatitude  detection-range))
    (<= (:longitude location) (:maxlongitude detection-range))
    (>= (:latitude  location) (:minlatitude  detection-range))
    (>= (:longitude location) (:minlongitude detection-range))))

; go through all treasure-chests and select all that are within 1km of the player (detectable)
; this time using the detection range instead of calculating the distances
(filter (partial in-range? detection-range) treasure-chests)

Further reading

https://en.wikipedia.org/wiki/Haversine_formula

http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates

https://en.wikipedia.org/wiki/Minimum_bounding_rectangle

Tags:

Clojure Geolocation

Thomas Schranz

Profile picture for user thomas.schranz
follow me on twitter: https://twitter.com/__tosh

Skills:

Clojure
CAPTCHA
Diese Frage dient der Überprüfung, ob Sie ein menschlicher Besucher sind und um automatisierten SPAM zu verhindern.
    Datenschutzinformation
    Der datenschutzrechtliche Verantwortliche (Internet Privatstiftung Austria - Internet Foundation Austria, Österreich) würde gerne mit folgenden Diensten Ihre personenbezogenen Daten verarbeiten. Zur Personalisierung können Technologien wie Cookies, LocalStorage usw. verwendet werden. Dies ist für die Nutzung der Website nicht notwendig, ermöglicht aber eine noch engere Interaktion mit Ihnen. Falls gewünscht, treffen Sie bitte eine Auswahl: