/** * 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; }
/** * 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; }