Skip to content

Instantly share code, notes, and snippets.

@Phyks
Created November 20, 2018 18:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Phyks/2cc48655128f494e400e158ac73f214d to your computer and use it in GitHub Desktop.
Save Phyks/2cc48655128f494e400e158ac73f214d to your computer and use it in GitHub Desktop.
Fast distance computation for BRouter
class App {
public static void main(String [ ] args)
{
int N_TESTS = 10000000;
double R = 6371000.;
double rad = Math.PI / 180;
double[] latlng1 = {48.8124, 2.3158};
double[] latlng2 = {48.8204, 2.3210};
double lon1, lon2, lat1, lat2, l, l2, l4, coslat, coslat6, dlat, dlon, sinDLat, sinDLon, a, c;
double distance = 0.;
System.out.println("Leaflet implementation:");
long time = System.currentTimeMillis();
for (int i = 0; i < N_TESTS; i++) {
lat1 = latlng1[0] * rad;
lat2 = latlng2[0] * rad;
sinDLat = Math.sin((latlng2[0] - latlng1[0]) * rad / 2);
sinDLon = Math.sin((latlng2[1] - latlng1[1]) * rad / 2);
a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon;
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
distance = R * c;
}
System.out.println((System.currentTimeMillis() - time) / 1000.);
System.out.println(distance);
System.out.println("Current BRouter implementation:");
time = System.currentTimeMillis();
for (int i = 0; i < N_TESTS; i++) {
lon1 = latlng1[1] * 1e6;
lat1 = latlng1[0] * 1e6;
lon2 = latlng2[1] * 1e6;
lat2 = latlng2[0] * 1e6;
l = (lat2 - 90000000) * 0.00000001234134;
l2 = l * l;
l4 = l2 * l2;
coslat = 1. - l2 + l4 / 6.;
dlat = ( lat2 - lat1 );
dlon = ( lon2 - lon1 ) * coslat;
distance = Math.sqrt( dlat * dlat + dlon * dlon ) * 0.110984; // 6378000. / 57.3;
distance = (int) ( distance + 1.0 );
}
System.out.println((System.currentTimeMillis() - time) / 1000.);
System.out.println(distance);
System.out.println("Mapbox CheapRuler implementation:");
time = System.currentTimeMillis();
MathHelper mh = new MathHelper();
for (int i = 0; i < N_TESTS; i++) {
double cos = mh.cos(latlng1[0] * Math.PI / 180);
double cos2 = 2 * cos * cos - 1;
double cos3 = 2 * cos * cos2 - cos;
double cos4 = 2 * cos * cos3 - cos2;
double cos5 = 2 * cos * cos4 - cos3;
// multipliers for converting longitude and latitude degrees into distance (http://1.usa.gov/1Wb1bv7)
double kx = (111.41513 * cos - 0.09455 * cos3 + 0.00012 * cos5);
double ky = (111.13209 - 0.56605 * cos2 + 0.0012 * cos4);
dlat = (latlng1[0] - latlng2[0]) * ky;
dlon = (latlng1[1] - latlng2[1]) * kx;
distance = Math.sqrt(dlat * dlat + dlon * dlon); // in km
}
System.out.println((System.currentTimeMillis() - time) / 1000.);
System.out.println(distance * 1000);
}
}
// This code is coming from
// https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/MathHelper.java
// and is therefore under Mojang copyright.
public class MathHelper {
private static double[] a = new double[65536];
public static final double sin(double f) {
return a[(int) (f * 10430.378F) & '\uffff'];
}
public static final double cos(double f) {
return a[(int) (f * 10430.378F + 16384.0F) & '\uffff'];
}
static {
for (int i = 0; i < 65536; ++i) {
a[i] = Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment