Advertisement
Guest User

Untitled

a guest
Mar 27th, 2012
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.18 KB | None | 0 0
  1. class Location
  2. {
  3.     protected $longitude;
  4.     protected $latitude;
  5.    
  6.     /**
  7.      * Constructs a new location.
  8.      *
  9.      * @param float $lat
  10.      * @param float $lon
  11.      * @throws InvalidArgumentException
  12.      */
  13.     public function __construct($lat, $lon)
  14.     {
  15.         $this->setLatitude($lat);
  16.         $this->setLongitude($lon);
  17.     }
  18.    
  19.     public function bearingTo(Location $location)
  20.     {
  21.         $result = $this->distanceAndBearing($location);
  22.         return $result['bearing'];
  23.     }
  24.    
  25.     /**
  26.      * Returns the approximate distance in meters between this location and the given location.
  27.      *
  28.      * @returns float
  29.      */
  30.     public function distanceTo(Location $location)
  31.     {
  32.         $result = $this->distanceAndBearing($location);
  33.         return $result['distance'];
  34.     }
  35.    
  36.     /**
  37.      * Returns the latitude for this location.
  38.      *
  39.      * @return float
  40.      */
  41.     public function getLatitude()
  42.     {
  43.         return $this->latitude;
  44.     }
  45.  
  46.     /**
  47.      * Returns the longitude for this location.
  48.      *
  49.      * @return float
  50.      */
  51.     public function getLongitude()
  52.     {
  53.         return $this->longitude;
  54.     }
  55.    
  56.     /**
  57.      * Sets the latitude for this location.
  58.      *
  59.      * @param float $latitude
  60.      * @throws InvalidArgumentException
  61.      */
  62.     public function setLatitude($latitude)
  63.     {
  64.         if (!is_numeric($latitude))
  65.         {
  66.             throw new InvalidArgumentException("Argument must be numeric.");
  67.         }
  68.         $this->latitude = (float) $latitude;
  69.     }
  70.    
  71.     /**
  72.      * Sets the longitude for this location.
  73.      *
  74.      * @param float $longitude
  75.      * @throws InvalidArgumentException
  76.      */
  77.     public function setLongitude($longitude)
  78.     {
  79.         if (!is_numeric($longitude))
  80.         {
  81.             throw new InvalidArgumentException("Argument must be numeric.");
  82.         }
  83.         $this->longitude = (float) $longitude;
  84.     }
  85.    
  86.     private function distanceAndBearing(Location $location)
  87.     {
  88.         // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
  89.         // using the "Inverse Formula" (section 4)
  90.         $lat1 = deg2rad($this->getLatitude());
  91.         $lat2 = deg2rad($location->getLatitude());
  92.         $lon1 = deg2rad($this->getLongitude());
  93.         $lon2 = deg2rad($location->getLongitude());
  94.        
  95.         $major = 6378137.0;
  96.         $minor = 6356752.3142;
  97.         $f = ($major-$minor)/$major;
  98.        
  99.         $aSqMinusBSqOverBSq = (pow($major, 2) - pow($minor, 2))/($minor*$minor);
  100.         $L = $lon2 - $lon1;
  101.         $U1 = atan((1.0 - $f) * tan($lat1));
  102.         $U2 = atan((1.0 - $f) * tan($lat2));
  103.        
  104.         $cosU1 = cos($U1);
  105.         $cosU2 = cos($U2);
  106.         $sinU1 = sin($U1);
  107.         $sinU2 = sin($U2);
  108.         $sinU1sinU2 = $sinU1 * $sinU2;
  109.         $cosU1cosU2 = $cosU1 * $cosU2;
  110.        
  111.         $A = 0.0;
  112.         $cos2SM = 0.0;
  113.         $sinSigma = 0.0;
  114.         $cosSigma = 0.0;
  115.         $deltaSigma = 0.0;
  116.         $sinLambda = 0.0;
  117.         $cosLambda = 0.0;
  118.         $sigma = 0.0;
  119.         $lambda = $L;
  120.        
  121.         for ($i = 0; $i < 20; $i++)
  122.         {
  123.             $lambdaOrig = $lambda;
  124.             $cosLambda = cos($lambda);
  125.             $sinLambda = sin($lambda);
  126.             $t1 = $cosU1 * $sinLambda;
  127.             $t2 = $cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda;
  128.             $sinSqSigma = pow($t1, 2) + pow($t2, 2);
  129.             $sinSigma = sqrt($sinSqSigma);
  130.             $sinAlpha = ($sinSigma == 0) ? 0.0 : $cosU1cosU2 * $sinLambda / $sinSigma;
  131.             $cosSqAlpha = 1.0 - pow($sinAlpha, 2);
  132.             $uSq = $cosSqAlpha * $aSqMinusBSqOverBSq;
  133.  
  134.             $A = 1 + ($uSq / 16384.0) * (4096.0 + $uSq * (-768 + $uSq * (320.0 - 175.0 * $uSq)));
  135.             $B = ($uSq / 1024.0) * (256.0 + $uSq * (-128.0 + $uSq * (74.0 - 47.0 * $uSq)));
  136.             $C = ($f / 16.0) * $cosSqAlpha * (4.0 + $f * (4.0 - 3.0 * $cosSqAlpha));
  137.  
  138.             $cosSigma = $sinU1sinU2 + $cosU1cosU2 * $cosLambda;
  139.             $cos2SM = ($cosSqAlpha == 0) ? 0.0 : $cosSigma - 2.0 * $sinU1sinU2 / $cosSqAlpha;
  140.            
  141.             $sigma = atan2($sinSigma, $cosSigma);
  142.             $cos2SMSq = pow($cos2SM, 2);
  143.             $deltaSigma = $B * $sinSigma * ($cos2SM + ($B / 4.0) * ($cosSigma * (-1.0 + 2.0 * $cos2SMSq) - ($B / 6.0) * $cos2SM * (-3.0 + 4.0 * pow($sinSigma, 2)) * (-3.0 + 4.0 * $cos2SMSq)));
  144.            
  145.             $lambda = $L + (1.0 - $C) * $f * $sinAlpha * ($sigma + $C * $sinSigma * ($cos2SM + $C * $cosSigma * (-1.0 + 2.0 * $cos2SM * $cos2SM)));
  146.             $delta = ($lambda - $lambdaOrig) / $lambda;
  147.             if (abs($delta) < 1.0e-12) break;
  148.         }
  149.         $distance = (float) ($minor * $A * ($sigma - $deltaSigma));
  150.         $bearing = (float) rad2deg(atan2($cosU2 * $sinLambda, $cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda));
  151.        
  152.         return array(
  153.             'distance' => $distance,
  154.             'bearing' => $bearing
  155.         );
  156.     }
  157. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement