USGS

Isis 3.0 Object Programmers' Reference

Home

Sensor.cpp

Go to the documentation of this file.
00001 
00023 #include "Sensor.h"
00024 
00025 #include <QDebug>
00026 
00027 #include <iomanip>
00028 
00029 #include "Angle.h"
00030 #include "Constants.h"
00031 #include "CubeManager.h"
00032 #include "Distance.h"
00033 #include "EllipsoidShape.h"
00034 #include "IException.h"
00035 #include "IString.h"
00036 #include "iTime.h"
00037 #include "Latitude.h"
00038 #include "Longitude.h"
00039 #include "NaifStatus.h"
00040 #include "Projection.h"
00041 #include "ShapeModel.h"
00042 #include "SpecialPixel.h"
00043 #include "SurfacePoint.h"
00044 #include "Target.h"
00045 #include "UniqueIOCachingAlgorithm.h"
00046 
00047 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
00048 
00049 using namespace std;
00050 
00051 namespace Isis {
00052 
00060   Sensor::Sensor(Pvl &lab) : Spice(lab) {
00061   }
00062 
00064   Sensor::~Sensor() {
00065   }
00066 
00067 
00073   void Sensor::IgnoreElevationModel(bool ignore) {
00074     // if we have an elevation model and are not ignoring it,
00075     //   set p_hasElevationModel to true
00076     if (!ignore) {
00077       target()->restoreShape();
00078     }
00079     else {
00080       target()->setShapeEllipsoid();
00081     }
00082   }
00083 
00084 
00094   void Sensor::setTime(const iTime &time) {
00095     Spice::setTime(time);
00096     target()->shape()->clearSurfacePoint();
00097   }
00098 
00136   bool Sensor::SetLookDirection(const double v[3]) {
00137     // The look vector must be in the camera coordinate system
00138 
00139     // copy v to LookC
00140     // lookC[0] = v[0];
00141     // lookC[1] = v[1];
00142     // lookC[2] = v[2];
00143     vector<double> lookC(v, v + 3);
00144 
00145     // Convert it to body-fixed
00146     const vector<double> &lookJ = instrumentRotation()->J2000Vector(lookC);
00147     const vector<double> &lookB = bodyRotation()->ReferenceVector(lookJ);
00148 
00149     // This memcpy does:
00150     // m_lookB[0] = lookB[0];
00151     // m_lookB[1] = lookB[1];
00152     // m_lookB[2] = lookB[2];
00153     memcpy(m_lookB, &lookB[0], sizeof(double) * 3);
00154     m_newLookB = true;
00155 
00156     // Don't try to intersect the sky
00157     if (target()->isSky()) {
00158       target()->shape()->setHasIntersection(false);
00159       return false;
00160     }
00161 
00162     // See if it intersects the planet
00163     const vector<double> &sB = bodyRotation()->ReferenceVector(
00164         instrumentPosition()->Coordinate());
00165 
00166     // double tolerance = resolution() / 100.0; return
00167     // target()->shape()->intersectSurface(sB, lookB, tolerance);
00168     return target()->shape()->intersectSurface(sB, lookB);
00169   }
00170 
00180   bool Sensor::HasSurfaceIntersection() const {
00181     return target()->shape()->hasIntersection();
00182   }
00183 
00184 
00190   void Sensor::Coordinate(double p[3]) const {
00191     ShapeModel *shape = target()->shape();
00192     p[0] = shape->surfaceIntersection()->GetX().kilometers();
00193     p[1] = shape->surfaceIntersection()->GetY().kilometers();
00194     p[2] = shape->surfaceIntersection()->GetZ().kilometers();
00195   }
00196 
00203   double Sensor::UniversalLatitude() const {
00204     return target()->shape()->surfaceIntersection()->GetLatitude().degrees();
00205   }
00206 
00207 
00211   Latitude Sensor::GetLatitude() const {
00212     return target()->shape()->surfaceIntersection()->GetLatitude();
00213   }
00214 
00215 
00222   double Sensor::UniversalLongitude() const {
00223     return target()->shape()->surfaceIntersection()->GetLongitude().degrees();
00224   }
00225 
00226 
00230   Longitude Sensor::GetLongitude() const {
00231     return target()->shape()->surfaceIntersection()->GetLongitude();
00232   }
00233 
00237   SurfacePoint Sensor::GetSurfacePoint() const {
00238     return *(target()->shape()->surfaceIntersection());
00239   }
00240 
00241 
00247   Distance Sensor::LocalRadius() const {
00248     //TODO: We probably need to be validating surface intersect point is not NULL
00249     // Here? or in ShapeModel? or what, man?
00250     return target()->shape()->surfaceIntersection()->GetLocalRadius();
00251   }
00252 
00253 
00262   Distance Sensor::LocalRadius(Latitude lat, Longitude lon) {
00263     return target()->shape()->localRadius(lat, lon); 
00264   }
00265 
00266 
00275   Distance Sensor::LocalRadius(double lat, double lon) {
00276     return target()->shape()->localRadius(Latitude(lat, Angle::Degrees),
00277                                 Longitude(lon, Angle::Degrees));
00278   }
00279 
00285   double Sensor::PhaseAngle() const {
00286     std::vector<double> sunB(m_uB, m_uB+3);
00287     return target()->shape()->phaseAngle(
00288                                bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()), sunB);
00289   }
00290 
00291 
00297   double Sensor::EmissionAngle() const {
00298     return target()->shape()->emissionAngle(
00299         bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()));
00300   }
00301 
00302 
00308   double Sensor::IncidenceAngle() const {
00309     std::vector<double> sunB(m_uB, m_uB+3);
00310     return target()->shape()->incidenceAngle(sunB);
00311   }
00312 
00328   bool Sensor::SetUniversalGround(const double latitude,
00329                                   const double longitude, bool backCheck) {
00330 
00331     ShapeModel *shape = target()->shape();
00332     shape->clearSurfacePoint();
00333 
00334     // Can't intersect the sky
00335     if (target()->isSky()) {
00336       return false;
00337     }
00338 
00339     // Load the latitude/longitude
00340     Latitude lat(latitude, Angle::Degrees);
00341     Longitude lon(longitude, Angle::Degrees);
00342     shape->surfaceIntersection()->SetSpherical(lat, lon, LocalRadius(lat, lon));
00343     return SetGroundLocal(backCheck);
00344   }
00345 
00362   bool Sensor::SetUniversalGround(const double latitude,
00363                                   const double longitude,
00364                                   const double radius, bool backCheck) {
00365 
00366     ShapeModel *shape = target()->shape();
00367     shape->clearSurfacePoint();
00368 
00369    // Can't intersect the sky
00370     if (target()->isSky()) {
00371       return false;
00372     }
00373 
00374     Latitude lat(latitude, Angle::Degrees);
00375     Longitude lon(longitude, Angle::Degrees);
00376     Distance rad(radius, Distance::Meters);
00377     shape->surfaceIntersection()->SetSpherical(lat, lon, rad);
00378 
00379     return SetGroundLocal(backCheck);
00380   }
00381 
00382 
00396   bool Sensor::SetGround(const SurfacePoint &surfacePt, bool backCheck) {
00397     ShapeModel *shape = target()->shape();
00398     shape->clearSurfacePoint();
00399 
00400     // Can't intersect the sky
00401     if (target()->isSky()) {
00402       return false;
00403     }
00404 
00405     shape->setSurfacePoint(surfacePt);
00406 
00407     return SetGroundLocal(backCheck);
00408   }
00409 
00422   bool Sensor::SetGroundLocal(bool backCheck) {
00423     ShapeModel *shape = target()->shape();
00424     // With the 3 spherical value compute the x/y/z coordinate
00425     //latrec_c(m_radius, (m_longitude * PI / 180.0), (m_latitude * PI / 180.0), m_pB);
00426 
00427 
00428     if (!(shape->surfaceIntersection()->Valid())) {
00429       return false;
00430     }
00431 
00432     // Make sure the point isn't on the backside of the body
00433 
00434     // This is static purely for performance reasons. A significant speedup
00435     // is achieved here.
00436     const vector<double> &sB =
00437         bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate());
00438 
00439     m_lookB[0] = shape->surfaceIntersection()->GetX().kilometers() - sB[0];
00440     m_lookB[1] = shape->surfaceIntersection()->GetY().kilometers() - sB[1];
00441     m_lookB[2] = shape->surfaceIntersection()->GetZ().kilometers() - sB[2];
00442     m_newLookB = true;
00443 
00444     // See if the point is on the backside of the target
00445 
00446     if (backCheck) {
00447       // Assume the intersection point is good in order to get the emission angle
00448       shape->setHasIntersection(true);
00449       if (fabs(shape->emissionAngle(sB)) > 90.) {
00450         shape->clearSurfacePoint();
00451         shape->setHasIntersection(false);
00452         return false;
00453       }
00454     }
00455 
00456     // return with success
00457     shape->setHasIntersection(true);
00458     
00459     return true;
00460   }
00461 
00462 
00463 
00469   void Sensor::LookDirection(double v[3]) const {
00470     vector<double> lookB(3);
00471     lookB[0] = m_lookB[0];
00472     lookB[1] = m_lookB[1];
00473     lookB[2] = m_lookB[2];
00474     vector<double> lookJ = bodyRotation()->J2000Vector(lookB);
00475     vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
00476     v[0] = lookC[0];
00477     v[1] = lookC[1];
00478     v[2] = lookC[2];
00479   }
00480 
00484   double Sensor::RightAscension() {
00485     if (m_newLookB) computeRaDec();
00486     return m_ra;
00487   }
00488 
00493   double Sensor::Declination() {
00494     if (m_newLookB) computeRaDec();
00495     return m_dec;
00496   }
00497 
00501   void Sensor::computeRaDec() {
00502     m_newLookB = false;
00503     vector<double> lookB(3);
00504     lookB[0] = m_lookB[0];
00505     lookB[1] = m_lookB[1];
00506     lookB[2] = m_lookB[2];
00507     vector<double> lookJ = bodyRotation()->J2000Vector(lookB);;
00508 
00509     SpiceDouble range;
00510     recrad_c((SpiceDouble *)&lookJ[0], &range, &m_ra, &m_dec);
00511     m_ra *= 180.0 / PI;
00512     m_dec *= 180.0 / PI;
00513   }
00514 
00523   bool Sensor::SetRightAscensionDeclination(const double ra, const double dec) {
00524     vector<double> lookJ(3);
00525     radrec_c(1.0, ra * PI / 180.0, dec * PI / 180.0, (SpiceDouble *)&lookJ[0]);
00526 
00527     vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
00528     return SetLookDirection((double *)&lookC[0]);
00529   }
00530 
00531 
00537   void Sensor::SpacecraftSurfaceVector(double scSurfaceVector[3]) const {
00538     scSurfaceVector[0] = m_lookB[0];
00539     scSurfaceVector[1] = m_lookB[1];
00540     scSurfaceVector[2] = m_lookB[2];
00541   }
00542 
00543 
00544 
00549   double Sensor::SlantDistance() const {
00550     SpiceDouble psB[3], upsB[3];
00551     SpiceDouble dist;
00552 
00553     std::vector<double> sB = bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate());
00554 
00555     SpiceDouble pB[3];
00556     ShapeModel *shape = target()->shape();
00557     pB[0] = shape->surfaceIntersection()->GetX().kilometers();
00558     pB[1] = shape->surfaceIntersection()->GetY().kilometers();
00559     pB[2] = shape->surfaceIntersection()->GetZ().kilometers();
00560 
00561     vsub_c(pB, (SpiceDouble *) &sB[0], psB);
00562     unorm_c(psB, upsB, &dist);
00563     return dist;
00564   }
00565 
00570   double Sensor::LocalSolarTime() {
00571     double slat, slon;
00572     subSolarPoint(slat, slon);
00573 
00574     double lst = UniversalLongitude() - slon + 180.0;
00575     lst = lst / 15.0;  // 15 degress per hour
00576     if (lst < 0.0) lst += 24.0;
00577     if (lst > 24.0) lst -= 24.0;
00578     return lst;
00579   }
00580 
00585   double Sensor::SolarDistance() const {
00586     // Get the sun coord
00587     double sB[3];
00588     Spice::sunPosition(sB);
00589 
00590     // Calc the change
00591     ShapeModel *shape = target()->shape();
00592     double xChange = sB[0] - shape->surfaceIntersection()->GetX().kilometers();
00593     double yChange = sB[1] - shape->surfaceIntersection()->GetY().kilometers();
00594     double zChange = sB[2] - shape->surfaceIntersection()->GetZ().kilometers();
00595 
00596     // Calc the distance and convert to AU
00597     double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
00598     dist /= 149597870.691;
00599     return dist;
00600   }
00601 
00602 
00608   double Sensor::SpacecraftAltitude() {
00609     // Get the spacecraft coord
00610     double spB[3];
00611     Spice::instrumentPosition(spB);
00612 
00613     // Get subspacecraft point
00614     double lat, lon;
00615     subSpacecraftPoint(lat, lon);
00616     double rlat = lat * PI / 180.0;
00617     double rlon = lon * PI / 180.0;
00618 
00619     // Compute radius
00620     Distance rad = LocalRadius(lat, lon);
00621 
00622     // Now with the 3 spherical value compute the x/y/z coordinate
00623     double ssB[3];
00624     latrec_c(rad.kilometers(), rlon, rlat, ssB);
00625 
00626     // Calc the change
00627     double xChange = spB[0] - ssB[0];
00628     double yChange = spB[1] - ssB[1];
00629     double zChange = spB[2] - ssB[2];
00630 
00631     // Calc the distance
00632     double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
00633     return dist;
00634   }
00635 
00636 
00642 //  Distance Sensor::DemRadius(const SurfacePoint &pt) {
00643 //    return DemRadius(pt.GetLatitude(), pt.GetLongitude());
00644 //  }
00645 
00646 
00653 //  Distance Sensor::DemRadius(const Latitude &lat, const Longitude &lon) {
00654 //    if (!m_hasElevationModel) return Distance();
00655 //    //if (!lat.Valid() || !lon.Valid()) return Distance();
00656 //    m_demProj->SetUniversalGround(lat.degrees(), lon.degrees());
00657 //    if (!m_demProj->IsGood()) {
00658 //      return Distance();
00659 //    }
00660 
00661 //    m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
00662 
00663 //    m_demCube->read(*m_portal);
00664 
00665 //    const double &radius = m_interp->Interpolate(m_demProj->WorldX(),
00666 //                                                 m_demProj->WorldY(),
00667 //                                                 m_portal->DoubleBuffer());
00668 
00669 //    return Distance(radius, Distance::Meters);
00670 //      Distance fred;
00671 //      return fred;
00672 //  }
00673 
00674 
00685 //  double Sensor::DemRadius(double lat, double lon) {
00686 //    if (!m_demProj->SetUniversalGround(lat, lon)) {
00687 //      return Isis::Null;
00688 //    }
00689 
00690 //    m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
00691 //    m_demCube->read(*m_portal);
00692 
00693 //    double radius = m_interp->Interpolate(m_demProj->WorldX(),
00694 //                                          m_demProj->WorldY(),
00695 //                                          m_portal->DoubleBuffer());
00696 //    if (Isis::IsSpecial(radius)) {
00697 //      return Isis::Null;
00698 //    }
00699 
00700 //    return radius / 1000.0;
00701 //      double fred;
00702 //      return fred;
00703 //  }
00710 //   bool HasElevationModel() {
00711 //     return m_hasElevationModel;
00712 //   };
00713 
00714 }