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

com.graphhopper.util.AngleCalc Maven / Gradle / Ivy

Go to download

GraphHopper is a fast and memory efficient Java road routing engine working seamlessly with OpenStreetMap data.

The newest version!
/*
 *  Licensed to GraphHopper GmbH under one or more contributor
 *  license agreements. See the NOTICE file distributed with this work for 
 *  additional information regarding copyright ownership.
 * 
 *  GraphHopper GmbH licenses this file to you under the Apache License, 
 *  Version 2.0 (the "License"); you may not use this file except in 
 *  compliance with the License. You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.graphhopper.util;

import static java.lang.Math.cos;
import static java.lang.Math.toRadians;

/**
 * Calculates the angle of a turn, defined by three points. The fast atan2 method is from Jim Shima,
 * 1999, http://www.dspguru.com/dsp/tricks/fixed-point-atan2-with-self-normalization
 * 

* @author Johannes Pelzer * @author Peter Karich */ public class AngleCalc { private final static double PI_4 = Math.PI / 4.0; private final static double PI_2 = Math.PI / 2.0; private final static double PI3_4 = 3.0 * Math.PI / 4.0; static final double atan2( double y, double x ) { // kludge to prevent 0/0 condition double absY = Math.abs(y) + 1e-10; double r, angle; if (x < 0.0) { r = (x + absY) / (absY - x); angle = PI3_4; } else { r = (x - absY) / (x + absY); angle = PI_4; } angle += (0.1963 * r * r - 0.9817) * r; if (y < 0.0) // negate if in quad III or IV return -angle; return angle; } /** * Return orientation of line relative to east. *

* @return Orientation in interval -pi to +pi where 0 is east */ public double calcOrientation( double lat1, double lon1, double lat2, double lon2 ) { double shrinkFactor = cos(toRadians((lat1 + lat2) / 2)); return Math.atan2((lat2 - lat1), shrinkFactor * (lon2 - lon1)); } /** * convert north based clockwise azimuth (0, 360) into x-axis/east based angle (-Pi, Pi) */ public double convertAzimuth2xaxisAngle(double azimuth) { if (Double.compare(azimuth, 360)>0 || Double.compare(azimuth, 0)<0) { throw new IllegalArgumentException("Azimuth " + azimuth + " must be in (0, 360)"); } double angleXY = PI_2 - azimuth/180.*Math.PI; if (angleXY<-Math.PI) angleXY += 2*Math.PI; if (angleXY>Math.PI) angleXY -= 2*Math.PI; return angleXY; } /** * Change the representation of an orientation, so the difference to the given baseOrientation * will be smaller or equal to PI (180 degree). This is achieved by adding or substracting a * 2*PI, so the direction of the orientation will not be changed */ public double alignOrientation( double baseOrientation, double orientation ) { double resultOrientation; if (baseOrientation >= 0) { if (orientation < -Math.PI + baseOrientation) resultOrientation = orientation + 2 * Math.PI; else resultOrientation = orientation; } else { if (orientation > +Math.PI + baseOrientation) resultOrientation = orientation - 2 * Math.PI; else resultOrientation = orientation; } return resultOrientation; } /** * Calculate the azimuth in degree for a line given by two coordinates. Direction in 'degree' * where 0 is north, 90 is east, 180 is south and 270 is west. */ double calcAzimuth( double lat1, double lon1, double lat2, double lon2 ) { double orientation = -calcOrientation(lat1, lon1, lat2, lon2); orientation = Helper.round4(orientation + Math.PI / 2); if (orientation < 0) orientation += 2 * Math.PI; return Math.toDegrees(orientation); } String azimuth2compassPoint( double azimuth ) { String cp; double slice = 360.0 / 16; if (azimuth < slice) { cp = "N"; } else if (azimuth < slice * 3) { cp = "NE"; } else if (azimuth < slice * 5) { cp = "E"; } else if (azimuth < slice * 7) { cp = "SE"; } else if (azimuth < slice * 9) { cp = "S"; } else if (azimuth < slice * 11) { cp = "SW"; } else if (azimuth < slice * 13) { cp = "W"; } else if (azimuth < slice * 15) { cp = "NW"; } else { cp = "N"; } return cp; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy