@@ -119,91 +119,71 @@ public BBox createBBox(double lat, double lon, double radiusInMeter) {
119
119
public double calcNormalizedEdgeDistance (double r_lat_deg , double r_lon_deg ,
120
120
double a_lat_deg , double a_lon_deg ,
121
121
double b_lat_deg , double b_lon_deg ) {
122
- return calcNormalizedEdgeDistanceNew (r_lat_deg , r_lon_deg , a_lat_deg , a_lon_deg , b_lat_deg , b_lon_deg , false );
123
- }
124
-
125
- @ Override
126
- public double calcNormalizedEdgeDistance3D (double r_lat_deg , double r_lon_deg , double r_ele_m ,
127
- double a_lat_deg , double a_lon_deg , double a_ele_m ,
128
- double b_lat_deg , double b_lon_deg , double b_ele_m ) {
129
- if (Double .isNaN (r_ele_m ) || Double .isNaN (a_ele_m ) || Double .isNaN (b_ele_m ))
130
- return calcNormalizedEdgeDistance (r_lat_deg , r_lon_deg , a_lat_deg , a_lon_deg , b_lat_deg , b_lon_deg );
131
-
132
122
double shrinkFactor = calcShrinkFactor (a_lat_deg , b_lat_deg );
133
123
134
124
double a_lat = a_lat_deg ;
135
125
double a_lon = a_lon_deg * shrinkFactor ;
136
- double a_ele = a_ele_m / METERS_PER_DEGREE ;
137
126
138
127
double b_lat = b_lat_deg ;
139
128
double b_lon = b_lon_deg * shrinkFactor ;
140
- double b_ele = b_ele_m / METERS_PER_DEGREE ;
141
129
142
130
double r_lat = r_lat_deg ;
143
131
double r_lon = r_lon_deg * shrinkFactor ;
144
- double r_ele = r_ele_m / METERS_PER_DEGREE ;
145
132
146
133
double delta_lon = b_lon - a_lon ;
147
134
double delta_lat = b_lat - a_lat ;
148
- double delta_ele = b_ele - a_ele ;
149
135
150
- double norm = delta_lon * delta_lon + delta_lat * delta_lat + delta_ele * delta_ele ;
151
- double factor = ((r_lon - a_lon ) * delta_lon + (r_lat - a_lat ) * delta_lat + (r_ele - a_ele ) * delta_ele ) / norm ;
136
+ if (delta_lat == 0 )
137
+ // special case: horizontal edge
138
+ return calcNormalizedDist (a_lat_deg , r_lon_deg , r_lat_deg , r_lon_deg );
152
139
153
- // x,y,z is projection of r onto segment a-b
140
+ if (delta_lon == 0 )
141
+ // special case: vertical edge
142
+ return calcNormalizedDist (r_lat_deg , a_lon_deg , r_lat_deg , r_lon_deg );
143
+
144
+ double norm = delta_lon * delta_lon + delta_lat * delta_lat ;
145
+ double factor = ((r_lon - a_lon ) * delta_lon + (r_lat - a_lat ) * delta_lat ) / norm ;
146
+
147
+ // x,y is projection of r onto segment a-b
154
148
double c_lon = a_lon + factor * delta_lon ;
155
149
double c_lat = a_lat + factor * delta_lat ;
156
- double c_ele_m = (a_ele + factor * delta_ele ) * METERS_PER_DEGREE ;
157
- return calcNormalizedDist (c_lat , c_lon / shrinkFactor , r_lat_deg , r_lon_deg ) + calcNormalizedDist (r_ele_m - c_ele_m );
150
+ return calcNormalizedDist (c_lat , c_lon / shrinkFactor , r_lat_deg , r_lon_deg );
158
151
}
159
152
160
- /**
161
- * New edge distance calculation where no validEdgeDistance check would be necessary
162
- * <p>
163
- *
164
- * @return the normalized distance of the query point "r" to the project point "c" onto the line
165
- * segment a-b
166
- */
167
- public double calcNormalizedEdgeDistanceNew (double r_lat_deg , double r_lon_deg ,
168
- double a_lat_deg , double a_lon_deg ,
169
- double b_lat_deg , double b_lon_deg ,
170
- boolean reduceToSegment ) {
153
+ @ Override
154
+ public double calcNormalizedEdgeDistance3D (double r_lat_deg , double r_lon_deg , double r_ele_m ,
155
+ double a_lat_deg , double a_lon_deg , double a_ele_m ,
156
+ double b_lat_deg , double b_lon_deg , double b_ele_m ) {
157
+ if (Double .isNaN (r_ele_m ) || Double .isNaN (a_ele_m ) || Double .isNaN (b_ele_m ))
158
+ return calcNormalizedEdgeDistance (r_lat_deg , r_lon_deg , a_lat_deg , a_lon_deg , b_lat_deg , b_lon_deg );
159
+
171
160
double shrinkFactor = calcShrinkFactor (a_lat_deg , b_lat_deg );
172
161
173
162
double a_lat = a_lat_deg ;
174
163
double a_lon = a_lon_deg * shrinkFactor ;
164
+ double a_ele = a_ele_m / METERS_PER_DEGREE ;
175
165
176
166
double b_lat = b_lat_deg ;
177
167
double b_lon = b_lon_deg * shrinkFactor ;
168
+ double b_ele = b_ele_m / METERS_PER_DEGREE ;
178
169
179
170
double r_lat = r_lat_deg ;
180
171
double r_lon = r_lon_deg * shrinkFactor ;
172
+ double r_ele = r_ele_m / METERS_PER_DEGREE ;
181
173
182
174
double delta_lon = b_lon - a_lon ;
183
175
double delta_lat = b_lat - a_lat ;
176
+ double delta_ele = b_ele - a_ele ;
184
177
185
- if (delta_lat == 0 )
186
- // special case: horizontal edge
187
- return calcNormalizedDist (a_lat_deg , r_lon_deg , r_lat_deg , r_lon_deg );
188
-
189
- if (delta_lon == 0 )
190
- // special case: vertical edge
191
- return calcNormalizedDist (r_lat_deg , a_lon_deg , r_lat_deg , r_lon_deg );
192
-
193
- double norm = delta_lon * delta_lon + delta_lat * delta_lat ;
194
- double factor = ((r_lon - a_lon ) * delta_lon + (r_lat - a_lat ) * delta_lat ) / norm ;
178
+ double norm = delta_lon * delta_lon + delta_lat * delta_lat + delta_ele * delta_ele ;
179
+ double factor = ((r_lon - a_lon ) * delta_lon + (r_lat - a_lat ) * delta_lat + (r_ele - a_ele ) * delta_ele ) / norm ;
180
+ if (Double .isNaN (factor )) factor = 0 ;
195
181
196
- // make new calculation compatible to old
197
- if (reduceToSegment ) {
198
- if (factor > 1 )
199
- factor = 1 ;
200
- else if (factor < 0 )
201
- factor = 0 ;
202
- }
203
- // x,y is projection of r onto segment a-b
182
+ // x,y,z is projection of r onto segment a-b
204
183
double c_lon = a_lon + factor * delta_lon ;
205
184
double c_lat = a_lat + factor * delta_lat ;
206
- return calcNormalizedDist (c_lat , c_lon / shrinkFactor , r_lat_deg , r_lon_deg );
185
+ double c_ele_m = (a_ele + factor * delta_ele ) * METERS_PER_DEGREE ;
186
+ return calcNormalizedDist (c_lat , c_lon / shrinkFactor , r_lat_deg , r_lon_deg ) + calcNormalizedDist (r_ele_m - c_ele_m );
207
187
}
208
188
209
189
double calcShrinkFactor (double a_lat_deg , double b_lat_deg ) {
@@ -300,6 +280,41 @@ public GHPoint projectCoordinate(double latInDeg, double lonInDeg, double distan
300
280
return new GHPoint (projectedLat , projectedLon );
301
281
}
302
282
283
+ @ Override
284
+ public GHPoint intermediatePoint (double f , double lat1 , double lon1 , double lat2 , double lon2 ) {
285
+ double lat1radians = Math .toRadians (lat1 );
286
+ double lon1radians = Math .toRadians (lon1 );
287
+ double lat2radians = Math .toRadians (lat2 );
288
+ double lon2radians = Math .toRadians (lon2 );
289
+
290
+ // This formula is taken from: (http://www.movable-type.co.uk/scripts/latlong.html -> https://github.com/chrisveness/geodesy MIT)
291
+
292
+ double deltaLat = lat2radians - lat1radians ;
293
+ double deltaLon = lon2radians - lon1radians ;
294
+ double cosLat1 = cos (lat1radians );
295
+ double cosLat2 = cos (lat2radians );
296
+ double sinHalfDeltaLat = sin (deltaLat / 2 );
297
+ double sinHalfDeltaLon = sin (deltaLon / 2 );
298
+
299
+ double a = sinHalfDeltaLat * sinHalfDeltaLat + cosLat1 * cosLat2 * sinHalfDeltaLon * sinHalfDeltaLon ;
300
+ double angularDistance = 2 * Math .atan2 (Math .sqrt (a ), Math .sqrt (1 -a ));
301
+ double sinDistance = sin (angularDistance );
302
+
303
+ if (angularDistance == 0 ) return new GHPoint (lat1 , lon1 );
304
+
305
+ double A = Math .sin ((1 -f )*angularDistance ) / sinDistance ;
306
+ double B = Math .sin (f *angularDistance ) / sinDistance ;
307
+
308
+ double x = A * cosLat1 * cos (lon1radians ) + B * cosLat2 * cos (lon2radians );
309
+ double y = A * cosLat1 * sin (lon1radians ) + B * cosLat2 * sin (lon2radians );
310
+ double z = A * sin (lat1radians ) + B * sin (lat2radians );
311
+
312
+ double midLat = Math .toDegrees (Math .atan2 (z , Math .sqrt (x *x + y *y )));
313
+ double midLon = Math .toDegrees (Math .atan2 (y , x ));
314
+
315
+ return new GHPoint (midLat , midLon );
316
+ }
317
+
303
318
@ Override
304
319
public boolean isCrossBoundary (double lon1 , double lon2 ) {
305
320
return abs (lon1 - lon2 ) > 300 ;
0 commit comments