/**
  * This method is used to set the projection x/y. The Set forces an attempted
  * calculation of the corresponding latitude/longitude position. This may or
  * may not be successful and a status is returned as such.
  *
  * @param x X coordinate of the projection in units that are the same as the
  *          radii in the label
  *
  * @param y Y coordinate of the projection in units that are the same as the
  *          radii in the label
  *
  * @return bool
  */
  bool TransverseMercator::SetCoordinate(const double x, const double y) {
    // Save the coordinate
    SetXY(x,y);

    // Declare & Initialize variables
    double f,g,h,temp,con,phi,dphi,sinphi,cosphi,tanphi;
    double c,cs,t,ts,n,rp,d,ds;
    const double epsilon = 1.0e-10;

    // Sphere Conversion
    if (p_sph) {
      f = exp(GetX() / (p_equatorialRadius * p_scalefactor));
      g = 0.5 * (f - 1.0 / f);
      temp = p_centerLatitude + GetY() / (p_equatorialRadius * p_scalefactor);
      h = cos(temp);
      con = sqrt((1.0 - h * h) / (1.0 + g * g));
      if (con > 1.0) con = 1.0;
      if (con < -1.0) con = -1.0;
      p_latitude = asin(con);
      if (temp < 0.0 ) p_latitude = -p_latitude;
      p_longitude = p_centerLongitude;
      if (g != 0.0 || h != 0.0) {
        p_longitude = atan2(g,h) + p_centerLongitude;
      }
    }

    // Ellipsoid Conversion
    else if (!p_sph) {
      con = (p_ml0 + GetY() / p_scalefactor) / p_equatorialRadius;
      phi = con;
      for (int i = 1; i < 7; i++) {
        dphi = ((con + p_e1 * sin(2.0 * phi) - p_e2 * sin(4.0 * phi)
                 + p_e3 * sin(6.0 * phi)) / p_e0) - phi;
        phi += dphi;
        if (fabs(dphi) <= epsilon) break;
      }

      // Didn't converge
      if (fabs(dphi) > epsilon) {
        p_good = false;
        return p_good;
      }
      if (fabs(phi) >= Isis::HALFPI) {
        if (GetY() >= 0.0) p_latitude = fabs(Isis::HALFPI);
        if (GetY() < 0.0) p_latitude = - fabs(Isis::HALFPI);
        p_longitude = p_centerLongitude;
      }
      else {
        sinphi = sin(phi);
        cosphi = cos(phi);
        tanphi = tan(phi);
        c = p_esp * cosphi * cosphi;
        cs = c * c;
        t = tanphi * tanphi;
        ts = t * t;
        con = 1.0 - p_eccsq * sinphi * sinphi;
        n = p_equatorialRadius / sqrt(con);
        rp = n * (1.0 - p_eccsq) / con;
        d = GetX() / (n * p_scalefactor);
        ds = d * d;
        p_latitude = phi - (n * tanphi * ds / rp) * (0.5 - ds /
                      24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 *
                      p_esp - ds / 30.0 * (61.0 + 90.0 * t + 298.0 * c +
                      45.0 * ts - 252.0 * p_esp - 3.0 * cs)));


        // Latitude cannot be greater than + or - halfpi radians (or 90 degrees)
        if (fabs(p_latitude) > Isis::HALFPI) {
          p_good = false;
          return p_good;
        }
        p_longitude = p_centerLongitude + (d * (1.0 - ds / 6.0 *
                      (1.0 + 2.0 * t + c - ds / 20.0 * (5.0 - 2.0 * c +
                      28.0 * t - 3.0 * cs + 8.0 * p_esp + 24.0 * ts))) / cosphi);
      }
    }

    // Convert to Degrees
    p_latitude *= 180.0 / Isis::PI;
    p_longitude *= 180.0 / Isis::PI;

    // Cleanup the longitude
    if (p_longitudeDirection == PositiveWest) p_longitude *= -1.0;
  // These need to be done for circular type projections
    p_longitude = To360Domain (p_longitude);
    if (p_longitudeDomain == 180) p_longitude = To180Domain(p_longitude);

    // Cleanup the latitude
    if (IsPlanetocentric()) p_latitude = ToPlanetocentric(p_latitude);

    p_good = true;
    return p_good;
  }
Exemple #2
0
  /**
   * This method is used to set the projection x/y. The Set forces an attempted
   * calculation of the corresponding latitude/longitude position. This may or
   * may not be successful and a status is returned as such.
   *
   * @param x X coordinate of the projection in units that are the same as the
   *          radii in the label
   *
   * @param y Y coordinate of the projection in units that are the same as the
   *          radii in the label
   *
   * @return bool
   */
  bool PointPerspective::SetCoordinate(const double x, const double y) {
    // Save the coordinate
    SetXY(x, y);

    // Declare instance variables and calculate rho
    double rho, rp, con, com, z, sinz, cosz;
    const double epsilon = 1.0e-10;
    rho = sqrt(GetX() * GetX() + GetY() * GetY());
    rp = rho / m_equatorialRadius;
    con = m_P - 1.0;
    com = m_P + 1.0;

    // Error calculating rho - should be less than equatorial radius
    if (rp > (sqrt(con / com))) {
      m_good = false;
      return m_good;
    }

    // Calculate the latitude and longitude
    m_longitude = m_centerLongitude;
    if (fabs(rho) <= epsilon) {
      m_latitude = m_centerLatitude;
    }
    else {
      if (rp <= epsilon) {
        sinz = 0.0;
      }
      else {
        sinz = (m_P - sqrt(1.0 - rp * rp * com / con)) / (con / rp + rp / con);
      }
      z = asin(sinz);
      sinz = sin(z);
      cosz = cos(z);
      con = cosz * m_sinph0 + GetY() * sinz * m_cosph0 / rho;
      if (con > 1.0) con = 1.0;
      if (con < -1.0) con = -1.0;
      m_latitude = asin(con);

      con = fabs(m_centerLatitude) - HALFPI;
      if (fabs(con) <= epsilon) {
        if (m_centerLatitude >= 0.0) {
          m_longitude += atan2(GetX(), -GetY());
        }
        else {
          m_longitude += atan2(-GetX(), GetY());
        }
      }
      else {
        con = cosz - m_sinph0 * sin(m_latitude);
        if ((fabs(con) >= epsilon) || (fabs(GetX()) >= epsilon)) {
          m_longitude += atan2(GetX() * sinz * m_cosph0, con * rho);
        }
      }
    }

    // Convert to degrees
    m_latitude *= 180.0 / PI;
    m_longitude *= 180.0 / PI;

    // Cleanup the longitude
    if (m_longitudeDirection == PositiveWest) m_longitude *= -1.0;
    // These need to be done for circular type projections
    m_longitude = To360Domain(m_longitude);
    if (m_longitudeDomain == 180) m_longitude = To180Domain(m_longitude);

    // Cleanup the latitude
    if (IsPlanetocentric()) m_latitude = ToPlanetocentric(m_latitude);

    m_good = true;
    return m_good;
  }