Exemplo n.º 1
0
 /**
  * Get the distance between two Latitude/Longitude objects using the Vincenty formula
  *
  * The Vincenty Formula calculates the distance to your destination point based on the specified ellipsoid
  *
  * @param     LatLong               $endPoint    The destination point
  * @param     ReferenceEllipsoid    $ellipsoid
  * @return    Distance              The great circle distance between this Lat/Long and the $endpoint Lat/Long
  * @throws    Exception
  */
 public function getDistanceVincenty(LatLong $endPoint, ReferenceEllipsoid $ellipsoid = null)
 {
     if (is_null($ellipsoid)) {
         $ellipsoid = new ReferenceEllipsoid(ReferenceEllipsoid::WGS_84);
     }
     $semiMinor = $ellipsoid->getSemiMinorAxis();
     $flattening = $ellipsoid->getFlattening();
     $lDifference = $this->longitude->getValue(Angle::RADIANS) - $endPoint->getLongitude()->getValue(Angle::RADIANS);
     $U1Value = atan((1 - $flattening) * tan($endPoint->getLatitude()->getValue(Angle::RADIANS)));
     $U2Value = atan((1 - $flattening) * tan($this->latitude->getValue(Angle::RADIANS)));
     $sinU1 = sin($U1Value);
     $cosU1 = cos($U1Value);
     $sinU2 = sin($U2Value);
     $cosU2 = cos($U2Value);
     $lambda = $lDifference;
     $lambdaP = 2 * M_PI;
     $iterLimit = 20;
     while (abs($lambda - $lambdaP) > 1.0E-12 && $iterLimit > 0) {
         $sinLambda = sin($lambda);
         $cosLambda = cos($lambda);
         $sinSigma = sqrt($cosU2 * $sinLambda * ($cosU2 * $sinLambda) + ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda) * ($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda));
         if ($sinSigma == 0.0) {
             //  co-incident points
             return new Distance();
         }
         $cosSigma = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosLambda;
         $sigma = atan2($sinSigma, $cosSigma);
         $alpha = asin($cosU1 * $cosU2 * $sinLambda / $sinSigma);
         $cosSqAlpha = cos($alpha) * cos($alpha);
         $cos2SigmaM = $cosSigma - 2 * $sinU1 * $sinU2 / $cosSqAlpha;
         $cValue = $flattening / 16 * $cosSqAlpha * (4 + $flattening * (4 - 3 * $cosSqAlpha));
         $lambdaP = $lambda;
         $lambda = $lDifference + (1 - $cValue) * $flattening * sin($alpha) * ($sigma + $cValue * $sinSigma * ($cos2SigmaM + $cValue * $cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM)));
     }
     $uSq = $cosSqAlpha * $ellipsoid->getSecondEccentricitySquared();
     $aValue = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq)));
     $bValue = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq)));
     $deltaSigma = $bValue * $sinSigma * ($cos2SigmaM + $bValue / 4 * ($cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM) - $bValue / 6 * $cos2SigmaM * (-3 + 4 * $sinSigma * $sinSigma) * (-3 + 4 * $cos2SigmaM * $cos2SigmaM)));
     return new Distance($semiMinor * $aValue * ($sigma - $deltaSigma));
 }
 public function testGetEllipsoidNames()
 {
     $referenceEllipsoidNames = ReferenceEllipsoid::getEllipsoidNames();
     $this->assertGreaterThan(0, count($referenceEllipsoidNames));
     $this->assertTrue(in_array('Airy (1830)', $referenceEllipsoidNames));
 }
Exemplo n.º 3
0
 /**
  * Get the Area of this region
  *
  * The algorithm used here is derived from the algorithm used by the GRASS GIS package
  *
  * @param     ReferenceEllipsoid|null    $ellipsoid    Reference Ellipsoid to use for this calculation
  *                                                              If null, then the WGS 1984 Ellipsoid will be used
  * @return    Area    The area of this region
  */
 public function getArea(ReferenceEllipsoid $ellipsoid = null)
 {
     $pointCount = count($this->nodePoints);
     if ($pointCount == 0) {
         return new Area();
     } elseif (is_null($ellipsoid)) {
         $ellipsoid = new ReferenceEllipsoid(ReferenceEllipsoid::WGS_1984);
     }
     $semiMajorAxis = $ellipsoid->getSemiMajorAxis();
     $eccentricitySquared = $ellipsoid->getFirstEccentricitySquared();
     $eccentricity4 = $eccentricitySquared * $eccentricitySquared;
     $eccentricity6 = $eccentricity4 * $eccentricitySquared;
     $AE = $semiMajorAxis * $semiMajorAxis * (1 - $eccentricitySquared);
     $this->QA = 2.0 / 3.0 * $eccentricitySquared;
     $this->QB = 3.0 / 5.0 * $eccentricity4;
     $this->QC = 4.0 / 7.0 * $eccentricity6;
     $this->QbarA = -1.0 - 2.0 / 3.0 * $eccentricitySquared - 3.0 / 5.0 * $eccentricity4 - 4.0 / 7.0 * $eccentricity6;
     $this->QbarB = 2.0 / 9.0 * $eccentricitySquared + 2.0 / 5.0 * $eccentricity4 + 4.0 / 7.0 * $eccentricity6;
     $this->QbarC = -(3.0 / 25.0) * $eccentricity4 - 12.0 / 35.0 * $eccentricity6;
     $this->QbarD = 4.0 / 49.0 * $eccentricity6;
     $Qp = $this->_Q(M_PI_2);
     $pointCount--;
     $longitude2 = $this->nodePoints[$pointCount]->getLongitude()->getValue(Angle::RADIANS);
     $latitude2 = $this->nodePoints[$pointCount]->getLatitude()->getValue(Angle::RADIANS);
     $Qbar2 = $this->_Qbar($latitude2);
     $area = 0.0;
     $n = 0;
     while ($n++ < $pointCount) {
         $longitude1 = $longitude2;
         $latitude1 = $latitude2;
         $Qbar1 = $Qbar2;
         $longitude2 = $this->nodePoints[$n]->getLongitude()->getValue(Angle::RADIANS);
         $latitude2 = $this->nodePoints[$n]->getLatitude()->getValue(Angle::RADIANS);
         $Qbar2 = $this->_Qbar($latitude2);
         self::datelineAdjust($longitude1, $longitude2);
         $deltaLongitude = $longitude2 - $longitude1;
         $area += $deltaLongitude * ($Qp - $this->_Q($latitude2));
         if (($deltaLatitude = $latitude2 - $latitude1) != 0.0) {
             $area += $deltaLongitude * $this->_Q($latitude2) - $deltaLongitude / $deltaLatitude * ($Qbar2 - $Qbar1);
         }
     }
     $area = self::polarAdjust($area, $AE, $Qp);
     return new Area($area);
 }