woensdag 18 juni 2008

Het is me in de (aard)bol geslagen


“In mathematics, you don't understand things, you get used to them.” von Neumann

En met dat in gedachte zal ik toch proberen om een verhelderend stuk te schrijven over dit favoriete vak van menig programmeur. Waar heb ik dat aan te danken, hoor ik je denken en ergens heb je gelijk. Waarom zou ik je lastig vallen met een onderwerp waar je vroeger al slecht in was en wat je sinds het behalen van je diploma waarschijnlijk achteraan in je hersenen hebt geduwd (nog achter die genante herinneringen van toen je veertien was en je je geluk waagde bij het mooiste meisje van de klas). Hiervoor verwijs ik je naar Google in Mountain View, Californië. Die bedachten enkele jaren geleden dat het grappig zou zijn om een virtuele aarde te maken met aaneengeregen foto’s. Google Earth is in een korte tijd uitgegroeid tot een begrip en steeds vaker word je geconfronteerd met opdrachten waarbij locatiegegevens en kaarten een rol spelen. Het is een kwestie van tijd voordat je oog in oog komt te staan met de opgave om de afstand tussen twee coördinaten te berekenen en erachter komt dat deze coördinaten (uitgedrukt in lengtegraden en breedtegraden) niet altijd even ver van elkaar af staan. Met alleen de stelling van Pythagoras, die je ooit uit je hoofd hebt geknald omdat je wiskunde docent je wist te vertellen dat je hiermee alles kon uitrekenen, kom je letterlijk en figuurlijk nergens. Wat jij nodig hebt is een stevige dosis haversinus.

De haversinus formule kun je gebruiken om de afstand tussen twee coördinaten te berekenen en wel op de volgende manier:


  • Je neemt de radius van de aarde (R), 6371 km

  • Je neemt het verschil tussen de twee breedtegraden (∆b = b1 – b2)

  • Je neemt het verschil tussen de twee lengtegraden (∆l = l1 – l2)

  • En dan gooi je die in de onderstaande formule:

    afstand = R * (2 * atan2(√(sin2(∆b/2) + cos (b1) * cos(b2) * sin2(∆l/2) ), √(1-a)))


Ho ho ho, even een stapje terug, wat was die laatste? Laat me het uitdrukken in Java code, dat begrijp je vast beter.


public double calculateDistance(double long1, double long2, double lat1, double lat2) {
Integer r = new Integer(6371);
Double deltaLong = Math.toRadians(long1 - long2);
Double deltaLat = Math.toRadians(lat1 - lat2);
Double x = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(deltaLong/2) * Math.sin(deltaLong/2);
Double y = 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1-x));
Double z = r * y;
return z;
}

Ok, laten we het er maar op houden dat je in wiskunde niks begrijpt, maar er aan went.