121 QString msg =
"Projection failed. No target radii are available " 122 "through keywords [EquatorialRadius and PolarRadius] " 129 QString msg =
"Projection failed. Invalid value for keyword " 130 "[EquatorialRadius]. It must be greater than zero";
134 QString msg =
"Projection failed. Invalid value for keyword " 135 "[PolarRadius]. It must be greater than zero";
140 if ((QString)
m_mappingGrp[
"LatitudeType"] ==
"Planetographic") {
143 else if ((QString)
m_mappingGrp[
"LatitudeType"] ==
"Planetocentric") {
147 QString msg =
"Projection failed. Invalid value for keyword " 148 "[LatitudeType] must be " 149 "[Planetographic or Planetocentric]";
154 if ((QString)
m_mappingGrp[
"LongitudeDirection"] ==
"PositiveWest") {
157 else if ((QString)
m_mappingGrp[
"LongitudeDirection"] ==
"PositiveEast") {
161 QString msg =
"Projection failed. Invalid value for keyword " 162 "[LongitudeDirection] must be " 163 "[PositiveWest or PositiveEast]";
168 if ((QString)
m_mappingGrp[
"LongitudeDomain"] ==
"360") {
171 else if ((QString)
m_mappingGrp[
"LongitudeDomain"] ==
"180") {
175 QString msg =
"Projection failed. Invalid value for keyword " 176 "[LongitudeDomain] must be [180 or 360]";
192 QString msg =
"Projection failed. " 194 +
"] is outside the range of [-90:90]";
199 QString msg =
"Projection failed. " 201 +
"] is outside the range of [-90:90]";
206 QString msg =
"Projection failed. " 207 "[MinimumLatitude,MaximumLatitude] of [" 210 +
"properly ordered";
215 QString msg =
"Projection failed. " 216 "[MinimumLongitude,MaximumLongitude] of [" 219 +
"properly ordered";
235 QString msg =
"Projection failed. Invalid keyword value(s). " 237 +
" must be greater than or equal to [PolarRadius] = " 256 QString msg =
"Projection failed. Invalid label group [Mapping]";
276 if (!Projection::operator==(proj))
return false;
342 if (latitude ==
Null) {
344 "Unable to calculate local radius. The given latitude value [" 345 +
toString(latitude) +
"] is invalid.",
351 if (a - c < DBL_EPSILON) {
355 double lat = latitude *
PI / 180.0;
356 return a * c / sqrt(pow(c * cos(lat), 2) + pow(a * sin(lat), 2));
450 double eRadius,
double pRadius) {
451 if (lat ==
Null || abs(lat) > 90.0) {
453 "Unable to convert to Planetocentric. The given latitude value [" 458 if (abs(mylat) < 90.0) {
460 mylat = atan(tan(mylat) * (pRadius / eRadius) *
461 (pRadius / eRadius));
496 double eRadius,
double pRadius) {
498 if (qFuzzyCompare(fabs(lat), 90.0)) {
501 if (lat ==
Null || fabs(lat) > 90.0) {
503 "Unable to convert to Planetographic. The given latitude value [" 508 if (fabs(mylat) < 90.0) {
510 mylat = atan(tan(mylat) * (eRadius / pRadius) *
511 (eRadius / pRadius));
525 return "Planetocentric";
566 "Unable to convert to PositiveEast. The given longitude value [" 577 else if (domain == 180) {
581 QString msg =
"Unable to convert longitude. Domain [" +
toString(domain)
582 +
"] is not 180 or 360.";
605 "Unable to convert to PositiveWest. The given longitude value [" 616 else if (domain == 180) {
620 QString msg =
"Unable to convert longitude. Domain [" +
toString(domain)
621 +
"] is not 180 or 360.";
637 return "PositiveWest";
675 "Unable to convert to 180 degree domain. The given longitude value [" 693 "Unable to convert to 360 degree domain. The given longitude value [" 699 if ( (lon < 0.0 || lon > 360.0) &&
700 !qFuzzyCompare(lon, 0.0) && !qFuzzyCompare(lon, 360.0)) {
1009 double &minY,
double &maxY) {
1079 if (latitude ==
Null || longitude ==
Null) {
1120 if (adjustedMinLon > adjustedMaxLon) {
1121 if (adjustedLon > adjustedMinLon) {
1124 adjustedMinLon -= 360;
1128 if (qFuzzyCompare(maxLon - minLon, 360.0)) {
1131 else if (adjustedMinLon <= adjustedLon && adjustedLon <= adjustedMaxLon) {
1211 double &minY,
double &maxY) {
1223 double minFoundX1, minFoundX2;
1224 double minFoundY1, minFoundY2;
1240 double minFoundX3, minFoundX4;
1241 double minFoundY3, minFoundY4;
1257 double minFoundX5 = min(minFoundX1, minFoundX2);
1258 double minFoundX6 = min(minFoundX3, minFoundX4);
1261 double minFoundY5 = min(minFoundY1, minFoundY2);
1262 double minFoundY6 = min(minFoundY3, minFoundY4);
1266 double maxFoundX1, maxFoundX2;
1267 double maxFoundY1, maxFoundY2;
1283 double maxFoundX3, maxFoundX4;
1284 double maxFoundY3, maxFoundY4;
1300 double maxFoundX5 = max(maxFoundX1, maxFoundX2);
1301 double maxFoundX6 = max(maxFoundX3, maxFoundX4);
1304 double maxFoundY5 = max(maxFoundY1, maxFoundY2);
1305 double maxFoundY6 = max(maxFoundY3, maxFoundY4);
1310 for (
unsigned int specialLatCase = 0;
1311 specialLatCase < specialLatCases.size();
1312 specialLatCase ++) {
1313 double minX, maxX, minY, maxY;
1317 minX, specialLatCases[specialLatCase],
true,
false,
true);
1320 minY, specialLatCases[specialLatCase],
false,
false,
true);
1323 maxX, specialLatCases[specialLatCase],
true,
false,
false);
1326 maxY, specialLatCases[specialLatCase],
false,
false,
false);
1335 for (
unsigned int specialLonCase = 0;
1336 specialLonCase < specialLonCases.size();
1337 specialLonCase ++) {
1338 double minX, maxX, minY, maxY;
1342 minX, specialLonCases[specialLonCase],
true,
true,
true);
1345 minY, specialLonCases[specialLonCase],
false,
true,
true);
1348 maxX, specialLonCases[specialLonCase],
true,
true,
false);
1351 maxY, specialLonCases[specialLonCase],
false,
true,
false);
1413 double &extremeVal,
const double constBorder,
1414 bool searchX,
bool searchLongitude,
bool findMin) {
1415 if (minBorder ==
Null || maxBorder ==
Null || constBorder ==
Null) {
1419 const int NUM_ATTEMPTS = (
unsigned int)DBL_DIG;
1422 double minBorderX, minBorderY, maxBorderX, maxBorderY;
1426 findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
1427 maxBorderY, constBorder, searchX, searchLongitude, findMin);
1428 if (minBorderX ==
Null && maxBorderX ==
Null 1429 && minBorderY ==
Null && maxBorderY ==
Null ) {
1430 attempts = NUM_ATTEMPTS;
1435 while ((fabs(minBorderX - maxBorderX) > TOLERANCE
1436 || fabs(minBorderY - maxBorderY) > TOLERANCE)
1437 && (attempts < NUM_ATTEMPTS));
1442 if (attempts >= NUM_ATTEMPTS) {
1447 if (searchLongitude) {
1457 if (searchX) extremeVal = min(minBorderX, maxBorderX);
1458 else extremeVal = min(minBorderY, maxBorderY);
1461 if (searchX) extremeVal = max(minBorderX, maxBorderX);
1462 else extremeVal = max(minBorderY, maxBorderY);
1527 double &minBorderX,
double &minBorderY,
1528 double &maxBorderX,
double &maxBorderY,
1529 const double constBorder,
bool searchX,
1530 bool searchLongitude,
bool findMin) {
1531 if (minBorder ==
Null || maxBorder ==
Null || constBorder ==
Null) {
1533 minBorderY = minBorderX;
1534 minBorderY = minBorderX;
1537 if (!searchLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1542 maxBorderY = minBorderY;
1546 const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1547 const double LOOP_END = maxBorder + (STEP_SIZE / 2.0);
1550 double currBorderVal = minBorder;
1558 while (!
m_good && currBorderVal <= LOOP_END) {
1559 currBorderVal+=STEP_SIZE;
1560 if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1561 currBorderVal = 90.0;
1575 double border1 = currBorderVal;
1576 double border2 = currBorderVal;
1577 double border3 = currBorderVal;
1583 double value2 = value1;
1587 double extremeVal2 = value2;
1591 double extremeBorder1 = minBorder;
1592 double extremeBorder3 = minBorder;
1594 while (currBorderVal <= LOOP_END) {
1601 if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1602 currBorderVal = 90.0;
1606 currBorderVal += STEP_SIZE;
1615 border1 = currBorderVal;
1619 if ((findMin && value2 < extremeVal2)
1620 || (!findMin && value2 > extremeVal2)) {
1625 extremeVal2 = value2;
1627 extremeBorder3 = border3;
1628 extremeBorder1 = border1;
1635 minBorder = extremeBorder3;
1640 if (extremeBorder1 <= maxBorder ) {
1641 maxBorder = extremeBorder1;
1689 const double constBorder,
1690 bool variableIsLat) {
1691 if (variableBorder ==
Null || constBorder ==
Null) {
1695 if (variableIsLat) {
1696 lat = variableBorder;
1701 lon = variableBorder;
1717 keyNames <<
"TargetName" <<
"ProjectionName" <<
"EquatorialRadius" <<
"PolarRadius" 1718 <<
"LatitudeType" <<
"LongitudeDirection" <<
"LongitudeDomain" 1719 <<
"PixelResolution" <<
"Scale" <<
"UpperLeftCornerX" <<
"UpperLeftCornerY" 1720 <<
"MinimumLatitude" <<
"MaximumLatitude" <<
"MinimumLongitude" <<
"MaximumLongitude" 1723 foreach (QString keyName, keyNames) {
1787 QString msg =
"Snyder's q variable should only be computed for " 1788 "ellipsoidal projections.";
1793 * (sinPhi / (1 - eSinPhi * eSinPhi)
1794 - 1 / (2 *
m_eccentricity) * log( (1 - eSinPhi) / (1 + eSinPhi) ));
1819 double localPhi =
HALFPI - 2.0 * atan(t);
1821 double difference = DBL_MAX;
1828 const int MAX_ITERATIONS = 45;
1830 while ((iteration < MAX_ITERATIONS) && (difference > 0.0000000001)) {
1831 double eccTimesSinphi =
Eccentricity() * sin(localPhi);
1833 2.0 * atan(t * pow((1.0 - eccTimesSinphi) /
1834 (1.0 + eccTimesSinphi), halfEcc));
1835 difference = fabs(newPhi - localPhi);
1840 if (iteration >= MAX_ITERATIONS) {
1841 QString msg =
"Failed to converge in TProjection::phi2Compute()";
1864 double denominator = sqrt(1.0 - eccTimesSinphi * eccTimesSinphi);
1865 return cosphi / denominator;
1886 if ((
HALFPI) - fabs(phi) < DBL_EPSILON)
return 0.0;
1889 double denominator = pow((1.0 - eccTimesSinphi) /
1890 (1.0 + eccTimesSinphi),
1892 return tan(0.5 * (
HALFPI - phi)) / denominator;
1910 return sqrt(pow(onePlusEcc, onePlusEcc) *
1911 pow(oneMinusEcc, oneMinusEcc));
double EquatorialRadius() const
This returns the equatorial radius of the target.
virtual ~TProjection()
Destroys the TProjection object.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
bool inLatitudeRange(double latitude)
Determine whether the given latitude is within the range of the MinimumLatitude and MaximumLatitude r...
double MaximumLongitude() const
This returns the maximum longitude of the area of interest.
const double Null
Value for an Isis Null pixel.
std::vector< double > m_specialLonCases
Constant Longitudes that intersect a discontinuity.
double mCompute(const double sinphi, const double cosphi) const
A convience method to compute Snyder's m equation (14-15) for a given latitude, . ...
WorldMapper * m_mapper
This points to a mapper passed into the SetWorldMapper method.
double tCompute(const double phi, const double sinphi) const
A convience method to compute Snyder's t equation (15-9) for a given latitude, .
bool xyRangeOblique(double &minX, double &maxX, double &minY, double &maxY)
This method is used to find the XY range for oblique aspect projections (non-polar projections) by "w...
bool SetUniversalGround(const double lat, const double lon)
This method is used to set the latitude/longitude which must be Planetocentric (latitude) and Positiv...
const double PI
The mathematical constant PI.
double Scale() const
This method returns the scale for mapping world coordinates into projection coordinates.
bool IsPositiveEast() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
Longitude values increase in the westerly direction.
Base class for Map TProjections.
QString LatitudeTypeString() const
This method returns the latitude type as a string.
const double HALFPI
The mathematical constant PI/2.
virtual bool operator==(const Projection &proj)
This method determines whether two map projection objects are equal by comparing the equatorial radiu...
virtual bool IsEquatorialCylindrical()
This method returns true if the projection is equatorial cylindrical.
double PixelResolution() const
Returns the pixel resolution value from the PVL mapping group in meters/pixel.
Namespace for the standard library.
std::vector< double > m_specialLatCases
Constant Latitudes that intersect a discontinuity.
Latitudes are measured as the angle from the equatorial plane to the normal to the surface of the pla...
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround, or SetWorld was with successful or not.
double XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
double m_polarRadius
Polar radius of the target.
bool inLongitudeRange(double longitude)
Determine whether the given longitude is within the range of the MinimumLongitude and MaximumLongitud...
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
Latitudes are measured as the angle from the equatorial plane to the plane through the center of the ...
double m_latitude
This contains the currently set latitude value.
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
void setSearchGround(const double variableBorder, const double constBorder, bool variableIsLat)
This function sets the ground for the given border values.
double degrees() const
Get the angle in units of Degrees.
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
double MinimumLongitude() const
This returns the minimum longitude of the area of interest.
double m_maximumY
See minimumX description.
double m_longitude
This contains the currently set longitude value.
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
This class is designed to encapsulate the concept of a Longitude.
double m_minimumLatitude
Contains the minimum latitude for the entire ground range.
static double ToPositiveWest(const double lon, const int domain)
This method converts a longitude into the positive west direction.
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
Base class for Map Projections.
double m_minimumY
See minimumX description.
double Eccentricity() const
This returns the eccentricity of the target,.
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
double m_equatorialRadius
Polar radius of the target.
bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
int m_longitudeDomain
This integer is either 180 or 360 and is read from the labels.
static double To180Domain(const double lon)
This method converts a longitude into the -180 to 180 domain.
bool Has180Domain() const
This indicates if the longitude domain is -180 to 180 (as opposed to 0 to 360).
void findExtreme(double &minBorder, double &maxBorder, double &minBorderX, double &minBorderY, double &maxBorderX, double &maxBorderY, const double constBorder, bool searchX, bool searchLongitude, bool findMin)
Searches for extreme (min/max/discontinuity) coordinate values across latitudes/longitudes.
bool IsPlanetographic() const
This indicates if the latitude type is planetographic (as opposed to planetocentric).
double Longitude() const
This returns a longitude with correct longitude direction and domain as specified in the label object...
Contains multiple PvlContainers.
void setProjectionType(const ProjectionType ptype)
Sets the projection subclass type.
bool m_groundRangeGood
Indicates if the ground range (min/max lat/lons) were read from the labels.
#define _FILEINFO_
Macro for the filename and line number.
double LocalRadius() const
This method returns the local radius in meters at the current latitude position.
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
virtual bool SetGround(const double lat, const double lon)
This method is used to set the latitude/longitude (assumed to be of the correct LatitudeType, LongitudeDirection, and LongitudeDomain.
A type of error that cannot be classified as any of the other error types.
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
QString LongitudeDirectionString() const
This method returns the longitude direction as a string.
bool Has360Domain() const
This indicates if the longitude domain is 0 to 360 (as opposed to -180 to 180).
Container for cube-like labels.
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
double phi2Compute(const double t) const
A convience method to compute latitude angle phi2 given small t, from Syder's recursive equation (7-9...
double MinimumLatitude() const
This returns the minimum latitude of the area of interest.
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double UniversalLatitude()
This returns a universal latitude (planetocentric).
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double e4Compute() const
A convience method to compute.
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
bool IsPositiveWest() const
This indicates if the longitude direction type is positive east (as opposed to postive west)...
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
double PolarRadius() const
This returns the polar radius of the target.
LatitudeType m_latitudeType
An enumerated type indicating the LatitudeType read from the labels.
double Latitude() const
This returns a latitude with correct latitude type as specified in the label object.
double m_eccentricity
The eccentricity of the target body.
Namespace for ISIS/Bullet specific routines.
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
QString LongitudeDomainString() const
This method returns the longitude domain as a string.
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
void SetXY(double x, double y)
This protected method is a helper for derived classes.
virtual double Resolution() const
This virtual method will the resolution of the world system relative to one unit in the projection sy...
void XYRangeCheck(const double latitude, const double longitude)
This convience function is established to assist in the development of the XYRange virtual method...
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
bool SetUnboundUniversalGround(const double coord1, const double coord2)
This method is used to set the latitude/longitude.
double m_maximumX
See minimumX description.
void doSearch(double minBorder, double maxBorder, double &extremeVal, const double constBorder, bool searchX, bool searchLongitude, bool findMin)
This method searches for extreme (min/max/discontinuity) coordinate values along the constBorder line...
double qCompute(const double sinPhi) const
A convience method to compute Snyder's q equation (3-12) for a given latitude, .
static double ToPositiveEast(const double lon, const int domain)
This method converts a longitude into the positive east direction.
Longitude values increase in the easterly direction.
PvlGroup m_mappingGrp
Mapping group that created this projection.
virtual double TrueScaleLatitude() const
This method returns the latitude of true scale.
These projections are used to map triaxial and irregular-shaped bodies.
virtual bool XYRange(double &minX, double &maxX, double &minY, double &maxY)
This method is used to determine the x/y range which completely covers the area of interest specified...
double MaximumLatitude() const
This returns the maximum latitude of the area of interest.