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)) {
975 double &minY,
double &maxY) {
1045 if (latitude ==
Null || longitude ==
Null) {
1086 if (adjustedMinLon > adjustedMaxLon) {
1087 if (adjustedLon > adjustedMinLon) {
1090 adjustedMinLon -= 360;
1094 if (qFuzzyCompare(maxLon - minLon, 360.0)) {
1097 else if (adjustedMinLon <= adjustedLon && adjustedLon <= adjustedMaxLon) {
1177 double &minY,
double &maxY) {
1189 double minFoundX1, minFoundX2;
1190 double minFoundY1, minFoundY2;
1206 double minFoundX3, minFoundX4;
1207 double minFoundY3, minFoundY4;
1223 double minFoundX5 = min(minFoundX1, minFoundX2);
1224 double minFoundX6 = min(minFoundX3, minFoundX4);
1227 double minFoundY5 = min(minFoundY1, minFoundY2);
1228 double minFoundY6 = min(minFoundY3, minFoundY4);
1232 double maxFoundX1, maxFoundX2;
1233 double maxFoundY1, maxFoundY2;
1249 double maxFoundX3, maxFoundX4;
1250 double maxFoundY3, maxFoundY4;
1266 double maxFoundX5 = max(maxFoundX1, maxFoundX2);
1267 double maxFoundX6 = max(maxFoundX3, maxFoundX4);
1270 double maxFoundY5 = max(maxFoundY1, maxFoundY2);
1271 double maxFoundY6 = max(maxFoundY3, maxFoundY4);
1276 for (
unsigned int specialLatCase = 0;
1277 specialLatCase < specialLatCases.size();
1278 specialLatCase ++) {
1279 double minX, maxX, minY, maxY;
1283 minX, specialLatCases[specialLatCase],
true,
false,
true);
1286 minY, specialLatCases[specialLatCase],
false,
false,
true);
1289 maxX, specialLatCases[specialLatCase],
true,
false,
false);
1292 maxY, specialLatCases[specialLatCase],
false,
false,
false);
1301 for (
unsigned int specialLonCase = 0;
1302 specialLonCase < specialLonCases.size();
1303 specialLonCase ++) {
1304 double minX, maxX, minY, maxY;
1308 minX, specialLonCases[specialLonCase],
true,
true,
true);
1311 minY, specialLonCases[specialLonCase],
false,
true,
true);
1314 maxX, specialLonCases[specialLonCase],
true,
true,
false);
1317 maxY, specialLonCases[specialLonCase],
false,
true,
false);
1379 double &extremeVal,
const double constBorder,
1380 bool searchX,
bool searchLongitude,
bool findMin) {
1381 if (minBorder ==
Null || maxBorder ==
Null || constBorder ==
Null) {
1385 const int NUM_ATTEMPTS = (
unsigned int)DBL_DIG;
1388 double minBorderX, minBorderY, maxBorderX, maxBorderY;
1392 findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
1393 maxBorderY, constBorder, searchX, searchLongitude, findMin);
1394 if (minBorderX ==
Null && maxBorderX ==
Null
1395 && minBorderY ==
Null && maxBorderY ==
Null ) {
1396 attempts = NUM_ATTEMPTS;
1401 while ((fabs(minBorderX - maxBorderX) > TOLERANCE
1402 || fabs(minBorderY - maxBorderY) > TOLERANCE)
1403 && (attempts < NUM_ATTEMPTS));
1408 if (attempts >= NUM_ATTEMPTS) {
1413 if (searchLongitude) {
1423 if (searchX) extremeVal = min(minBorderX, maxBorderX);
1424 else extremeVal = min(minBorderY, maxBorderY);
1427 if (searchX) extremeVal = max(minBorderX, maxBorderX);
1428 else extremeVal = max(minBorderY, maxBorderY);
1493 double &minBorderX,
double &minBorderY,
1494 double &maxBorderX,
double &maxBorderY,
1495 const double constBorder,
bool searchX,
1496 bool searchLongitude,
bool findMin) {
1497 if (minBorder ==
Null || maxBorder ==
Null || constBorder ==
Null) {
1499 minBorderY = minBorderX;
1500 minBorderY = minBorderX;
1503 if (!searchLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1508 maxBorderY = minBorderY;
1512 const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1513 const double LOOP_END = maxBorder + (STEP_SIZE / 2.0);
1516 double currBorderVal = minBorder;
1524 while (!
m_good && currBorderVal <= LOOP_END) {
1525 currBorderVal+=STEP_SIZE;
1526 if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1527 currBorderVal = 90.0;
1533 minBorderY = minBorderX;
1534 minBorderX = minBorderX;
1535 minBorderY = minBorderX;
1543 double border1 = currBorderVal;
1544 double border2 = currBorderVal;
1545 double border3 = currBorderVal;
1551 double value2 = value1;
1555 double extremeVal2 = value2;
1559 double extremeBorder1 = minBorder;
1560 double extremeBorder3 = minBorder;
1562 while (currBorderVal <= LOOP_END) {
1569 if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1570 currBorderVal = 90.0;
1574 currBorderVal += STEP_SIZE;
1583 border1 = currBorderVal;
1587 if ((findMin && value2 < extremeVal2)
1588 || (!findMin && value2 > extremeVal2)) {
1593 extremeVal2 = value2;
1595 extremeBorder3 = border3;
1596 extremeBorder1 = border1;
1603 minBorder = extremeBorder3;
1608 if (extremeBorder1 <= maxBorder ) {
1609 maxBorder = extremeBorder1;
1657 const double constBorder,
1658 bool variableIsLat) {
1659 if (variableBorder ==
Null || constBorder ==
Null) {
1663 if (variableIsLat) {
1664 lat = variableBorder;
1669 lon = variableBorder;
1685 keyNames <<
"TargetName" <<
"ProjectionName" <<
"EquatorialRadius" <<
"PolarRadius"
1686 <<
"LatitudeType" <<
"LongitudeDirection" <<
"LongitudeDomain"
1687 <<
"PixelResolution" <<
"Scale" <<
"UpperLeftCornerX" <<
"UpperLeftCornerY"
1688 <<
"MinimumLatitude" <<
"MaximumLatitude" <<
"MinimumLongitude" <<
"MaximumLongitude"
1691 foreach (QString keyName, keyNames) {
1755 QString msg =
"Snyder's q variable should only be computed for "
1756 "ellipsoidal projections.";
1761 * (sinPhi / (1 - eSinPhi * eSinPhi)
1762 - 1 / (2 * m_eccentricity) * log( (1 - eSinPhi) / (1 + eSinPhi) ));
1787 double localPhi =
HALFPI - 2.0 * atan(t);
1789 double difference = DBL_MAX;
1796 const int MAX_ITERATIONS = 45;
1798 while ((iteration < MAX_ITERATIONS) && (difference > 0.0000000001)) {
1799 double eccTimesSinphi =
Eccentricity() * sin(localPhi);
1801 2.0 * atan(t * pow((1.0 - eccTimesSinphi) /
1802 (1.0 + eccTimesSinphi), halfEcc));
1803 difference = fabs(newPhi - localPhi);
1808 if (iteration >= MAX_ITERATIONS) {
1809 QString msg =
"Failed to converge in TProjection::phi2Compute()";
1832 double denominator = sqrt(1.0 - eccTimesSinphi * eccTimesSinphi);
1833 return cosphi / denominator;
1854 if ((
HALFPI) - fabs(phi) < DBL_EPSILON)
return 0.0;
1857 double denominator = pow((1.0 - eccTimesSinphi) /
1858 (1.0 + eccTimesSinphi),
1860 return tan(0.5 * (
HALFPI - phi)) / denominator;
1878 return sqrt(pow(onePlusEcc, onePlusEcc) *
1879 pow(oneMinusEcc, oneMinusEcc));
virtual double Resolution() const
This virtual method will the resolution of the world system relative to one unit in the projection sy...
virtual ~TProjection()
Destroys the TProjection object.
QString LongitudeDirectionString() const
This method returns the longitude direction as a string.
bool inLatitudeRange(double latitude)
Determine whether the given latitude is within the range of the MinimumLatitude and MaximumLatitude r...
const double Null
Value for an Isis Null pixel.
std::vector< double > m_specialLonCases
Constant Longitudes that intersect a discontinuity.
WorldMapper * m_mapper
This points to a mapper passed into the SetWorldMapper method.
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...
double degrees() const
Get the angle in units of Degrees.
Longitude values increase in the westerly direction.
bool IsPositiveEast() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
Base class for Map TProjections.
bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east)...
bool Has360Domain() const
This indicates if the longitude domain is 0 to 360 (as opposed to -180 to 180).
double ToPlanetographic(const double lat) const
This method converts a planetocentric latitude to a planetographic latitude.
const double PI(3.14159265358979323846)
The mathematical constant PI.
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 XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
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...
double Eccentricity() const
This returns the eccentricity of the target,.
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
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 IsPositiveWest() const
This indicates if the longitude direction type is positive east (as opposed to postive west)...
const double HALFPI(1.57079632679489661923)
The mathematical constant PI/2.
bool inLongitudeRange(double longitude)
Determine whether the given longitude is within the range of the MinimumLongitude and MaximumLongitud...
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
double e4Compute() const
A convience method to compute.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double LocalRadius() const
This method returns the local radius in meters at the current latitude position.
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.
void setSearchGround(const double variableBorder, const double constBorder, bool variableIsLat)
This function sets the ground for the given border values.
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
double MinimumLatitude() const
This returns the minimum latitude of the area of interest.
double m_maximumY
See minimumX description.
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
double m_longitude
This contains the currently set longitude value.
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
double EquatorialRadius() const
This returns the equatorial radius of the target.
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 phi2Compute(const double t) const
A convience method to compute latitude angle phi2 given small t, from Syder's recursive equation (7-9...
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
Base class for Map Projections.
double m_minimumY
See minimumX description.
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.
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.
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.
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 MinimumLongitude() const
This returns the minimum longitude of the area of interest.
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 MaximumLatitude() const
This returns the maximum latitude of the area of interest.
Container for cube-like labels.
bool Has180Domain() const
This indicates if the longitude domain is -180 to 180 (as opposed to 0 to 360).
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double UniversalLatitude()
This returns a universal latitude (planetocentric).
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround, or SetWorld was with successful or not.
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
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.
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
double Longitude() const
This returns a longitude with correct longitude direction and domain as specified in the label object...
double mCompute(const double sinphi, const double cosphi) const
A convience method to compute Snyder's m equation (14-15) for a given latitude, . ...
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
virtual double TrueScaleLatitude() const
This method returns the latitude of true scale.
LatitudeType m_latitudeType
An enumerated type indicating the LatitudeType read from the labels.
double PolarRadius() const
This returns the polar radius of the target.
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.
double qCompute(const double sinPhi) const
A convience method to compute Snyder's q equation (3-12) for a given latitude, .
double MaximumLongitude() const
This returns the maximum longitude of the area of interest.
bool IsPlanetographic() const
This indicates if the latitude type is planetographic (as opposed to planetocentric).
QString LatitudeTypeString() const
This method returns the latitude type 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.
double tCompute(const double phi, const double sinphi) const
A convience method to compute Snyder's t equation (15-9) for a given latitude, .
void XYRangeCheck(const double latitude, const double longitude)
This convience function is established to assist in the development of the XYRange virtual method...
QString LongitudeDomainString() const
This method returns the longitude domain as a string.
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
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...
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
static double ToPositiveEast(const double lon, const int domain)
This method converts a longitude into the positive east direction.
double PixelResolution() const
Returns the pixel resolution value from the PVL mapping group in meters/pixel.
Longitude values increase in the easterly direction.
PvlGroup m_mappingGrp
Mapping group that created this projection.
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 Scale() const
This method returns the scale for mapping world coordinates into projection coordinates.