USGS

Isis 3.0 Object Programmers' Reference

Home

Sensor.cpp
Go to the documentation of this file.
1 
23 #include "Sensor.h"
24 
25 #include <iomanip>
26 
27 #include <QDebug>
28 #include <QString>
29 
30 #include "Angle.h"
31 #include "Constants.h"
32 #include "CubeManager.h"
33 #include "Distance.h"
34 #include "EllipsoidShape.h"
35 #include "IException.h"
36 #include "IString.h"
37 #include "iTime.h"
38 #include "Latitude.h"
39 #include "Longitude.h"
40 #include "NaifStatus.h"
41 #include "Projection.h"
42 #include "ShapeModel.h"
43 #include "SpecialPixel.h"
44 #include "SurfacePoint.h"
45 #include "Target.h"
47 
48 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
49 
50 using namespace std;
51 
52 namespace Isis {
53 
61  Sensor::Sensor(Cube &cube) : Spice(cube) {
62  }
63 
64 
67  }
68 
69 
75  void Sensor::IgnoreElevationModel(bool ignore) {
76  // if we have an elevation model and are not ignoring it,
77  // set p_hasElevationModel to true
78  if (!ignore) {
79  target()->restoreShape();
80  }
81  else {
83  }
84  }
85 
86 
97 
98  QString message = "Pixel Ifov offsets not implemented for this camera.";
100  }
101 
102 
112  void Sensor::setTime(const iTime &time) {
113  Spice::setTime(time);
115  }
116 
117 
156  bool Sensor::SetLookDirection(const double v[3]) {
157  // The look vector must be in the camera coordinate system
158 
159  // copy v to LookC
160  // lookC[0] = v[0];
161  // lookC[1] = v[1];
162  // lookC[2] = v[2];
163  vector<double> lookC(v, v + 3);
164 
165  // Convert it to body-fixed
166  const vector<double> &lookJ = instrumentRotation()->J2000Vector(lookC);
167  const vector<double> &lookB = bodyRotation()->ReferenceVector(lookJ);
168 
169  // This memcpy does:
170  // m_lookB[0] = lookB[0];
171  // m_lookB[1] = lookB[1];
172  // m_lookB[2] = lookB[2];
173  memcpy(m_lookB, &lookB[0], sizeof(double) * 3);
174  m_newLookB = true;
175 
176  // Don't try to intersect the sky
177  if (target()->isSky()) {
178  target()->shape()->setHasIntersection(false);
179  return false;
180  }
181 
182  // See if it intersects the planet
183  const vector<double> &sB = bodyRotation()->ReferenceVector(
185 
186  // double tolerance = resolution() / 100.0; return
187  // target()->shape()->intersectSurface(sB, lookB, tolerance);
188  return target()->shape()->intersectSurface(sB, lookB);
189  }
190 
191 
201  return target()->shape()->hasIntersection();
202  }
203 
204 
210  void Sensor::Coordinate(double p[3]) const {
211  ShapeModel *shape = target()->shape();
212  p[0] = shape->surfaceIntersection()->GetX().kilometers();
213  p[1] = shape->surfaceIntersection()->GetY().kilometers();
214  p[2] = shape->surfaceIntersection()->GetZ().kilometers();
215  }
216 
217 
224  double Sensor::UniversalLatitude() const {
225  return GetLatitude().degrees();
226  }
227 
228 
236  return target()->shape()->surfaceIntersection()->GetLatitude();
237  }
238 
239 
247  double Sensor::UniversalLongitude() const {
248  return GetLongitude().degrees();
249  }
250 
251 
260  return target()->shape()->surfaceIntersection()->GetLongitude();
261  }
262 
263 
270  return *(target()->shape()->surfaceIntersection());
271  }
272 
273 
282  //TODO: We probably need to be validating surface intersect point is not NULL
283  // Here? or in ShapeModel? or what, man?
285  }
286 
287 
300  return target()->shape()->localRadius(lat, lon);
301  }
302 
303 
315  Distance Sensor::LocalRadius(double lat, double lon) {
316  return target()->shape()->localRadius(Latitude(lat, Angle::Degrees),
317  Longitude(lon, Angle::Degrees));
318  }
319 
320 
326  double Sensor::PhaseAngle() const {
327  std::vector<double> sunB(m_uB, m_uB+3);
328  return target()->shape()->phaseAngle(
329  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()), sunB);
330  }
331 
332 
338  double Sensor::EmissionAngle() const {
339  return target()->shape()->emissionAngle(
340  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()));
341  }
342 
343 
349  double Sensor::IncidenceAngle() const {
350  std::vector<double> sunB(m_uB, m_uB+3);
351  return target()->shape()->incidenceAngle(sunB);
352  }
353 
354 
370  bool Sensor::SetUniversalGround(const double latitude,
371  const double longitude,
372  bool backCheck) {
373 
374  ShapeModel *shape = target()->shape();
375  shape->clearSurfacePoint();
376 
377  // Can't intersect the sky
378  if (target()->isSky()) {
379  return false;
380  }
381 
382  // Load the latitude/longitude
383  Latitude lat(latitude, Angle::Degrees);
384  Longitude lon(longitude, Angle::Degrees);
385  shape->surfaceIntersection()->SetSpherical(lat, lon, LocalRadius(lat, lon));
386  return SetGroundLocal(backCheck);
387  }
388 
405  bool Sensor::SetUniversalGround(const double latitude,
406  const double longitude,
407  const double radius,
408  bool backCheck) {
409 
410  ShapeModel *shape = target()->shape();
411  shape->clearSurfacePoint();
412 
413  // Can't intersect the sky
414  if (target()->isSky()) {
415  return false;
416  }
417 
418  Latitude lat(latitude, Angle::Degrees);
419  Longitude lon(longitude, Angle::Degrees);
420  Distance rad(radius, Distance::Meters);
421  shape->surfaceIntersection()->SetSpherical(lat, lon, rad);
422 
423  return SetGroundLocal(backCheck);
424  }
425 
426 
440  bool Sensor::SetGround(const SurfacePoint &surfacePt, bool backCheck) {
441  ShapeModel *shape = target()->shape();
442  shape->clearSurfacePoint();
443 
444  // Can't intersect the sky
445  if (target()->isSky()) {
446  return false;
447  }
448 
449  shape->setSurfacePoint(surfacePt);
450 
451  return SetGroundLocal(backCheck);
452  }
453 
454 
467  bool Sensor::SetGroundLocal(bool backCheck) {
468  ShapeModel *shape = target()->shape();
469  // With the 3 spherical value compute the x/y/z coordinate
470  //latrec_c(m_radius, (m_longitude * PI / 180.0), (m_latitude * PI / 180.0), m_pB);
471 
472 
473  if (!(shape->surfaceIntersection()->Valid())) {
474  return false;
475  }
476 
477  // Make sure the point isn't on the backside of the body
478 
479  // This is static purely for performance reasons. A significant speedup
480  // is achieved here.
481  const vector<double> &sB =
483 
484  m_lookB[0] = shape->surfaceIntersection()->GetX().kilometers() - sB[0];
485  m_lookB[1] = shape->surfaceIntersection()->GetY().kilometers() - sB[1];
486  m_lookB[2] = shape->surfaceIntersection()->GetZ().kilometers() - sB[2];
487  m_newLookB = true;
488 
489  // See if the point is on the backside of the target
490 
491  if (backCheck) {
492  // Assume the intersection point is good in order to get the emission angle
493  shape->setHasIntersection(true);
494  if (fabs(shape->emissionAngle(sB)) > 90.) {
495  shape->clearSurfacePoint();
496  shape->setHasIntersection(false);
497  return false;
498  }
499  }
500 
501  // return with success
502  shape->setHasIntersection(true);
503 
504  return true;
505  }
506 
507 
513  void Sensor::LookDirection(double v[3]) const {
514  vector<double> lookB(3);
515  lookB[0] = m_lookB[0];
516  lookB[1] = m_lookB[1];
517  lookB[2] = m_lookB[2];
518  vector<double> lookJ = bodyRotation()->J2000Vector(lookB);
519  vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
520  v[0] = lookC[0];
521  v[1] = lookC[1];
522  v[2] = lookC[2];
523  }
524 
525 
532  if (m_newLookB) computeRaDec();
533  return m_ra;
534  }
535 
536 
543  if (m_newLookB) computeRaDec();
544  return m_dec;
545  }
546 
547 
552  m_newLookB = false;
553  vector<double> lookB(3);
554  lookB[0] = m_lookB[0];
555  lookB[1] = m_lookB[1];
556  lookB[2] = m_lookB[2];
557  vector<double> lookJ = bodyRotation()->J2000Vector(lookB);;
558 
559  SpiceDouble range;
560  recrad_c((SpiceDouble *)&lookJ[0], &range, &m_ra, &m_dec);
561  m_ra *= 180.0 / PI;
562  m_dec *= 180.0 / PI;
563  }
564 
565 
574  bool Sensor::SetRightAscensionDeclination(const double ra, const double dec) {
575  vector<double> lookJ(3);
576  radrec_c(1.0, ra * PI / 180.0, dec * PI / 180.0, (SpiceDouble *)&lookJ[0]);
577 
578  vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
579  return SetLookDirection((double *)&lookC[0]);
580  }
581 
582 
591  void Sensor::SpacecraftSurfaceVector(double scSurfaceVector[3]) const {
592  scSurfaceVector[0] = m_lookB[0];
593  scSurfaceVector[1] = m_lookB[1];
594  scSurfaceVector[2] = m_lookB[2];
595  }
596 
597 
603  double Sensor::SlantDistance() const {
604  SpiceDouble psB[3], upsB[3];
605  SpiceDouble dist;
606 
607  std::vector<double> sB = bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate());
608 
609  SpiceDouble pB[3];
610  ShapeModel *shape = target()->shape();
611  pB[0] = shape->surfaceIntersection()->GetX().kilometers();
612  pB[1] = shape->surfaceIntersection()->GetY().kilometers();
613  pB[2] = shape->surfaceIntersection()->GetZ().kilometers();
614 
615  vsub_c(pB, (SpiceDouble *) &sB[0], psB);
616  unorm_c(psB, upsB, &dist);
617  return dist;
618  }
619 
620 
627  double slat, slon;
628  subSolarPoint(slat, slon);
629 
630  double lst = UniversalLongitude() - slon + 180.0;
631  lst = lst / 15.0; // 15 degress per hour
632  if (lst < 0.0) lst += 24.0;
633  if (lst > 24.0) lst -= 24.0;
634  return lst;
635  }
636 
637 
643  double Sensor::SolarDistance() const {
644  // Get the sun coord
645  double sB[3];
646  Spice::sunPosition(sB);
647 
648  // Calc the change
649  ShapeModel *shape = target()->shape();
650  double xChange = sB[0] - shape->surfaceIntersection()->GetX().kilometers();
651  double yChange = sB[1] - shape->surfaceIntersection()->GetY().kilometers();
652  double zChange = sB[2] - shape->surfaceIntersection()->GetZ().kilometers();
653 
654  // Calc the distance and convert to AU
655  double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
656  dist /= 149597870.691;
657  return dist;
658  }
659 
660 
668  // Get the spacecraft coord
669  double spB[3];
671 
672  // Get subspacecraft point
673  double lat, lon;
674  subSpacecraftPoint(lat, lon);
675  double rlat = lat * PI / 180.0;
676  double rlon = lon * PI / 180.0;
677 
678  // Compute radius
679  Distance rad = LocalRadius(lat, lon);
680 
681  // Now with the 3 spherical value compute the x/y/z coordinate
682  double ssB[3];
683  latrec_c(rad.kilometers(), rlon, rlat, ssB);
684 
685  // Calc the change
686  double xChange = spB[0] - ssB[0];
687  double yChange = spB[1] - ssB[1];
688  double zChange = spB[2] - ssB[2];
689 
690  // Calc the distance
691  double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
692  return dist;
693  }
694 
695 
701 // Distance Sensor::DemRadius(const SurfacePoint &pt) {
702 // return DemRadius(pt.GetLatitude(), pt.GetLongitude());
703 // }
704 
705 
712 // Distance Sensor::DemRadius(const Latitude &lat, const Longitude &lon) {
713 // if (!m_hasElevationModel) return Distance();
714 // //if (!lat.Valid() || !lon.Valid()) return Distance();
715 // m_demProj->SetUniversalGround(lat.degrees(), lon.degrees());
716 // if (!m_demProj->IsGood()) {
717 // return Distance();
718 // }
719 
720 // m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
721 
722 // m_demCube->read(*m_portal);
723 
724 // const double &radius = m_interp->Interpolate(m_demProj->WorldX(),
725 // m_demProj->WorldY(),
726 // m_portal->DoubleBuffer());
727 
728 // return Distance(radius, Distance::Meters);
729 // Distance fred;
730 // return fred;
731 // }
732 
733 
744 // double Sensor::DemRadius(double lat, double lon) {
745 // if (!m_demProj->SetUniversalGround(lat, lon)) {
746 // return Isis::Null;
747 // }
748 
749 // m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
750 // m_demCube->read(*m_portal);
751 
752 // double radius = m_interp->Interpolate(m_demProj->WorldX(),
753 // m_demProj->WorldY(),
754 // m_portal->DoubleBuffer());
755 // if (Isis::IsSpecial(radius)) {
756 // return Isis::Null;
757 // }
758 
759 // return radius / 1000.0;
760 // double fred;
761 // return fred;
762 // }
769 // bool HasElevationModel() {
770 // return m_hasElevationModel;
771 // };
772 
773 }