|
Isis 3.0 Object Programmers' Reference |
Home |
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 }