Example #1
0
 /**
  * Create a Geodetic point from a Geocentric point.
  */
 public static function fromGeocentric(Geocentric $point)
 {
     // Local definitions and variables
     // end-criterium of loop, accuracy of sin(Latitude)
     $genau = 1.0E-12;
     $genau2 = $genau * $genau;
     $maxiter = 30;
     $X = $point->x;
     $Y = $point->y;
     // Z value not always supplied
     // CHECKME: this does not make sense. Without Z we are talking about a flat
     // plain, and not a 3D point in space.
     $Z = $point->z ? $point->z : 0.0;
     /*
     $P;        // distance between semi-minor axis and location 
     $RR;       // distance between center and location
     $CT;       // sin of geocentric latitude 
     $ST;       // cos of geocentric latitude 
     $RX;
     $RK;
     $RN;       // Earth radius at location 
     $CPHI0;    // cos of start or old geodetic latitude in iterations 
     $SPHI0;    // sin of start or old geodetic latitude in iterations 
     $CPHI;     // cos of searched geodetic latitude
     $SPHI;     // sin of searched geodetic latitude 
     $SDPHI;    // end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) 
     $at_pole;     // indicates location is in polar region 
     $iter;        // of continous iteration, max. 30 is always enough (s.a.) 
     $lon;
     $lat;
     $height;
     */
     $a = $point->getEllipsoid()->a;
     $b = $point->getEllipsoid()->b;
     $at_pole = false;
     // The distance from the axis passing through the poles.
     $P = sqrt($X * $X + $Y * $Y);
     $RR = sqrt($X * $X + $Y * $Y + $Z * $Z);
     // Special cases for latitude and longitude.
     if ($P / $a < $genau) {
         // Special case: at the poles if P=0. (X=0, Y=0)
         $at_pole = true;
         $lon = 0.0;
         // If (X,Y,Z)=(0,0,0) then Height becomes semi-minor axis
         // of ellipsoid (=center of mass) and Latitude becomes PI/2
         if ($RR / $a < $genau) {
             $lat = M_PI_2;
             $height = -$b;
             return;
         }
     } else {
         // Ellipsoidal (geodetic) longitude interval:
         // -PI < Longitude <= +PI
         $lon = atan2($Y, $X);
     }
     // The eccentricity squared.
     $es = $point->getEllipsoid()->es;
     /* --------------------------------------------------------------
      * Following iterative algorithm was developped by
      * "Institut für Erdmessung", University of Hannover, July 1988.
      * Internet: www.ife.uni-hannover.de
      * Iterative computation of CPHI,SPHI and Height.
      * Iteration of CPHI and SPHI to 10**-12 radian res$p->
      * 2*10**-7 arcsec.
      * --------------------------------------------------------------
      */
     $CT = $Z / $RR;
     $ST = $P / $RR;
     $RX = 1.0 / sqrt(1.0 - $es * (2.0 - $es) * $ST * $ST);
     $CPHI0 = $ST * (1.0 - $es) * $RX;
     $SPHI0 = $CT * $RX;
     $iter = 0;
     // Loop to find sin(Latitude) res $p-> Latitude
     // until |sin(Latitude(iter)-Latitude(iter-1))| < genau
     do {
         ++$iter;
         $RN = $a / sqrt(1.0 - $es * $SPHI0 * $SPHI0);
         // Ellipsoidal (geodetic) height
         $height = $P * $CPHI0 + $Z * $SPHI0 - $RN * (1.0 - $es * $SPHI0 * $SPHI0);
         $RK = $es * $RN / ($RN + $height);
         $RX = 1.0 / sqrt(1.0 - $RK * (2.0 - $RK) * $ST * $ST);
         $CPHI = $ST * (1.0 - $RK) * $RX;
         $SPHI = $CT * $RX;
         $SDPHI = $SPHI * $CPHI0 - $CPHI * $SPHI0;
         $CPHI0 = $CPHI;
         $SPHI0 = $SPHI;
     } while ($SDPHI * $SDPHI > $genau2 && $iter < $maxiter);
     // Ellipsoidal (geodetic) latitude
     $lat = atan($SPHI / abs($CPHI));
     // Create a new Geodetic coordinate.
     // Keep the same datum as the current point.
     $geodetic_point = new static(rad2deg($lat), rad2deg($lon), $height, $point->getDatum());
     return $geodetic_point;
 }
Example #2
0
 /**
  * Convert a geocentric point from the WGS84 datum.
  */
 public function fromWgs84(Geocentric $point)
 {
     if ($this->type == static::TYPE_3TERM) {
         $x = $point->x - $this->params[0];
         $y = $point->y - $this->params[1];
         $z = $point->z - $this->params[2];
     } elseif ($this->type == static::TYPE_7TERM) {
         $Dx_BF = $this->params[0];
         $Dy_BF = $this->params[1];
         $Dz_BF = $this->params[2];
         // These need converting from seconds of arc to radians.
         $Rx_BF = $this->params[3] * static::SEC_TO_RAD;
         $Ry_BF = $this->params[4] * static::SEC_TO_RAD;
         $Rz_BF = $this->params[5] * static::SEC_TO_RAD;
         // Convert parts per million to a multiplier
         $M_BF = 1 + $this->params[6] * static::PPM_TO_MULT;
         $x_tmp = ($point->x - $Dx_BF) / $M_BF;
         $y_tmp = ($point->y - $Dy_BF) / $M_BF;
         $z_tmp = ($point->z - $Dz_BF) / $M_BF;
         $x = $x_tmp + $Rz_BF * $y_tmp - $Ry_BF * $z_tmp;
         $y = -$Rz_BF * $x_tmp + $y_tmp + $Rx_BF * $z_tmp;
         $z = $Ry_BF * $x_tmp - $Rx_BF * $y_tmp + $z_tmp;
     } else {
         throw new Excreption('Unknown datum transformation parameter type');
     }
     // Give the point the new datum.
     $new_point = $point->withOrdinates($x, $y, $z)->withDatum($this);
     return $new_point;
 }