cdm/src/main/java/ucar/unidata/geoloc/projection/sat/GEOSTransform.java
public double[] satToEarth(double x, double y) {

    if (scan_geom.equals(GOES)) { // convert from GOES to GEOS for transfrom below
      double[] lambda_theta_geos = GOES_to_GEOS(x, y);
      x = lambda_theta_geos[0];
      y = lambda_theta_geos[1];
    }

    double c1 = (h * Math.cos(x) * Math.cos(y)) * (h * Math.cos(x) * Math.cos(y));
    double c2 = (Math.cos(y) * Math.cos(y) + fp * Math.sin(y) * Math.sin(y)) * d;

    if (c1 < c2) {
      return new double[]{Double.NaN, Double.NaN};
    }

    double s_d = Math.sqrt(c1 - c2);

    double s_n = (h * Math.cos(x) * Math.cos(y) - s_d) / (Math.cos(y) * Math.cos(y) + fp * Math.sin(y) * Math.sin(y));

    double s_1 = h - s_n * Math.cos(x) * Math.cos(y);
    double s_2 = s_n * Math.sin(x) * Math.cos(y);
    double s_3 = -s_n * Math.sin(y);

    double s_xy = Math.sqrt(s_1 * s_1 + s_2 * s_2);
    double geographic_lon = Math.atan(s_2 / s_1) + sub_lon;

    double geographic_lat = Math.atan(-fp * (s_3 / s_xy));

    double lonDegrees = RAD_TO_DEG * geographic_lon;
    double latDegrees = RAD_TO_DEG * geographic_lat;

    // force output longitude to -180 to 180 range
    if (lonDegrees < -180.0) lonDegrees += 360.0;
    if (lonDegrees > 180.0) lonDegrees -= 360.0;

    return new double[]{lonDegrees, latDegrees};
  }
public double[] satToEarth(double x, double y) {

    if (scan_geom.equals(GOES)) { // convert from GOES to GEOS for transfrom below
      double[] lambda_theta_geos = GOES_to_GEOS(x, y);
      x = lambda_theta_geos[0];
      y = lambda_theta_geos[1];
    }

    double c1 = (h * Math.cos(x) * Math.cos(y)) * (h * Math.cos(x) * Math.cos(y));
    double c2 = (Math.cos(y) * Math.cos(y) + fp * Math.sin(y) * Math.sin(y)) * d;

    if (c1 < c2) {
      return new double[]{Double.NaN, Double.NaN};
    }

    double s_d = Math.sqrt(c1 - c2);

    double s_n = (h * Math.cos(x) * Math.cos(y) - s_d) / (Math.cos(y) * Math.cos(y) + fp * Math.sin(y) * Math.sin(y));

    double s_1 = h - s_n * Math.cos(x) * Math.cos(y);
    double s_2 = s_n * Math.sin(x) * Math.cos(y);
    double s_3 = -s_n * Math.sin(y);

    double s_xy = Math.sqrt(s_1 * s_1 + s_2 * s_2);
    double geographic_lon = Math.atan(s_2 / s_1) + sub_lon;

    double geographic_lat = Math.atan(-fp * (s_3 / s_xy));

    double lonDegrees = RAD_TO_DEG * geographic_lon;
    double latDegrees = RAD_TO_DEG * geographic_lat;

    // force output longitude to -180 to 180 range
    if (lonDegrees < -180.0) lonDegrees += 360.0;
    if (lonDegrees > 180.0) lonDegrees -= 360.0;

    return new double[]{lonDegrees, latDegrees};
  }
Transform satellite view angle coordinates, known as the "intermeidate" coordinates in the
CGMS Normalized Geostationary Projection, to geographic Earth coordinates.

@param x is lamda (East-West) angle, units: radians
@param y is theta (Norht-South) angle, units: radians
@return (Longitude, Latitude), units degrees