All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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