|
Isis 3 Programmer Reference
|
7 #include "TProjection.h"
19 #include "Constants.h"
20 #include "Displacement.h"
22 #include "IException.h"
24 #include "Longitude.h"
25 #include "NaifStatus.h"
28 #include "PvlKeyword.h"
29 #include "SpecialPixel.h"
31 #include "WorldMapper.h"
106 QString msg =
"Projection failed. No target radii are available "
107 "through keywords [EquatorialRadius and PolarRadius] "
114 QString msg =
"Projection failed. Invalid value for keyword "
115 "[EquatorialRadius]. It must be greater than zero";
119 QString msg =
"Projection failed. Invalid value for keyword "
120 "[PolarRadius]. It must be greater than zero";
125 if ((QString)
m_mappingGrp[
"LatitudeType"] ==
"Planetographic") {
128 else if ((QString)
m_mappingGrp[
"LatitudeType"] ==
"Planetocentric") {
132 QString msg =
"Projection failed. Invalid value for keyword "
133 "[LatitudeType] must be "
134 "[Planetographic or Planetocentric]";
139 if ((QString)
m_mappingGrp[
"LongitudeDirection"] ==
"PositiveWest") {
142 else if ((QString)
m_mappingGrp[
"LongitudeDirection"] ==
"PositiveEast") {
146 QString msg =
"Projection failed. Invalid value for keyword "
147 "[LongitudeDirection] must be "
148 "[PositiveWest or PositiveEast]";
153 if ((QString)
m_mappingGrp[
"LongitudeDomain"] ==
"360") {
156 else if ((QString)
m_mappingGrp[
"LongitudeDomain"] ==
"180") {
160 QString msg =
"Projection failed. Invalid value for keyword "
161 "[LongitudeDomain] must be [180 or 360]";
177 QString msg =
"Projection failed. "
179 +
"] is outside the range of [-90:90]";
184 QString msg =
"Projection failed. "
186 +
"] is outside the range of [-90:90]";
191 QString msg =
"Projection failed. "
192 "[MinimumLatitude,MaximumLatitude] of ["
195 +
"properly ordered";
200 QString msg =
"Projection failed. "
201 "[MinimumLongitude,MaximumLongitude] of ["
204 +
"properly ordered";
220 QString msg =
"Projection failed. Invalid keyword value(s). "
222 +
" must be greater than or equal to [PolarRadius] = "
241 QString msg =
"Projection failed. Invalid label group [Mapping]";
261 if (!Projection::operator==(proj))
return false;
327 if (latitude ==
Null) {
329 "Unable to calculate local radius. The given latitude value ["
330 +
toString(latitude) +
"] is invalid.",
336 if (a - c < DBL_EPSILON) {
340 double lat = latitude *
PI / 180.0;
341 return a * c / sqrt(pow(c * cos(lat), 2) + pow(a * sin(lat), 2));
435 double eRadius,
double pRadius) {
436 if (lat ==
Null || abs(lat) > 90.0) {
438 "Unable to convert to Planetocentric. The given latitude value ["
443 if (abs(mylat) < 90.0) {
445 mylat = atan(tan(mylat) * (pRadius / eRadius) *
446 (pRadius / eRadius));
481 double eRadius,
double pRadius) {
483 if (qFuzzyCompare(fabs(lat), 90.0)) {
486 if (lat ==
Null || fabs(lat) > 90.0) {
488 "Unable to convert to Planetographic. The given latitude value ["
493 if (fabs(mylat) < 90.0) {
495 mylat = atan(tan(mylat) * (eRadius / pRadius) *
496 (eRadius / pRadius));
510 return "Planetocentric";
551 "Unable to convert to PositiveEast. The given longitude value ["
562 else if (domain == 180) {
566 QString msg =
"Unable to convert longitude. Domain [" +
toString(domain)
567 +
"] is not 180 or 360.";
590 "Unable to convert to PositiveWest. The given longitude value ["
601 else if (domain == 180) {
605 QString msg =
"Unable to convert longitude. Domain [" +
toString(domain)
606 +
"] is not 180 or 360.";
622 return "PositiveWest";
660 "Unable to convert to 180 degree domain. The given longitude value ["
678 "Unable to convert to 360 degree domain. The given longitude value ["
684 if ( (lon < 0.0 || lon > 360.0) &&
685 !qFuzzyCompare(lon, 0.0) && !qFuzzyCompare(lon, 360.0)) {
994 double &minY,
double &maxY) {
1064 if (latitude ==
Null || longitude ==
Null) {
1105 if (adjustedMinLon > adjustedMaxLon) {
1106 if (adjustedLon > adjustedMinLon) {
1109 adjustedMinLon -= 360;
1113 if (qFuzzyCompare(maxLon - minLon, 360.0)) {
1116 else if (adjustedMinLon <= adjustedLon && adjustedLon <= adjustedMaxLon) {
1196 double &minY,
double &maxY) {
1208 double minFoundX1, minFoundX2;
1209 double minFoundY1, minFoundY2;
1225 double minFoundX3, minFoundX4;
1226 double minFoundY3, minFoundY4;
1242 double minFoundX5 = min(minFoundX1, minFoundX2);
1243 double minFoundX6 = min(minFoundX3, minFoundX4);
1246 double minFoundY5 = min(minFoundY1, minFoundY2);
1247 double minFoundY6 = min(minFoundY3, minFoundY4);
1251 double maxFoundX1, maxFoundX2;
1252 double maxFoundY1, maxFoundY2;
1268 double maxFoundX3, maxFoundX4;
1269 double maxFoundY3, maxFoundY4;
1285 double maxFoundX5 = max(maxFoundX1, maxFoundX2);
1286 double maxFoundX6 = max(maxFoundX3, maxFoundX4);
1289 double maxFoundY5 = max(maxFoundY1, maxFoundY2);
1290 double maxFoundY6 = max(maxFoundY3, maxFoundY4);
1295 for (
unsigned int specialLatCase = 0;
1296 specialLatCase < specialLatCases.size();
1297 specialLatCase ++) {
1298 double minX, maxX, minY, maxY;
1302 minX, specialLatCases[specialLatCase],
true,
false,
true);
1305 minY, specialLatCases[specialLatCase],
false,
false,
true);
1308 maxX, specialLatCases[specialLatCase],
true,
false,
false);
1311 maxY, specialLatCases[specialLatCase],
false,
false,
false);
1320 for (
unsigned int specialLonCase = 0;
1321 specialLonCase < specialLonCases.size();
1322 specialLonCase ++) {
1323 double minX, maxX, minY, maxY;
1327 minX, specialLonCases[specialLonCase],
true,
true,
true);
1330 minY, specialLonCases[specialLonCase],
false,
true,
true);
1333 maxX, specialLonCases[specialLonCase],
true,
true,
false);
1336 maxY, specialLonCases[specialLonCase],
false,
true,
false);
1398 double &extremeVal,
const double constBorder,
1399 bool searchX,
bool searchLongitude,
bool findMin) {
1400 if (minBorder ==
Null || maxBorder ==
Null || constBorder ==
Null) {
1404 const int NUM_ATTEMPTS = (
unsigned int)DBL_DIG;
1407 double minBorderX, minBorderY, maxBorderX, maxBorderY;
1411 findExtreme(minBorder, maxBorder, minBorderX, minBorderY, maxBorderX,
1412 maxBorderY, constBorder, searchX, searchLongitude, findMin);
1413 if (minBorderX ==
Null && maxBorderX ==
Null
1414 && minBorderY ==
Null && maxBorderY ==
Null ) {
1415 attempts = NUM_ATTEMPTS;
1420 while ((fabs(minBorderX - maxBorderX) > TOLERANCE
1421 || fabs(minBorderY - maxBorderY) > TOLERANCE)
1422 && (attempts < NUM_ATTEMPTS));
1427 if (attempts >= NUM_ATTEMPTS) {
1432 if (searchLongitude) {
1442 if (searchX) extremeVal = min(minBorderX, maxBorderX);
1443 else extremeVal = min(minBorderY, maxBorderY);
1446 if (searchX) extremeVal = max(minBorderX, maxBorderX);
1447 else extremeVal = max(minBorderY, maxBorderY);
1512 double &minBorderX,
double &minBorderY,
1513 double &maxBorderX,
double &maxBorderY,
1514 const double constBorder,
bool searchX,
1515 bool searchLongitude,
bool findMin) {
1516 if (minBorder ==
Null || maxBorder ==
Null || constBorder ==
Null) {
1518 minBorderY = minBorderX;
1519 minBorderY = minBorderX;
1522 if (!searchLongitude && (fabs(fabs(constBorder) - 90.0) < DBL_EPSILON)) {
1527 maxBorderY = minBorderY;
1531 const double STEP_SIZE = (maxBorder - minBorder) / 10.0;
1532 const double LOOP_END = maxBorder + (STEP_SIZE / 2.0);
1535 double currBorderVal = minBorder;
1543 while (!
m_good && currBorderVal <= LOOP_END) {
1544 currBorderVal+=STEP_SIZE;
1545 if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1546 currBorderVal = 90.0;
1560 double border1 = currBorderVal;
1561 double border2 = currBorderVal;
1562 double border3 = currBorderVal;
1568 double value2 = value1;
1572 double extremeVal2 = value2;
1576 double extremeBorder1 = minBorder;
1577 double extremeBorder3 = minBorder;
1579 while (currBorderVal <= LOOP_END) {
1586 if (searchLongitude && (currBorderVal - 90.0 > DBL_EPSILON)) {
1587 currBorderVal = 90.0;
1591 currBorderVal += STEP_SIZE;
1600 border1 = currBorderVal;
1604 if ((findMin && value2 < extremeVal2)
1605 || (!findMin && value2 > extremeVal2)) {
1610 extremeVal2 = value2;
1612 extremeBorder3 = border3;
1613 extremeBorder1 = border1;
1620 minBorder = extremeBorder3;
1625 if (extremeBorder1 <= maxBorder ) {
1626 maxBorder = extremeBorder1;
1674 const double constBorder,
1675 bool variableIsLat) {
1676 if (variableBorder ==
Null || constBorder ==
Null) {
1680 if (variableIsLat) {
1681 lat = variableBorder;
1686 lon = variableBorder;
1702 keyNames <<
"TargetName" <<
"ProjectionName" <<
"EquatorialRadius" <<
"PolarRadius"
1703 <<
"LatitudeType" <<
"LongitudeDirection" <<
"LongitudeDomain"
1704 <<
"PixelResolution" <<
"Scale" <<
"UpperLeftCornerX" <<
"UpperLeftCornerY"
1705 <<
"MinimumLatitude" <<
"MaximumLatitude" <<
"MinimumLongitude" <<
"MaximumLongitude"
1708 foreach (QString keyName, keyNames) {
1772 QString msg =
"Snyder's q variable should only be computed for "
1773 "ellipsoidal projections.";
1778 * (sinPhi / (1 - eSinPhi * eSinPhi)
1779 - 1 / (2 *
m_eccentricity) * log( (1 - eSinPhi) / (1 + eSinPhi) ));
1804 double localPhi =
HALFPI - 2.0 * atan(t);
1806 double difference = DBL_MAX;
1813 const int MAX_ITERATIONS = 45;
1815 while ((iteration < MAX_ITERATIONS) && (difference > 0.0000000001)) {
1816 double eccTimesSinphi =
Eccentricity() * sin(localPhi);
1818 2.0 * atan(t * pow((1.0 - eccTimesSinphi) /
1819 (1.0 + eccTimesSinphi), halfEcc));
1820 difference = fabs(newPhi - localPhi);
1825 if (iteration >= MAX_ITERATIONS) {
1826 QString msg =
"Failed to converge in TProjection::phi2Compute()";
1849 double denominator = sqrt(1.0 - eccTimesSinphi * eccTimesSinphi);
1850 return cosphi / denominator;
1871 if ((
HALFPI) - fabs(phi) < DBL_EPSILON)
return 0.0;
1874 double denominator = pow((1.0 - eccTimesSinphi) /
1875 (1.0 + eccTimesSinphi),
1877 return tan(0.5 * (
HALFPI - phi)) / denominator;
1895 return sqrt(pow(onePlusEcc, onePlusEcc) *
1896 pow(oneMinusEcc, oneMinusEcc));
double m_maximumLatitude
Contains the maximum latitude for the entire ground range.
static PvlGroup radiiGroup(QString target)
Creates a Pvl Group with keywords TargetName, EquitorialRadius, and PolarRadius.
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
const double HALFPI
The mathematical constant PI/2.
double m_longitude
This contains the currently set longitude value.
double m_eccentricity
The eccentricity of the target body.
int m_longitudeDomain
This integer is either 180 or 360 and is read from the labels.
virtual bool operator==(const Projection &proj)
This method determines whether two map projection objects are equal by comparing the equatorial radiu...
double m_minimumLongitude
Contains the minimum longitude for the entire ground range.
double m_latitude
This contains the currently set latitude value.
static double ToPositiveWest(const double lon, const int domain)
This method converts a longitude into the positive west direction.
WorldMapper * m_mapper
This points to a mapper passed into the SetWorldMapper method.
bool IsPositiveWest() const
This indicates if the longitude direction type is positive east (as opposed to postive west).
const double PI
The mathematical constant PI.
virtual double UniversalLatitude()
This returns a universal latitude (planetocentric).
QString LongitudeDirectionString() const
This method returns the longitude direction as a string.
LongitudeDirection m_longitudeDirection
An enumerated type indicating the LongitudeDirection read from the labels.
double m_minimumLatitude
Contains the minimum latitude for the entire ground range.
@ PositiveWest
Longitude values increase in the westerly direction.
double e4Compute() const
A convience method to compute.
double PixelResolution() const
Returns the pixel resolution value from the PVL mapping group in meters/pixel.
virtual bool SetCoordinate(const double x, const double y)
This method is used to set the projection x/y.
virtual double MinimumLongitude() const
This returns the minimum longitude of the area of interest.
virtual ~TProjection()
Destroys the TProjection object.
@ Unknown
A type of error that cannot be classified as any of the other error types.
double m_minimumY
See minimumX description.
@ Planetocentric
Latitudes are measured as the angle from the equatorial plane to the plane through the center of the ...
bool IsPlanetographic() const
This indicates if the latitude type is planetographic (as opposed to planetocentric).
virtual double Longitude() const
This returns a longitude with correct longitude direction and domain as specified in the label object...
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...
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 hasKeyword(const QString &name) const
Check to see if a keyword exists.
Container for cube-like labels.
double Eccentricity() const
This returns the eccentricity of the target,.
void SetXY(double x, double y)
This protected method is a helper for derived classes.
@ PositiveEast
Longitude values increase in the easterly direction.
double ToPlanetocentric(const double lat) const
This method converts a planetographic latitude to a planetocentric latitude.
std::vector< double > m_specialLonCases
Constant Longitudes that intersect a discontinuity.
LatitudeType m_latitudeType
An enumerated type indicating the LatitudeType read from the labels.
virtual double Resolution() const
This virtual method will the resolution of the world system relative to one unit in the projection sy...
virtual double MaximumLatitude() const
This returns the maximum latitude of the area of interest.
void XYRangeCheck(const double latitude, const double longitude)
This convience function is established to assist in the development of the XYRange virtual method.
double EquatorialRadius() const
This returns the equatorial radius of the target.
bool Has360Domain() const
This indicates if the longitude domain is 0 to 360 (as opposed to -180 to 180).
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Longitude force180Domain() const
This returns a longitude that is constricted to -180 to 180 degrees.
PvlGroup m_mappingGrp
Mapping group that created this projection.
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...
void setProjectionType(const ProjectionType ptype)
Sets the projection subclass type.
This class is designed to encapsulate the concept of a Longitude.
QString LongitudeDomainString() const
This method returns the longitude domain as a string.
QString LatitudeTypeString() const
This method returns the latitude type as a string.
virtual bool SetUniversalGround(const double lat, const double lon)
This method is used to set the latitude/longitude which must be Planetocentric (latitude) and Positiv...
bool inLongitudeRange(double longitude)
Determine whether the given longitude is within the range of the MinimumLongitude and MaximumLongitud...
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround,...
double qCompute(const double sinPhi) const
A convience method to compute Snyder's q equation (3-12) for a given latitude, .
double m_minimumX
The data elements m_minimumX, m_minimumY, m_maximumX, and m_maximumY are convience data elements when...
Contains multiple PvlContainers.
bool IsPositiveEast() const
This indicates if the longitude direction type is positive west (as opposed to postive east).
@ Planetographic
Latitudes are measured as the angle from the equatorial plane to the normal to the surface of the pla...
double PolarRadius() const
This returns the polar radius of the target.
void setSearchGround(const double variableBorder, const double constBorder, bool variableIsLat)
This function sets the ground for the given border values.
virtual double Latitude() const
This returns a latitude with correct latitude type as specified in the label object.
bool m_good
Indicates if the contents of m_x, m_y, m_latitude, and m_longitude are valid.
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...
Base class for Map TProjections.
bool SetUnboundUniversalGround(const double coord1, const double coord2)
This method is used to set the latitude/longitude.
double Scale() const
This method returns the scale for mapping world coordinates into projection coordinates.
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).
bool m_groundRangeGood
Indicates if the ground range (min/max lat/lons) were read from the labels.
const double Null
Value for an Isis Null pixel.
virtual double MaximumLongitude() const
This returns the maximum longitude of the area of interest.
bool inLatitudeRange(double latitude)
Determine whether the given latitude is within the range of the MinimumLatitude and MaximumLatitude r...
virtual PvlGroup MappingLongitudes()
This function returns the longitude keywords that this projection uses.
double LocalRadius() const
This method returns the local radius in meters at the current latitude position.
virtual double TrueScaleLatitude() const
This method returns the latitude of true scale.
void SetComputedXY(double x, double y)
This protected method is a helper for derived classes.
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,...
Namespace for the standard library.
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.
double m_maximumLongitude
Contains the maximum longitude for the entire ground range.
static double ToPositiveEast(const double lon, const int domain)
This method converts a longitude into the positive east direction.
virtual double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
virtual PvlGroup MappingLatitudes()
This function returns the latitude keywords that this projection uses.
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 degrees() const
Get the angle in units of Degrees.
virtual double MinimumLatitude() const
This returns the minimum latitude of the area of interest.
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
virtual PvlGroup Mapping()
This function returns the keywords that this projection uses.
double m_equatorialRadius
Polar radius of the target.
double m_polarRadius
Polar radius of the target.
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
bool IsPlanetocentric() const
This indicates if the latitude type is planetocentric (as opposed to planetographic).
double YCoord() const
This returns the projection Y provided SetGround, SetCoordinate, SetUniversalGround,...
double m_maximumY
See minimumX description.
virtual bool IsEquatorialCylindrical()
This method returns true if the projection is equatorial cylindrical.
Base class for Map Projections.
double m_maximumX
See minimumX description.
double mCompute(const double sinphi, const double cosphi) const
A convience method to compute Snyder's m equation (14-15) for a given latitude, .
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
double XCoord() const
This returns the projection X provided SetGround, SetCoordinate, SetUniversalGround,...
virtual bool HasGroundRange() const
This indicates if the longitude direction type is positive west (as opposed to postive east).
This is free and unencumbered software released into the public domain.
std::vector< double > m_specialLatCases
Constant Latitudes that intersect a discontinuity.