1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package org.onap.aaf.cadi.routing;
\r
25 import org.onap.aaf.inno.env.util.Split;
\r
27 public class GreatCircle {
\r
28 // Note: multiplying by this constant is faster than calling Math equivalent function
\r
29 private static final double DEGREES_2_RADIANS = Math.PI/180.0;
\r
31 public static final double DEGREES_2_NM = 60;
\r
32 public static final double DEGREES_2_KM = DEGREES_2_NM * 1.852; // 1.852 is exact ratio per 1929 Standard Treaty, adopted US 1954
\r
33 public static final double DEGREES_2_MI = DEGREES_2_NM * 1.1507795;
\r
37 * Calculate the length of an arc on a perfect sphere based on Latitude and Longitudes of two points
\r
38 * Parameters are in Degrees (i.e. the coordinate system you get from GPS, Mapping WebSites, Phones, etc)
\r
40 * L1 = Latitude of point A
\r
41 * G1 = Longitude of point A
\r
42 * L2 = Latitude of point B
\r
43 * G2 = Longitude of point B
\r
45 * d = acos (sin(L1)*sin(L2) + cos(L1)*cos(L2)*cos(G1 - G2))
\r
47 * Returns answer in Degrees
\r
49 * Since there are 60 degrees per nautical miles, you can convert to NM by multiplying by 60
\r
51 * Essential formula from a Princeton website, the "Law of Cosines" method.
\r
53 * Refactored cleaned up for speed 3/8/2013
\r
61 public static double calc(double latA, double lonA, double latB, double lonB) {
\r
62 // Formula requires Radians. Expect Params to be Coordinates (Degrees)
\r
63 // Simple ratio, quicker than calling Math.toRadians()
\r
64 latA *= DEGREES_2_RADIANS;
\r
65 lonA *= DEGREES_2_RADIANS;
\r
66 latB *= DEGREES_2_RADIANS;
\r
67 lonB *= DEGREES_2_RADIANS;
\r
70 Math.sin(latA) * Math.sin(latB) +
\r
71 Math.cos(latA) * Math.cos(latB) * Math.cos(lonA-lonB)
\r
73 / DEGREES_2_RADIANS;
\r
77 * Convert from "Lat,Long Lat,Long" String format
\r
78 * "Lat,Long,Lat,Long" Format
\r
79 * or all four entries "Lat Long Lat Long"
\r
81 * (Convenience function)
\r
83 * Since Distance is positive, a "-1" indicates an error in String formatting
\r
85 public static double calc(String ... coords) {
\r
88 switch(coords.length) {
\r
90 array = Split.split(',',coords[0]);
\r
91 if(array.length!=4)return -1;
\r
93 Double.parseDouble(array[0]),
\r
94 Double.parseDouble(array[1]),
\r
95 Double.parseDouble(array[2]),
\r
96 Double.parseDouble(array[3])
\r
99 array = Split.split(',',coords[0]);
\r
100 String [] array2 = Split.split(',',coords[1]);
\r
101 if(array.length!=2 || array2.length!=2)return -1;
\r
103 Double.parseDouble(array[0]),
\r
104 Double.parseDouble(array[1]),
\r
105 Double.parseDouble(array2[0]),
\r
106 Double.parseDouble(array2[1])
\r
110 Double.parseDouble(coords[0]),
\r
111 Double.parseDouble(coords[1]),
\r
112 Double.parseDouble(coords[2]),
\r
113 Double.parseDouble(coords[3])
\r
119 } catch (NumberFormatException e) {
\r
127 //* Haverside method, from Princeton
\r
135 //public static double calc3(double alat, double alon, double blat, double blon) {
\r
136 // alat *= DEGREES_2_RADIANS;
\r
137 // alon *= DEGREES_2_RADIANS;
\r
138 // blat *= DEGREES_2_RADIANS;
\r
139 // blon *= DEGREES_2_RADIANS;
\r
140 // return 2 * Math.asin(
\r
141 // Math.min(1, Math.sqrt(
\r
142 // Math.pow(Math.sin((blat-alat)/2), 2) +
\r
143 // (Math.cos(alat)*Math.cos(blat)*
\r
145 // Math.sin((blon-alon)/2),2)
\r
150 // / DEGREES_2_RADIANS;
\r
156 //This is a MEAN radius. The Earth is not perfectly spherical
\r
157 // public static final double EARTH_RADIUS_KM = 6371.0;
\r
158 // public static final double EARTH_RADIUS_NM = 3440.07;
\r
159 // public static final double KM_2_MILES_RATIO = 0.621371192;
\r
161 //* Code on Internet based on Unknown book. Lat/Long is in Degrees
\r
168 //public static double calc1(double alat, double alon, double blat, double blon) {
\r
169 // alat *= DEGREES_2_RADIANS;
\r
170 // alon *= DEGREES_2_RADIANS;
\r
171 // blat *= DEGREES_2_RADIANS;
\r
172 // blon *= DEGREES_2_RADIANS;
\r
174 // // Reused values
\r
175 // double cosAlat,cosBlat;
\r
177 // return Math.acos(
\r
178 // ((cosAlat=Math.cos(alat))*Math.cos(alon)*(cosBlat=Math.cos(blat))*Math.cos(blon)) +
\r
179 // (cosAlat*Math.sin(alon)*cosBlat*Math.sin(blon)) +
\r
180 // (Math.sin(alat)*Math.sin(blat))
\r
181 // )/DEGREES_2_RADIANS;
\r
186 * This method was 50% faster than calculation 1, and 75% than the Haverside method
\r
187 * Also, since it's based off of Agree standard Degrees of the Earth, etc, the calculations are more exact,
\r
188 * at least for Nautical Miles and Kilometers
\r