Calculating Geodistance – my move from #Java to #Clojure

Sometimes it’s too easy to rest on what you know well, anything for an easier life. Less challenges more ease. Grab a cup of tea and carry on. Sometimes shock to the system will wake you up and make you think a little harder.

Cue The Crippling XFactor Back Story

That’s been me with Java, for a long long time. Considering I’ve been working with it from the start in 1995. While I know other languages like PHP, Ruby and Python I’ve always gone back to Java to get things done for the simple reason is, I get things done.

Clojure and Scala came along, I dabbled with both and Scala was easier from a Java perspective and I took the easy way out. When you’re not exposed to something though it’s easy to go back to first principles of do what you know best. Clojure I couldn’t wrap my head around. I usually ended up with this sort of expression….

scared-lady

The Time Will Come….

There will be a day when you can’t avoid it. And over the last few months I’ve not been able to avoid Clojure. It’s staring me in the face and it’s what my client uses. The best way for me to learn is to have a goal in mind and code my way to a conclusion. Now fortunately for me I’m with some of the best Clojure programmers going, highly involved in the community, a lovely team to boot.

With some pair programming things are taking shape and that’s great. So my current face now seeing the power of Clojure is….

m2

There are times when you need to do you first solo flight and see what happens. So I did my first solo flight.

Calculating GeoDistance

i want to take two latitude and longitude points and calculate the number of miles between them. In Java it’s going to look something like this:

private double distance(double lat1, double lon1, double lat2, double lon2) {
        double theta = lon1 - lon2;
        double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))
                + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
                * Math.cos(deg2rad(theta));
        dist = Math.acos(dist);
        dist = rad2deg(dist);
        dist = dist * 60 * 1.1515;
        return dist;
    }
    private double deg2rad(double deg) {
        return (deg * Math.PI / 180.0);
    }
    private double rad2deg(double rad) {
        return (rad * 180 / Math.PI);
    }

If I run that and give it some co-ordinates it will push out the distance in miles.

System.out.println(gd.distance(55.0000 , 4.0000, 51.00000, 3.0000));

>> 279.4624387415594

So what’s I’m trying to do is write this program in Clojure and come up with the same output for the same test.

In the Java there are two private functions one to convert from degrees to radians and vice versa (deg2rad and rad2deg). So I’m going to write these first. They’re basic functions taking in the degrees and, for degrees to radians, multiplying by the value of PI and then dividing by 180.

Here’s my Clojure functions:

(defn- deg2rad [deg]
  (/ (* deg (. Math PI)) 180))

(defn- rad2deg [rad]
  (/ (* rad 180) (. Math PI)))

The things with Clojure functions is they’ll always return something. So once the calculation has been done whatever the value is will be returned. Looking good already.

Now to calculate the distance, well part of it anyway. There’s a lot of sine and cosine calculations to do so I’m going to create another method to do this.

(defn get-distance [lat1 lon1 lat2 lon2]
  (+ (* (Math/sin (deg2rad lat1)) (Math/sin (deg2rad lat2)))
     (* (Math/cos (deg2rad lat1))
        (Math/cos (deg2rad lat2))
        (Math/cos (deg2rad (- lon1 lon2))))
     ))

Within the square brackets [] are the values being entered into the function. You can now see where there deg2rad function is now being used.

Nearly there. All I need to do the arc cosine of the value of the get-distance function, convert from radians to degrees and the multiply by 60 * 1.1515 to get the number of miles.

(defn calc-distance [lat1 lon1 lat2 lon2]
  (* 60 1.1515 (rad2deg (Math/acos (get-distance lat1 lon1 lat2 lon2)))))

I’ve copy and pasted these functions into my Clojure REPL. And then I can test. You can see my test of the calc-distance function below.

#'user/deg2rad
#'user/rad2deg
#'user/get-distance
#'user/calc-distance
user> (calc-distance 55.0000 4.0000 51.00000 3.0000)
279.4624387415595
user> 

Now the output is the same as the original Java function. This makes me rather happy a bit like this but without the healthy food perhaps…..

1950s-woman-smiling-holding-platter-of-hors-d-oeuvres-snacks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: