Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
HaversineDistInMiles |
|
| 3.5;3.5 |
1 | /* | |
2 | * Copyright 2010 LinkedIn, Inc | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
5 | * use this file except in compliance with the License. You may obtain a copy of | |
6 | * the License at | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
13 | * License for the specific language governing permissions and limitations under | |
14 | * the License. | |
15 | */ | |
16 | ||
17 | package datafu.pig.geo; | |
18 | ||
19 | import org.apache.pig.data.DataType; | |
20 | import org.apache.pig.impl.logicalLayer.schema.Schema; | |
21 | ||
22 | import datafu.pig.util.SimpleEvalFunc; | |
23 | ||
24 | /** | |
25 | * Computes the distance (in miles) between two latitude-longitude pairs | |
26 | * using the {@link <a href="http://en.wikipedia.org/wiki/Haversine_formula" target="_blank">Haversine formula</a>}. | |
27 | * | |
28 | * <p> | |
29 | * Example: | |
30 | * <pre> | |
31 | * {@code | |
32 | * -- input is a TSV of two latitude and longitude pairs | |
33 | * input = LOAD 'input' AS (lat1 : double, long1 : double, lat2 : double, long2 : double); | |
34 | * output = FOREACH input GENERATE datafu.pig.geo.HaversineDistInMiles(lat1, long1, lat2, long2) as distance; | |
35 | * }</pre></p> | |
36 | */ | |
37 | 731 | public class HaversineDistInMiles extends SimpleEvalFunc<Double> |
38 | { | |
39 | public static final double EARTH_RADIUS = 3958.75; | |
40 | ||
41 | public Double call(Double lat1, Double lng1, Double lat2, Double lng2) | |
42 | { | |
43 | 4 | if (lat1 == null || lng1 == null || lat2 == null || lng2 == null) |
44 | 0 | return null; |
45 | ||
46 | 4 | double d_lat = Math.toRadians(lat2-lat1); |
47 | 4 | double d_long = Math.toRadians(lng2-lng1); |
48 | 4 | double a = Math.sin(d_lat/2) * Math.sin(d_lat/2) + |
49 | Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * | |
50 | Math.sin(d_long/2) * Math.sin(d_long/2); | |
51 | 4 | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); |
52 | 4 | return EARTH_RADIUS * c; |
53 | } | |
54 | ||
55 | @Override | |
56 | public Schema outputSchema(Schema input) | |
57 | { | |
58 | 121 | return new Schema(new Schema.FieldSchema("dist", DataType.DOUBLE)); |
59 | } | |
60 | } |