36906188849ebd0e039dfdd65ab3de802b8400c5
[aaf/authz.git] / cadi / client / src / main / java / org / onap / aaf / cadi / routing / GreatCircle.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.cadi.routing;
23
24 import org.onap.aaf.misc.env.util.Split;
25
26 public class GreatCircle {
27         // Note: multiplying by this constant is faster than calling Math equivalent function 
28         private static final double DEGREES_2_RADIANS = Math.PI/180.0;
29         
30         public static final double DEGREES_2_NM = 60;
31         public static final double DEGREES_2_KM = DEGREES_2_NM * 1.852; // 1.852 is exact ratio per 1929 Standard Treaty, adopted US 1954
32         public static final double DEGREES_2_MI = DEGREES_2_NM * 1.1507795; 
33         
34         /**
35          * 
36          * Calculate the length of an arc on a perfect sphere based on Latitude and Longitudes of two points
37          *    Parameters are in Degrees (i.e. the coordinate system you get from GPS, Mapping WebSites, Phones, etc)
38          *    
39          *              L1 = Latitude of point A
40          *      G1 = Longitude of point A
41          *          L2 = Latitude of point B
42          *      G2 = Longitude of point B
43          *      
44          *      d  = acos (sin(L1)*sin(L2) + cos(L1)*cos(L2)*cos(G1 - G2))
45          * 
46          * Returns answer in Degrees
47          * 
48          * Since there are 60 degrees per nautical miles, you can convert to NM by multiplying by 60
49          * 
50          * Essential formula from a Princeton website, the "Law of Cosines" method.  
51          * 
52          * Refactored cleaned up for speed Jonathan 3/8/2013
53          * 
54          * @param latA
55          * @param lonA
56          * @param latB
57          * @param lonB
58          * @return
59          */
60         public static double calc(double latA, double lonA, double latB, double lonB) {
61                 // Formula requires Radians.  Expect Params to be Coordinates (Degrees)
62                 // Simple ratio, quicker than calling Math.toRadians()
63                 latA *= DEGREES_2_RADIANS;
64                 lonA *= DEGREES_2_RADIANS;
65                 latB *= DEGREES_2_RADIANS;
66                 lonB *= DEGREES_2_RADIANS;
67
68                 return Math.acos(
69                                 Math.sin(latA) * Math.sin(latB) + 
70                                 Math.cos(latA) * Math.cos(latB) * Math.cos(lonA-lonB)
71                         )
72                         / DEGREES_2_RADIANS;
73         }
74         
75         /** 
76          * Convert from "Lat,Long Lat,Long" String format
77          *              "Lat,Long,Lat,Long" Format
78          *           or all four entries "Lat Long Lat Long"
79          * 
80          * (Convenience function)
81          * 
82          * Since Distance is positive, a "-1" indicates an error in String formatting
83          */
84         public static double calc(String ... coords) {
85                 try {
86                         String [] array;
87                         switch(coords.length) {
88                         case 1:
89                                 array = Split.split(',',coords[0]);
90                                 if(array.length!=4)return -1;
91                                 return calc(
92                                         Double.parseDouble(array[0]),
93                                         Double.parseDouble(array[1]),
94                                         Double.parseDouble(array[2]),
95                                         Double.parseDouble(array[3])
96                                         );
97                         case 2:
98                                 array = Split.split(',',coords[0]);
99                                 String [] array2 = Split.split(',',coords[1]);
100                                 if(array.length!=2 || array2.length!=2)return -1;
101                                 return calc(
102                                         Double.parseDouble(array[0]),
103                                         Double.parseDouble(array[1]),
104                                         Double.parseDouble(array2[0]),
105                                         Double.parseDouble(array2[1])
106                                         );
107                         case 4:
108                                 return calc(
109                                         Double.parseDouble(coords[0]),
110                                         Double.parseDouble(coords[1]),
111                                         Double.parseDouble(coords[2]),
112                                         Double.parseDouble(coords[3])
113                                         );
114                                 
115                         default:
116                                 return -1;
117                         }
118                 } catch (NumberFormatException e) {
119                         return -1;
120                 }
121         }
122
123 }
124
125 ///**
126 //* Haverside method, from Princeton
127 //* 
128 //* @param alat
129 //* @param alon
130 //* @param blat
131 //* @param blon
132 //* @return
133 //*/
134 //public static double calc3(double alat, double alon, double blat, double blon) {
135 //      alat *= DEGREES_2_RADIANS;
136 //      alon *= DEGREES_2_RADIANS;
137 //      blat *= DEGREES_2_RADIANS;
138 //      blon *= DEGREES_2_RADIANS;
139 //      return 2 * Math.asin(
140 //                      Math.min(1, Math.sqrt(
141 //                              Math.pow(Math.sin((blat-alat)/2), 2) +
142 //                              (Math.cos(alat)*Math.cos(blat)*
143 //                                      Math.pow(
144 //                                              Math.sin((blon-alon)/2),2)
145 //                                      )
146 //                              )
147 //                      )
148 //              )
149 //      / DEGREES_2_RADIANS;
150 //}
151 //
152
153
154
155 //This is a MEAN radius.  The Earth is not perfectly spherical
156 //      public static final double EARTH_RADIUS_KM = 6371.0;
157 //      public static final double EARTH_RADIUS_NM = 3440.07;
158 //      public static final double KM_2_MILES_RATIO = 0.621371192;
159 ///**
160 //* Code on Internet based on Unknown book.  Lat/Long is in Degrees
161 //* @param alat
162 //* @param alon
163 //* @param blat
164 //* @param blon
165 //* @return
166 //*/
167 //public static double calc1(double alat, double alon, double blat, double blon) {
168 //      alat *= DEGREES_2_RADIANS;
169 //      alon *= DEGREES_2_RADIANS;
170 //      blat *= DEGREES_2_RADIANS;
171 //      blon *= DEGREES_2_RADIANS;
172 //      
173 //      // Reused values
174 //      double cosAlat,cosBlat;
175 //      
176 //      return Math.acos(
177 //              ((cosAlat=Math.cos(alat))*Math.cos(alon)*(cosBlat=Math.cos(blat))*Math.cos(blon)) +
178 //              (cosAlat*Math.sin(alon)*cosBlat*Math.sin(blon)) +
179 //              (Math.sin(alat)*Math.sin(blat))
180 //              )/DEGREES_2_RADIANS;
181 //      
182 //}
183
184 /*
185 *  This method was 50% faster than calculation 1, and 75% than the Haverside method
186 *  Also, since it's based off of Agree standard Degrees of the Earth, etc, the calculations are more exact,
187 *    at least for Nautical Miles and Kilometers
188 */