/** @return Vector */
 public function toCartesian()
 {
     $Glat = Misc::toRadians($this->lat);
     $Glng = Misc::toRadians($this->lng);
     $h = 0;
     // height above ellipsoid - not currently used
     $a = $this->datum->getEllipsoid()->getA();
     $b = $this->datum->getEllipsoid()->getB();
     $sinGlat = sin($Glat);
     $cosGlat = cos($Glat);
     $sinGlng = sin($Glng);
     $cosGlng = cos($Glng);
     $eSq = ($a * $a - $b * $b) / ($a * $a);
     $v = $a / sqrt(1 - $eSq * $sinGlat * $sinGlat);
     $x = ($v + $h) * $cosGlat * $cosGlng;
     $y = ($v + $h) * $cosGlat * $sinGlng;
     $z = ((1 - $eSq) * $v + $h) * $sinGlat;
     return new Vector($x, $y, $z);
 }
 public function toLatLng(Datum $datum)
 {
     $ellipsoid = $datum->getEllipsoid();
     $e2 = ($ellipsoid->getA() * $ellipsoid->getA() - $ellipsoid->getB() * $ellipsoid->getB()) / ($ellipsoid->getA() * $ellipsoid->getA());
     // 1st eccentricity squared
     $G12 = ($ellipsoid->getA() * $ellipsoid->getA() - $ellipsoid->getB() * $ellipsoid->getB()) / ($ellipsoid->getB() * $ellipsoid->getB());
     // 2nd eccentricity squared
     $p = sqrt($this->x * $this->x + $this->y * $this->y);
     // distance from minor axis
     $R = sqrt($p * $p + $this->z + $this->z);
     // parametric latitude (Bowring eqn 17, replacing tanβ = z·a / p·b)
     $tan = $ellipsoid->getB() * $this->z / ($ellipsoid->getA() * $p) * (1 + $G12 * $ellipsoid->getB() / $R);
     $sin = $tan / sqrt(1 + $tan * $tan);
     $cos = $sin / $tan;
     // geodetic latitude (Bowring eqn 18)
     $G2 = atan2($this->z + $G12 * $ellipsoid->getB() * $sin * $sin * $sin, $p - $e2 * $ellipsoid->getA() * $cos * $cos * $cos);
     // longitude
     $G3 = atan2($this->y, $this->x);
     return new LatLng(Misc::toDegrees($G2), Misc::toDegrees($G3), $datum);
 }