Loading isis/src/base/objs/Camera/Camera.cpp +240 −64 Original line number Diff line number Diff line Loading @@ -22,10 +22,11 @@ */ #include "Camera.h" #include <algorithm> #include <cfloat> #include <cmath> #include <iomanip> #include <algorithm> #include <stdint.h> #include <QDebug> Loading Loading @@ -61,10 +62,10 @@ using namespace std; namespace Isis { /** * Constructs the Camera object * * @param lab Pvl label used to create the Camera object * @brief Constructs the Camera object. * @param cube The Pvl label from the cube is used to create the Camera object. */ Camera::Camera(Cube &cube) : Sensor(cube) { m_instrumentNameLong = "Unknown"; Loading Loading @@ -153,15 +154,13 @@ namespace Isis { } } /** * Sets the sample/line values of the image to get the lat/lon values * @brief Sets the sample/line values of the image to get the lat/lon values. * * @param sample Sample coordinate of the cube * @param line Line coordinate of the cube * * @return @b bool Returns true if the image was set successfully and false if it * was not * @param sample Sample coordinate of the cube. * @param line Line coordinate of the cube. * @return @b bool Returns True if the image was set successfully and Talse if it * was not. */ bool Camera::SetImage(const double sample, const double line) { p_childSample = sample; Loading Loading @@ -275,7 +274,6 @@ namespace Isis { return false; } /** * Sets the lat/lon values to get the sample/line values * Loading Loading @@ -416,9 +414,10 @@ namespace Isis { } } else { // ring plane // UniversalLongitude should return azimuth (ring longitude) in this case TODO: when we make the change // to real azimuths this value may need to be adjusted or code changed in the shapemodel or // surfacepoint class. // UniversalLongitude should return azimuth (ring longitude) in this case // TODO: // when we make the change to real azimuths this value may need to be adjusted or // code changed in the shapemodel or surfacepoint class. if (p_projection->SetUniversalGround(LocalRadius().meters(), UniversalLongitude())) { p_childSample = p_projection->WorldX(); p_childLine = p_projection->WorldY(); Loading @@ -438,14 +437,14 @@ namespace Isis { /** * Sets the lat/lon/radius values to get the sample/line values * @brief Sets the lat/lon/radius values to get the sample/line values * * @param latitude Latitude coordinate of the cube * @param longitude Longitude coordinate of the cube * @param radius Radius coordinate of the cube * * @return @b bool Returns true if the Universal Ground was set successfully * and false if it was not * @return @b bool Returns True if the Universal Ground was set successfully * and False if it was not */ bool Camera::SetUniversalGround(const double latitude, const double longitude, const double radius) { Loading @@ -460,8 +459,114 @@ namespace Isis { return false; } /** * @description This function provides an improved estimate of the detector resolution (in meters) * when the target is near the limb. It does this by calculating the determinant of an affine * transformation. The area element of one pixel projected onto the surface at Nadir looks * like a square with sides of length = Detector Resolution. The detector resolution is the * value returned by the original function. An affine projective transformation of this * area element as one would see if it was on the limb instead of looking straight down, appears * like a skewed parallelogram. * * The determinant of the transformation matrix taking the Nadir-area element into * some parallelogram near the limb of a planet measures the change in area for the * transformation when we are off-Nadir. The sqare-root of the area of this parallelogram * gives us the resolution. * *The calculation is straightforward. Any affine transformation with a strictly positive *determinant that is not a similarity transformation has a unique decomposition *(See Theorem 2.1 in Reference #1): * * * * * @f{eqnarray*} * * A = \[\left[\begin{array}{cc} a & b \\ * c & d \end{array} \right]\] = * * H_{\lambda}R_1(\psi)T_tR_2(\phi) = \lambda * \[ \left[\begin{array}{cc} cos(\psi) & -sin(\psi) \\ * sin(\psi) & cos(\psi) \end{array} \right]\] * \[ \left[\begin{array}{cc} t & 0 \\ * 0 & 1 \end{array} \right]\] * \[ \left[\begin{array}{cc} cos(\phi) & -sin(\phi) \\ * sin(\phi) & cos(\phi) \end{array} \right]\] * * @f} * * Where: * * @f$ t = \frac{1}{cos(\theta)}},\;\;\theta = \text{Emmission\;\; Angle}@f$ * and @f$\lambda = \text{zoom\;\;factor} = 1@f$ * * The determinant of A is: * * @f[ |A| = \lambda t = \frac{\lambda}{cos(\theta)} = \frac{1}{\cos(\theta)} @f] * * This is because the two rotation matrices in this decomposition have determinants equal to 1. * * Let @f$ n = \text{Detector\;\;Resolution} @f$ * * Then: * * @f[ Area = n^2 |A| =\frac{n^2}{cos(\theta)}@f] * * And: * * @f[ \text{Local\;\;Detector\;\; Resolution} = \frac{n}{\sqrt{cos(\theta)}} @f] * * * This method returns the Local Detector Resolution if the Look Vector intersects the target * and if @f$ 0 \leq \theta < \frac{\pi}{2} @f$ and -1.0 otherwise. * * * * * Reference 1: J-M Morel and G. Yu, "Asift: A new framework for fully affine * invariant image comparison," SIAM Journal on Imaging Sciences * 2(2), pp. 438-469, 2009 * * * @return @b double */ double Camera::ObliqueDetectorResolution(){ if(HasSurfaceIntersection()){ double thetaRad; double sB[3]; instrumentPosition(sB); double pB[3]; Coordinate(pB); double a = sB[0] - pB[0]; double b = sB[1] - pB[1]; double c = sB[2] - pB[2]; double rho = sqrt(a * a + b * b + c * c) * 1000.0; thetaRad = EmissionAngle()*DEG2RAD; if (thetaRad < HALFPI) { double nadirResolution = rho/(p_focalLength/p_pixelPitch); return nadirResolution/sqrt(cos(thetaRad)); } return Isis::Null; } return Isis::Null; } /** * Returns the detector resolution at the current position * @brief Returns the detector resolution at the current position in meters. * * @return @b double The detector resolution */ Loading @@ -480,17 +585,31 @@ namespace Isis { return Isis::Null; } /** * Returns the sample resolution at the current position * @brief Returns the sample resolution at the current position in meters. * * @return @b double The sample resolution */ double Camera::SampleResolution() { return DetectorResolution() * p_detectorMap->SampleScaleFactor(); } /** * Returns the line resolution at the current position * @brief Returns the oblique sample resolution at the current position in m. This gives * a more accurate estimate of the sample resolution at oblique angles. * * @return @b double The sample resolution */ double Camera::ObliqueSampleResolution() { return ObliqueDetectorResolution() * p_detectorMap->SampleScaleFactor(); } /** * @brief Returns the line resolution at the current position in meters. * * @return @b double The line resolution */ Loading @@ -498,9 +617,22 @@ namespace Isis { return DetectorResolution() * p_detectorMap->LineScaleFactor(); } /** * Returns the pixel resolution at the current position in m/pix * @brief Returns the oblique line resolution at the current position in meters. This * provides a more accurate estimate of the line resolution at oblique * angles. * * @return @b double The line resolution */ double Camera::ObliqueLineResolution() { return ObliqueDetectorResolution() * p_detectorMap->LineScaleFactor(); } /** * @brief Returns the pixel resolution at the current position in meters/pixel. * @return @b double The pixel resolution */ double Camera::PixelResolution() { Loading @@ -511,8 +643,24 @@ namespace Isis { return (lineRes + sampRes) / 2.0; } /** * Returns the lowest/worst resolution in the entire image * @brief Returns the oblique pixel resolution at the current position in meters/pixel. This * provides a more accurate estimate of the pixel resolution at oblique angles. * * @return @b double The pixel resolution */ double Camera::ObliquePixelResolution() { double lineRes = ObliqueLineResolution(); double sampRes = ObliqueSampleResolution(); if (lineRes < 0.0) return Isis::Null; if (sampRes < 0.0) return Isis::Null; return (lineRes + sampRes) / 2.0; } /** * @brief Returns the lowest/worst resolution in the entire image * * @return @b double The lowest/worst resolution in the image */ Loading @@ -521,8 +669,9 @@ namespace Isis { return p_maxres; } /** * Returns the highest/best resolution in the entire image * @brief Returns the highest/best resolution in the entire image * * @return @b double The highest/best resolution in the entire image */ Loading @@ -531,8 +680,31 @@ namespace Isis { return p_minres; } /** * Computes the ground range and min/max resolution * @brief Returns the lowest/worst oblique resolution in the entire image * * @return @b double The lowest/worst oblique resolution in the image */ double Camera::LowestObliqueImageResolution() { GroundRangeResolution(); return p_minobliqueres; } /** * @brief Returns the highest/best oblique resolution in the entire image * * @return @b double The highest/best oblique resolution in the entire image */ double Camera::HighestObliqueImageResolution() { GroundRangeResolution(); return p_maxobliqueres; } /** * @brief Computes the ground range and min/max resolution */ void Camera::GroundRangeResolution() { // Software adjustment is needed if we get here -- call RingRangeResolution instead Loading Loading @@ -560,6 +732,8 @@ namespace Isis { p_maxlon180 = -DBL_MAX; p_minres = DBL_MAX; p_maxres = -DBL_MAX; p_minobliqueres = DBL_MAX; p_maxobliqueres = -DBL_MAX; // See if we have band dependence and loop for the appropriate number of bands int eband = p_bands; Loading Loading @@ -591,6 +765,13 @@ namespace Isis { if (res < p_minres) p_minres = res; if (res > p_maxres) p_maxres = res; } // Determine min/max oblique resolution double obliqueres = ObliquePixelResolution(); if (obliqueres > 0.0) { if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres; if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres; } if ((line != 1) && (line != p_lines + 1)) break; } } // end loop through samples Loading Loading @@ -619,6 +800,14 @@ namespace Isis { if (res < p_minres) p_minres = res; if (res > p_maxres) p_maxres = res; } // Determine min/max oblique resolution double obliqueres = ObliquePixelResolution(); if (obliqueres > 0.0) { if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres; if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres; } break; } } Loading Loading @@ -648,6 +837,13 @@ namespace Isis { if (res < p_minres) p_minres = res; if (res > p_maxres) p_maxres = res; } double obliqueres = ObliquePixelResolution(); if (obliqueres > 0.0) { if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres; if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres; } } } } // end valid local (subspacecraft) radius Loading Loading @@ -738,7 +934,9 @@ namespace Isis { // Checks for invalid lat/lon ranges // if(p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX || p_maxlat == -DBL_MAX) { // if(p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX // || p_maxlat == -DBL_MAX) // { // string message = "Camera missed planet or SPICE data off."; // throw IException(IException::Unknown, message, _FILEINFO_); // } Loading @@ -746,7 +944,7 @@ namespace Isis { /** * Analogous to above GroundRangeResolution method. Computes the ring range * @brief Analogous to above GroundRangeResolution method. Computes the ring range * and min/max resolution */ void Camera::ringRangeResolution() { Loading Loading @@ -916,7 +1114,8 @@ namespace Isis { } // Checks for invalid radius/lon ranges if (p_minRingRadius == DBL_MAX || p_minRingRadius == DBL_MAX || p_minRingLongitude == DBL_MAX || p_maxRingLongitude == -DBL_MAX) { if (p_minRingRadius == DBL_MAX || p_minRingRadius == DBL_MAX || p_minRingLongitude == DBL_MAX || p_maxRingLongitude == -DBL_MAX) { string message = "RingPlane ShapeModel - Camera missed plane or SPICE data off."; throw IException(IException::Unknown, message, _FILEINFO_); } Loading Loading @@ -1152,7 +1351,8 @@ namespace Isis { * @param pvl Pvl to write mapping group to */ void Camera::basicRingMapping(Pvl &pvl) { if (target()->shape()->name() != "Plane") { // If we get here and we don't have a plane, throw an error if (target()->shape()->name() != "Plane") { // If we get here and we don't have a plane, throw an error IString msg = "A ring plane projection has been requested on an image whose shape is not a ring plane. "; msg += "Rerun spiceinit with shape=RINGPLANE. "; throw IException(IException::User, msg, _FILEINFO_); Loading Loading @@ -1189,6 +1389,8 @@ namespace Isis { SetPixelPitch(Spice::getDouble(key)); } /** * Sets the right ascension declination * Loading Loading @@ -1456,6 +1658,8 @@ namespace Isis { // angle (in radians) incidence = Angle(vsep_c(unitizedSurfSunVect, normal), Angle::Radians); } Loading @@ -1466,12 +1670,13 @@ namespace Isis { * @param maxra Maximum right ascension value * @param mindec Minimum declination value * @param maxdec Maximum declination value * * @return @b bool Returns true if the range computation was successful and false * if it was not */ bool Camera::RaDecRange(double &minra, double &maxra, double &mindec, double &maxdec) { bool computed = p_pointComputed; double originalSample = Sample(); double originalLine = Line(); Loading Loading @@ -1611,6 +1816,7 @@ namespace Isis { * @return @b double The resutant RaDec resolution */ double Camera::RaDecResolution() { bool computed = p_pointComputed; double originalSample = Sample(); double originalLine = Line(); Loading Loading @@ -1687,7 +1893,6 @@ namespace Isis { return ComputeAzimuth(LocalRadius(lat, lon), lat, lon); } /** * Return the Spacecraft Azimuth * Loading @@ -1701,7 +1906,6 @@ namespace Isis { return ComputeAzimuth(LocalRadius(lat, lon), lat, lon); } /** * Computes the image azimuth value from your current position (origin) to a point of interest * specified by the lat/lon input to this method. (NOTE: This azimuth is different from a Ground Loading Loading @@ -1952,7 +2156,6 @@ namespace Isis { return azimuth; } /** * Return the off nadir angle in degrees. * Loading @@ -1978,7 +2181,6 @@ namespace Isis { return c; } /** * Computes and returns the ground azimuth between the ground point and * another point of interest, such as the subspacecraft point or the Loading Loading @@ -2106,7 +2308,6 @@ namespace Isis { p_distortionMap = map; } /** * Sets the Focal Plane Map. This object will take ownership of the focal plane * map pointer. Loading @@ -2121,7 +2322,6 @@ namespace Isis { p_focalPlaneMap = map; } /** * Sets the Detector Map. This object will take ownership of the detector map * pointer. Loading @@ -2136,7 +2336,6 @@ namespace Isis { p_detectorMap = map; } /** * Sets the Ground Map. This object will take ownership of the ground map * pointer. Loading @@ -2151,7 +2350,6 @@ namespace Isis { p_groundMap = map; } /** * Sets the Sky Map. This object will take ownership of the sky map pointer. * Loading @@ -2165,7 +2363,6 @@ namespace Isis { p_skyMap = map; } /** * This loads the spice cache big enough for this image. The default cache size * is the number of lines in the cube if the ephemeris time changes in the Loading Loading @@ -2261,7 +2458,6 @@ namespace Isis { return ephemerisTimes; } /** * This method calculates the spice cache size. This method finds the number * of lines in the beta cube and adds 1, since we need at least 2 points for Loading Loading @@ -2346,7 +2542,6 @@ namespace Isis { p_geometricTilingEndSize = endSize; } /** * This will get the geometric tiling hint; these values are typically used for * ProcessRubberSheet::SetTiling(...). Loading Loading @@ -2380,7 +2575,6 @@ namespace Isis { return true; } /** * Checks to see if the camera object has a projection * Loading @@ -2391,7 +2585,6 @@ namespace Isis { return p_projection != 0; } /** * Virtual method that checks if the band is independent * Loading @@ -2402,7 +2595,6 @@ namespace Isis { return true; } /** * Returns the reference band * Loading @@ -2412,7 +2604,6 @@ namespace Isis { return p_referenceBand; } /** * Checks to see if the Camera object has a reference band * Loading @@ -2423,7 +2614,6 @@ namespace Isis { return p_referenceBand != 0; } /** * Virtual method that sets the band number * Loading @@ -2433,7 +2623,6 @@ namespace Isis { p_childBand = band; } /** * Returns the current sample number * Loading @@ -2443,7 +2632,6 @@ namespace Isis { return p_childSample; } /** * Returns the current band * Loading @@ -2453,7 +2641,6 @@ namespace Isis { return p_childBand; } /** * Returns the current line number * Loading @@ -2462,8 +2649,6 @@ namespace Isis { double Camera::Line() { return p_childLine; } /** * Returns the resolution of the camera * Loading @@ -2474,6 +2659,8 @@ namespace Isis { } /** * Returns the focal length * Loading @@ -2483,7 +2670,6 @@ namespace Isis { return p_focalLength; } /** * Returns the pixel pitch * Loading @@ -2493,7 +2679,6 @@ namespace Isis { return p_pixelPitch; } /** * Returns the pixel ifov offsets from center of pixel, which defaults to the * (pixel pitch * summing mode ) / 2. If an instrument has a non-square ifov, it must implement Loading Loading @@ -2525,7 +2710,6 @@ namespace Isis { return p_samples; } /** * Returns the number of lines in the image * Loading @@ -2535,7 +2719,6 @@ namespace Isis { return p_lines; } /** * Returns the number of bands in the image * Loading @@ -2545,7 +2728,6 @@ namespace Isis { return p_bands; } /** * Returns the number of lines in the parent alphacube * Loading @@ -2555,7 +2737,6 @@ namespace Isis { return p_alphaCube->AlphaLines(); } /** * Returns the number of samples in the parent alphacube * Loading @@ -2564,8 +2745,6 @@ namespace Isis { int Camera::ParentSamples() const { return p_alphaCube->AlphaSamples(); } /** * Returns a pointer to the CameraDistortionMap object * Loading @@ -2575,7 +2754,6 @@ namespace Isis { return p_distortionMap; } /** * Returns a pointer to the CameraFocalPlaneMap object * Loading @@ -2585,7 +2763,6 @@ namespace Isis { return p_focalPlaneMap; } /** * Returns a pointer to the CameraDetectorMap object * Loading @@ -2595,7 +2772,6 @@ namespace Isis { return p_detectorMap; } /** * Returns a pointer to the CameraGroundMap object * Loading @@ -2605,7 +2781,6 @@ namespace Isis { return p_groundMap; } /** * Returns a pointer to the CameraSkyMap object * Loading Loading @@ -2794,3 +2969,4 @@ namespace Isis { // end namespace isis } isis/src/base/objs/Camera/Camera.h +78 −68 Original line number Diff line number Diff line Loading @@ -213,15 +213,15 @@ namespace Isis { * @history 2015-10-16 Ian Humphrey - Added protected members for spacecraft and instrument * names as well as public member getters. Updated unit test. * References #2335. * @history 2015-09-01 Ian Humphrey and Makayla Shepherd - Modified unit test to override * Sensor's pure virtual methods. * @history 2015-10-16 Ian Humphrey - Added protected members for spacecraft and instrument * names as well as public member getters. Updated unit test. * References #2335. * @history 2016-06-27 Kelvin Rodriguez - Added member function to compute celestial north * clock angle. References #2365 * @history 2016-08-01 Curtis Rose - Changed return values of resolutions from -1 to Isis::Null. * Fixes #2065. * @history 2016-08-16 Tyler Wilson - Added ObliqueDectectorResolution,ObliqueLineResolution, * ObliqueSampleResolution, and ObliquePixelResolution functions * which give greatly improved approximations compared to their * non-oblique counterpart functions when the Look vector is pointing * off nadir and near the limb. Fixes #476. References #4100. */ class Camera : public Sensor { Loading Loading @@ -267,9 +267,17 @@ namespace Isis { double SampleResolution(); double DetectorResolution(); double ObliqueDetectorResolution(); double ObliqueSampleResolution(); double ObliqueLineResolution(); double ObliquePixelResolution(); virtual double resolution(); double LowestImageResolution(); double HighestImageResolution(); double LowestObliqueImageResolution(); double HighestObliqueImageResolution(); void BasicMapping(Pvl &map); void basicRingMapping(Pvl &map); Loading @@ -288,7 +296,6 @@ namespace Isis { bool RaDecRange(double &minra, double &maxra, double &mindec, double &maxdec); double RaDecResolution(); CameraDistortionMap *DistortionMap(); Loading Loading @@ -483,6 +490,8 @@ namespace Isis { double p_maxlon; //!< The maximum longitude double p_minres; //!< The minimum resolution double p_maxres; //!< The maximum resolution double p_minobliqueres; //!< The minimum oblique resolution double p_maxobliqueres; //!< The maximum oblique resolution double p_minlon180; //!< The minimum longitude in the 180 domain double p_maxlon180; //!< The maximum longitude in the 180 domain bool p_groundRangeComputed; /**!< Flag showing if ground range Loading Loading @@ -520,7 +529,7 @@ namespace Isis { AlphaCube *p_alphaCube; //!< A pointer to the AlphaCube double p_childSample; //!< Sample value for child double p_childLine; //!< Line value for child int p_childBand; //!< Band value for child. Should be the virtual band not original band. int p_childBand; //!< Band value for child CameraDistortionMap *p_distortionMap; //!< A pointer to the DistortionMap CameraFocalPlaneMap *p_focalPlaneMap; //!< A pointer to the FocalPlaneMap CameraDetectorMap *p_detectorMap; //!< A pointer to the DetectorMap Loading @@ -540,3 +549,4 @@ namespace Isis { }; #endif isis/src/base/objs/Camera/Camera.truth +4 −0 Original line number Diff line number Diff line Loading @@ -47,9 +47,13 @@ Line: 962 GroundRange: 0 IntersectsLongitudeDomain: 0 PixelResolution: 628 ObliquePixelResolution: 685 LineResolution: 628 ObliqueLineResolution: 685 SampleResolution: 628 ObliqueSampleResolution: 685 DetectorResolution: 157 ObliqueDetectorResolution: 171 LowestImageResolution: 2047 HighestImageResolution: 430 Calling BasicMapping (pvl)... Loading isis/src/base/objs/Camera/unitTest.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -162,9 +162,15 @@ int main() { } cout << "PixelResolution: " << c->PixelResolution() << endl; cout << "ObliquePixelResolution: " << c->ObliquePixelResolution() << endl; cout << "LineResolution: " << c->LineResolution() << endl; cout << "ObliqueLineResolution: " << c->ObliqueLineResolution() << endl; cout << "SampleResolution: " << c->SampleResolution() << endl; cout << "ObliqueSampleResolution: " << c->ObliqueSampleResolution() << endl; cout << "DetectorResolution: " << c->DetectorResolution() << endl; cout << "ObliqueDetectorResolution: " << c->ObliqueDetectorResolution() << endl; cout << "LowestImageResolution: " << setprecision(4) << c->LowestImageResolution() << endl; cout << "HighestImageResolution: " << setprecision(3) Loading Loading
isis/src/base/objs/Camera/Camera.cpp +240 −64 Original line number Diff line number Diff line Loading @@ -22,10 +22,11 @@ */ #include "Camera.h" #include <algorithm> #include <cfloat> #include <cmath> #include <iomanip> #include <algorithm> #include <stdint.h> #include <QDebug> Loading Loading @@ -61,10 +62,10 @@ using namespace std; namespace Isis { /** * Constructs the Camera object * * @param lab Pvl label used to create the Camera object * @brief Constructs the Camera object. * @param cube The Pvl label from the cube is used to create the Camera object. */ Camera::Camera(Cube &cube) : Sensor(cube) { m_instrumentNameLong = "Unknown"; Loading Loading @@ -153,15 +154,13 @@ namespace Isis { } } /** * Sets the sample/line values of the image to get the lat/lon values * @brief Sets the sample/line values of the image to get the lat/lon values. * * @param sample Sample coordinate of the cube * @param line Line coordinate of the cube * * @return @b bool Returns true if the image was set successfully and false if it * was not * @param sample Sample coordinate of the cube. * @param line Line coordinate of the cube. * @return @b bool Returns True if the image was set successfully and Talse if it * was not. */ bool Camera::SetImage(const double sample, const double line) { p_childSample = sample; Loading Loading @@ -275,7 +274,6 @@ namespace Isis { return false; } /** * Sets the lat/lon values to get the sample/line values * Loading Loading @@ -416,9 +414,10 @@ namespace Isis { } } else { // ring plane // UniversalLongitude should return azimuth (ring longitude) in this case TODO: when we make the change // to real azimuths this value may need to be adjusted or code changed in the shapemodel or // surfacepoint class. // UniversalLongitude should return azimuth (ring longitude) in this case // TODO: // when we make the change to real azimuths this value may need to be adjusted or // code changed in the shapemodel or surfacepoint class. if (p_projection->SetUniversalGround(LocalRadius().meters(), UniversalLongitude())) { p_childSample = p_projection->WorldX(); p_childLine = p_projection->WorldY(); Loading @@ -438,14 +437,14 @@ namespace Isis { /** * Sets the lat/lon/radius values to get the sample/line values * @brief Sets the lat/lon/radius values to get the sample/line values * * @param latitude Latitude coordinate of the cube * @param longitude Longitude coordinate of the cube * @param radius Radius coordinate of the cube * * @return @b bool Returns true if the Universal Ground was set successfully * and false if it was not * @return @b bool Returns True if the Universal Ground was set successfully * and False if it was not */ bool Camera::SetUniversalGround(const double latitude, const double longitude, const double radius) { Loading @@ -460,8 +459,114 @@ namespace Isis { return false; } /** * @description This function provides an improved estimate of the detector resolution (in meters) * when the target is near the limb. It does this by calculating the determinant of an affine * transformation. The area element of one pixel projected onto the surface at Nadir looks * like a square with sides of length = Detector Resolution. The detector resolution is the * value returned by the original function. An affine projective transformation of this * area element as one would see if it was on the limb instead of looking straight down, appears * like a skewed parallelogram. * * The determinant of the transformation matrix taking the Nadir-area element into * some parallelogram near the limb of a planet measures the change in area for the * transformation when we are off-Nadir. The sqare-root of the area of this parallelogram * gives us the resolution. * *The calculation is straightforward. Any affine transformation with a strictly positive *determinant that is not a similarity transformation has a unique decomposition *(See Theorem 2.1 in Reference #1): * * * * * @f{eqnarray*} * * A = \[\left[\begin{array}{cc} a & b \\ * c & d \end{array} \right]\] = * * H_{\lambda}R_1(\psi)T_tR_2(\phi) = \lambda * \[ \left[\begin{array}{cc} cos(\psi) & -sin(\psi) \\ * sin(\psi) & cos(\psi) \end{array} \right]\] * \[ \left[\begin{array}{cc} t & 0 \\ * 0 & 1 \end{array} \right]\] * \[ \left[\begin{array}{cc} cos(\phi) & -sin(\phi) \\ * sin(\phi) & cos(\phi) \end{array} \right]\] * * @f} * * Where: * * @f$ t = \frac{1}{cos(\theta)}},\;\;\theta = \text{Emmission\;\; Angle}@f$ * and @f$\lambda = \text{zoom\;\;factor} = 1@f$ * * The determinant of A is: * * @f[ |A| = \lambda t = \frac{\lambda}{cos(\theta)} = \frac{1}{\cos(\theta)} @f] * * This is because the two rotation matrices in this decomposition have determinants equal to 1. * * Let @f$ n = \text{Detector\;\;Resolution} @f$ * * Then: * * @f[ Area = n^2 |A| =\frac{n^2}{cos(\theta)}@f] * * And: * * @f[ \text{Local\;\;Detector\;\; Resolution} = \frac{n}{\sqrt{cos(\theta)}} @f] * * * This method returns the Local Detector Resolution if the Look Vector intersects the target * and if @f$ 0 \leq \theta < \frac{\pi}{2} @f$ and -1.0 otherwise. * * * * * Reference 1: J-M Morel and G. Yu, "Asift: A new framework for fully affine * invariant image comparison," SIAM Journal on Imaging Sciences * 2(2), pp. 438-469, 2009 * * * @return @b double */ double Camera::ObliqueDetectorResolution(){ if(HasSurfaceIntersection()){ double thetaRad; double sB[3]; instrumentPosition(sB); double pB[3]; Coordinate(pB); double a = sB[0] - pB[0]; double b = sB[1] - pB[1]; double c = sB[2] - pB[2]; double rho = sqrt(a * a + b * b + c * c) * 1000.0; thetaRad = EmissionAngle()*DEG2RAD; if (thetaRad < HALFPI) { double nadirResolution = rho/(p_focalLength/p_pixelPitch); return nadirResolution/sqrt(cos(thetaRad)); } return Isis::Null; } return Isis::Null; } /** * Returns the detector resolution at the current position * @brief Returns the detector resolution at the current position in meters. * * @return @b double The detector resolution */ Loading @@ -480,17 +585,31 @@ namespace Isis { return Isis::Null; } /** * Returns the sample resolution at the current position * @brief Returns the sample resolution at the current position in meters. * * @return @b double The sample resolution */ double Camera::SampleResolution() { return DetectorResolution() * p_detectorMap->SampleScaleFactor(); } /** * Returns the line resolution at the current position * @brief Returns the oblique sample resolution at the current position in m. This gives * a more accurate estimate of the sample resolution at oblique angles. * * @return @b double The sample resolution */ double Camera::ObliqueSampleResolution() { return ObliqueDetectorResolution() * p_detectorMap->SampleScaleFactor(); } /** * @brief Returns the line resolution at the current position in meters. * * @return @b double The line resolution */ Loading @@ -498,9 +617,22 @@ namespace Isis { return DetectorResolution() * p_detectorMap->LineScaleFactor(); } /** * Returns the pixel resolution at the current position in m/pix * @brief Returns the oblique line resolution at the current position in meters. This * provides a more accurate estimate of the line resolution at oblique * angles. * * @return @b double The line resolution */ double Camera::ObliqueLineResolution() { return ObliqueDetectorResolution() * p_detectorMap->LineScaleFactor(); } /** * @brief Returns the pixel resolution at the current position in meters/pixel. * @return @b double The pixel resolution */ double Camera::PixelResolution() { Loading @@ -511,8 +643,24 @@ namespace Isis { return (lineRes + sampRes) / 2.0; } /** * Returns the lowest/worst resolution in the entire image * @brief Returns the oblique pixel resolution at the current position in meters/pixel. This * provides a more accurate estimate of the pixel resolution at oblique angles. * * @return @b double The pixel resolution */ double Camera::ObliquePixelResolution() { double lineRes = ObliqueLineResolution(); double sampRes = ObliqueSampleResolution(); if (lineRes < 0.0) return Isis::Null; if (sampRes < 0.0) return Isis::Null; return (lineRes + sampRes) / 2.0; } /** * @brief Returns the lowest/worst resolution in the entire image * * @return @b double The lowest/worst resolution in the image */ Loading @@ -521,8 +669,9 @@ namespace Isis { return p_maxres; } /** * Returns the highest/best resolution in the entire image * @brief Returns the highest/best resolution in the entire image * * @return @b double The highest/best resolution in the entire image */ Loading @@ -531,8 +680,31 @@ namespace Isis { return p_minres; } /** * Computes the ground range and min/max resolution * @brief Returns the lowest/worst oblique resolution in the entire image * * @return @b double The lowest/worst oblique resolution in the image */ double Camera::LowestObliqueImageResolution() { GroundRangeResolution(); return p_minobliqueres; } /** * @brief Returns the highest/best oblique resolution in the entire image * * @return @b double The highest/best oblique resolution in the entire image */ double Camera::HighestObliqueImageResolution() { GroundRangeResolution(); return p_maxobliqueres; } /** * @brief Computes the ground range and min/max resolution */ void Camera::GroundRangeResolution() { // Software adjustment is needed if we get here -- call RingRangeResolution instead Loading Loading @@ -560,6 +732,8 @@ namespace Isis { p_maxlon180 = -DBL_MAX; p_minres = DBL_MAX; p_maxres = -DBL_MAX; p_minobliqueres = DBL_MAX; p_maxobliqueres = -DBL_MAX; // See if we have band dependence and loop for the appropriate number of bands int eband = p_bands; Loading Loading @@ -591,6 +765,13 @@ namespace Isis { if (res < p_minres) p_minres = res; if (res > p_maxres) p_maxres = res; } // Determine min/max oblique resolution double obliqueres = ObliquePixelResolution(); if (obliqueres > 0.0) { if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres; if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres; } if ((line != 1) && (line != p_lines + 1)) break; } } // end loop through samples Loading Loading @@ -619,6 +800,14 @@ namespace Isis { if (res < p_minres) p_minres = res; if (res > p_maxres) p_maxres = res; } // Determine min/max oblique resolution double obliqueres = ObliquePixelResolution(); if (obliqueres > 0.0) { if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres; if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres; } break; } } Loading Loading @@ -648,6 +837,13 @@ namespace Isis { if (res < p_minres) p_minres = res; if (res > p_maxres) p_maxres = res; } double obliqueres = ObliquePixelResolution(); if (obliqueres > 0.0) { if (obliqueres < p_minobliqueres) p_minobliqueres = obliqueres; if (obliqueres > p_maxobliqueres) p_maxobliqueres = obliqueres; } } } } // end valid local (subspacecraft) radius Loading Loading @@ -738,7 +934,9 @@ namespace Isis { // Checks for invalid lat/lon ranges // if(p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX || p_maxlat == -DBL_MAX) { // if(p_minlon == DBL_MAX || p_minlat == DBL_MAX || p_maxlon == -DBL_MAX // || p_maxlat == -DBL_MAX) // { // string message = "Camera missed planet or SPICE data off."; // throw IException(IException::Unknown, message, _FILEINFO_); // } Loading @@ -746,7 +944,7 @@ namespace Isis { /** * Analogous to above GroundRangeResolution method. Computes the ring range * @brief Analogous to above GroundRangeResolution method. Computes the ring range * and min/max resolution */ void Camera::ringRangeResolution() { Loading Loading @@ -916,7 +1114,8 @@ namespace Isis { } // Checks for invalid radius/lon ranges if (p_minRingRadius == DBL_MAX || p_minRingRadius == DBL_MAX || p_minRingLongitude == DBL_MAX || p_maxRingLongitude == -DBL_MAX) { if (p_minRingRadius == DBL_MAX || p_minRingRadius == DBL_MAX || p_minRingLongitude == DBL_MAX || p_maxRingLongitude == -DBL_MAX) { string message = "RingPlane ShapeModel - Camera missed plane or SPICE data off."; throw IException(IException::Unknown, message, _FILEINFO_); } Loading Loading @@ -1152,7 +1351,8 @@ namespace Isis { * @param pvl Pvl to write mapping group to */ void Camera::basicRingMapping(Pvl &pvl) { if (target()->shape()->name() != "Plane") { // If we get here and we don't have a plane, throw an error if (target()->shape()->name() != "Plane") { // If we get here and we don't have a plane, throw an error IString msg = "A ring plane projection has been requested on an image whose shape is not a ring plane. "; msg += "Rerun spiceinit with shape=RINGPLANE. "; throw IException(IException::User, msg, _FILEINFO_); Loading Loading @@ -1189,6 +1389,8 @@ namespace Isis { SetPixelPitch(Spice::getDouble(key)); } /** * Sets the right ascension declination * Loading Loading @@ -1456,6 +1658,8 @@ namespace Isis { // angle (in radians) incidence = Angle(vsep_c(unitizedSurfSunVect, normal), Angle::Radians); } Loading @@ -1466,12 +1670,13 @@ namespace Isis { * @param maxra Maximum right ascension value * @param mindec Minimum declination value * @param maxdec Maximum declination value * * @return @b bool Returns true if the range computation was successful and false * if it was not */ bool Camera::RaDecRange(double &minra, double &maxra, double &mindec, double &maxdec) { bool computed = p_pointComputed; double originalSample = Sample(); double originalLine = Line(); Loading Loading @@ -1611,6 +1816,7 @@ namespace Isis { * @return @b double The resutant RaDec resolution */ double Camera::RaDecResolution() { bool computed = p_pointComputed; double originalSample = Sample(); double originalLine = Line(); Loading Loading @@ -1687,7 +1893,6 @@ namespace Isis { return ComputeAzimuth(LocalRadius(lat, lon), lat, lon); } /** * Return the Spacecraft Azimuth * Loading @@ -1701,7 +1906,6 @@ namespace Isis { return ComputeAzimuth(LocalRadius(lat, lon), lat, lon); } /** * Computes the image azimuth value from your current position (origin) to a point of interest * specified by the lat/lon input to this method. (NOTE: This azimuth is different from a Ground Loading Loading @@ -1952,7 +2156,6 @@ namespace Isis { return azimuth; } /** * Return the off nadir angle in degrees. * Loading @@ -1978,7 +2181,6 @@ namespace Isis { return c; } /** * Computes and returns the ground azimuth between the ground point and * another point of interest, such as the subspacecraft point or the Loading Loading @@ -2106,7 +2308,6 @@ namespace Isis { p_distortionMap = map; } /** * Sets the Focal Plane Map. This object will take ownership of the focal plane * map pointer. Loading @@ -2121,7 +2322,6 @@ namespace Isis { p_focalPlaneMap = map; } /** * Sets the Detector Map. This object will take ownership of the detector map * pointer. Loading @@ -2136,7 +2336,6 @@ namespace Isis { p_detectorMap = map; } /** * Sets the Ground Map. This object will take ownership of the ground map * pointer. Loading @@ -2151,7 +2350,6 @@ namespace Isis { p_groundMap = map; } /** * Sets the Sky Map. This object will take ownership of the sky map pointer. * Loading @@ -2165,7 +2363,6 @@ namespace Isis { p_skyMap = map; } /** * This loads the spice cache big enough for this image. The default cache size * is the number of lines in the cube if the ephemeris time changes in the Loading Loading @@ -2261,7 +2458,6 @@ namespace Isis { return ephemerisTimes; } /** * This method calculates the spice cache size. This method finds the number * of lines in the beta cube and adds 1, since we need at least 2 points for Loading Loading @@ -2346,7 +2542,6 @@ namespace Isis { p_geometricTilingEndSize = endSize; } /** * This will get the geometric tiling hint; these values are typically used for * ProcessRubberSheet::SetTiling(...). Loading Loading @@ -2380,7 +2575,6 @@ namespace Isis { return true; } /** * Checks to see if the camera object has a projection * Loading @@ -2391,7 +2585,6 @@ namespace Isis { return p_projection != 0; } /** * Virtual method that checks if the band is independent * Loading @@ -2402,7 +2595,6 @@ namespace Isis { return true; } /** * Returns the reference band * Loading @@ -2412,7 +2604,6 @@ namespace Isis { return p_referenceBand; } /** * Checks to see if the Camera object has a reference band * Loading @@ -2423,7 +2614,6 @@ namespace Isis { return p_referenceBand != 0; } /** * Virtual method that sets the band number * Loading @@ -2433,7 +2623,6 @@ namespace Isis { p_childBand = band; } /** * Returns the current sample number * Loading @@ -2443,7 +2632,6 @@ namespace Isis { return p_childSample; } /** * Returns the current band * Loading @@ -2453,7 +2641,6 @@ namespace Isis { return p_childBand; } /** * Returns the current line number * Loading @@ -2462,8 +2649,6 @@ namespace Isis { double Camera::Line() { return p_childLine; } /** * Returns the resolution of the camera * Loading @@ -2474,6 +2659,8 @@ namespace Isis { } /** * Returns the focal length * Loading @@ -2483,7 +2670,6 @@ namespace Isis { return p_focalLength; } /** * Returns the pixel pitch * Loading @@ -2493,7 +2679,6 @@ namespace Isis { return p_pixelPitch; } /** * Returns the pixel ifov offsets from center of pixel, which defaults to the * (pixel pitch * summing mode ) / 2. If an instrument has a non-square ifov, it must implement Loading Loading @@ -2525,7 +2710,6 @@ namespace Isis { return p_samples; } /** * Returns the number of lines in the image * Loading @@ -2535,7 +2719,6 @@ namespace Isis { return p_lines; } /** * Returns the number of bands in the image * Loading @@ -2545,7 +2728,6 @@ namespace Isis { return p_bands; } /** * Returns the number of lines in the parent alphacube * Loading @@ -2555,7 +2737,6 @@ namespace Isis { return p_alphaCube->AlphaLines(); } /** * Returns the number of samples in the parent alphacube * Loading @@ -2564,8 +2745,6 @@ namespace Isis { int Camera::ParentSamples() const { return p_alphaCube->AlphaSamples(); } /** * Returns a pointer to the CameraDistortionMap object * Loading @@ -2575,7 +2754,6 @@ namespace Isis { return p_distortionMap; } /** * Returns a pointer to the CameraFocalPlaneMap object * Loading @@ -2585,7 +2763,6 @@ namespace Isis { return p_focalPlaneMap; } /** * Returns a pointer to the CameraDetectorMap object * Loading @@ -2595,7 +2772,6 @@ namespace Isis { return p_detectorMap; } /** * Returns a pointer to the CameraGroundMap object * Loading @@ -2605,7 +2781,6 @@ namespace Isis { return p_groundMap; } /** * Returns a pointer to the CameraSkyMap object * Loading Loading @@ -2794,3 +2969,4 @@ namespace Isis { // end namespace isis }
isis/src/base/objs/Camera/Camera.h +78 −68 Original line number Diff line number Diff line Loading @@ -213,15 +213,15 @@ namespace Isis { * @history 2015-10-16 Ian Humphrey - Added protected members for spacecraft and instrument * names as well as public member getters. Updated unit test. * References #2335. * @history 2015-09-01 Ian Humphrey and Makayla Shepherd - Modified unit test to override * Sensor's pure virtual methods. * @history 2015-10-16 Ian Humphrey - Added protected members for spacecraft and instrument * names as well as public member getters. Updated unit test. * References #2335. * @history 2016-06-27 Kelvin Rodriguez - Added member function to compute celestial north * clock angle. References #2365 * @history 2016-08-01 Curtis Rose - Changed return values of resolutions from -1 to Isis::Null. * Fixes #2065. * @history 2016-08-16 Tyler Wilson - Added ObliqueDectectorResolution,ObliqueLineResolution, * ObliqueSampleResolution, and ObliquePixelResolution functions * which give greatly improved approximations compared to their * non-oblique counterpart functions when the Look vector is pointing * off nadir and near the limb. Fixes #476. References #4100. */ class Camera : public Sensor { Loading Loading @@ -267,9 +267,17 @@ namespace Isis { double SampleResolution(); double DetectorResolution(); double ObliqueDetectorResolution(); double ObliqueSampleResolution(); double ObliqueLineResolution(); double ObliquePixelResolution(); virtual double resolution(); double LowestImageResolution(); double HighestImageResolution(); double LowestObliqueImageResolution(); double HighestObliqueImageResolution(); void BasicMapping(Pvl &map); void basicRingMapping(Pvl &map); Loading @@ -288,7 +296,6 @@ namespace Isis { bool RaDecRange(double &minra, double &maxra, double &mindec, double &maxdec); double RaDecResolution(); CameraDistortionMap *DistortionMap(); Loading Loading @@ -483,6 +490,8 @@ namespace Isis { double p_maxlon; //!< The maximum longitude double p_minres; //!< The minimum resolution double p_maxres; //!< The maximum resolution double p_minobliqueres; //!< The minimum oblique resolution double p_maxobliqueres; //!< The maximum oblique resolution double p_minlon180; //!< The minimum longitude in the 180 domain double p_maxlon180; //!< The maximum longitude in the 180 domain bool p_groundRangeComputed; /**!< Flag showing if ground range Loading Loading @@ -520,7 +529,7 @@ namespace Isis { AlphaCube *p_alphaCube; //!< A pointer to the AlphaCube double p_childSample; //!< Sample value for child double p_childLine; //!< Line value for child int p_childBand; //!< Band value for child. Should be the virtual band not original band. int p_childBand; //!< Band value for child CameraDistortionMap *p_distortionMap; //!< A pointer to the DistortionMap CameraFocalPlaneMap *p_focalPlaneMap; //!< A pointer to the FocalPlaneMap CameraDetectorMap *p_detectorMap; //!< A pointer to the DetectorMap Loading @@ -540,3 +549,4 @@ namespace Isis { }; #endif
isis/src/base/objs/Camera/Camera.truth +4 −0 Original line number Diff line number Diff line Loading @@ -47,9 +47,13 @@ Line: 962 GroundRange: 0 IntersectsLongitudeDomain: 0 PixelResolution: 628 ObliquePixelResolution: 685 LineResolution: 628 ObliqueLineResolution: 685 SampleResolution: 628 ObliqueSampleResolution: 685 DetectorResolution: 157 ObliqueDetectorResolution: 171 LowestImageResolution: 2047 HighestImageResolution: 430 Calling BasicMapping (pvl)... Loading
isis/src/base/objs/Camera/unitTest.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -162,9 +162,15 @@ int main() { } cout << "PixelResolution: " << c->PixelResolution() << endl; cout << "ObliquePixelResolution: " << c->ObliquePixelResolution() << endl; cout << "LineResolution: " << c->LineResolution() << endl; cout << "ObliqueLineResolution: " << c->ObliqueLineResolution() << endl; cout << "SampleResolution: " << c->SampleResolution() << endl; cout << "ObliqueSampleResolution: " << c->ObliqueSampleResolution() << endl; cout << "DetectorResolution: " << c->DetectorResolution() << endl; cout << "ObliqueDetectorResolution: " << c->ObliqueDetectorResolution() << endl; cout << "LowestImageResolution: " << setprecision(4) << c->LowestImageResolution() << endl; cout << "HighestImageResolution: " << setprecision(3) Loading