org.osmtools.utils.LonLatMath Maven / Gradle / Ivy
/**
* This file is part of Relation Analyzer for OSM.
* Copyright (c) 2001 by Adrian Stabiszewski, [email protected]
*
* Relation Analyzer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Relation Analyzer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Relation Analyzer. If not, see .
*/
package org.osmtools.utils;
import org.osmtools.api.LonLat;
public class LonLatMath {
private static int[] sinTable = new int[201];
private static int[] cosTable = new int[201];
static {
for (int x = -157; x <= 157; x++) {
int pos = round(Math.sin((double)x / 100.0) * 100);
sinTable[pos + 100] = x;
pos = round(Math.cos((double)x / 100.0) * 100);
cosTable[pos + 100] = x;
}
}
private static final double LAT_DEGEE_DISTANCE = 40009.153 / 362; // Erdumfang ueber die Pole
private static final double LONG_DEGEE_DISTANCE = 40076.592 / 360; // Erdumfang am Aequator
public static int round(double d) {
return (int)new Double(Math.floor(d + 0.5d)).longValue();
}
public static double rotateX(double x, double y, double sin, double cos) {
return cos * x + sin * y;
}
public static double rotateY(double x, double y, double sin, double cos) {
return -sin * x + cos * y;
}
public static double distance(LonLat lonLat1, LonLat lonLat2) {
return distance(lonLat1.getLon(), lonLat1.getLat(), lonLat2.getLon(), lonLat2.getLat());
}
public static double distance(double long1, double lat1, double long2, double lat2) {
double latDistance = Math.abs(lat1 - lat2) * LAT_DEGEE_DISTANCE;
double longDistance = Math.abs(long1 - long2)
* Math.cos(Math.toRadians(Math.max(lat1, lat2) - Math.abs(lat1 - lat2))) * LONG_DEGEE_DISTANCE;
return Math.sqrt(latDistance * latDistance + longDistance * longDistance);
}
public static double asin(double d) {
return (double)sinTable[round(d * 100) + 100] / 100.0;
}
public static double acos(double d) {
return (double)cosTable[round(d * 100) + 100] / 100.0;
}
public static double checkpointDirection(double cpLong, double cpLat, double posLong, double posLat) {
double latDistance = Math.abs(cpLat - posLat) * LAT_DEGEE_DISTANCE;
double longDistance = Math.abs(cpLong - posLong)
* Math.cos(Math.toRadians(Math.max(cpLat, posLat) - Math.abs(cpLat - posLat))) * LONG_DEGEE_DISTANCE;
double hypo = Math.sqrt(latDistance * latDistance + longDistance * longDistance);
double sin = longDistance / hypo;
double raddeg = asin(sin);
if (cpLat < posLat) {
if (cpLong > posLong) {
return Math.PI - raddeg; // SUED OST
}
else {
return raddeg + Math.PI; // SUED WEST
}
}
else {
if (cpLong > posLong) {
return raddeg; // NORD OST
}
else {
return 2 * Math.PI - raddeg; // NORD WEST
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy