Coverage Report - datafu.pig.geo.HaversineDistInMiles
 
Classes in this File Line Coverage Branch Coverage Complexity
HaversineDistInMiles
88%
8/9
50%
4/8
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  
 }