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 
66  }
67 
68 
74  void Sensor::IgnoreElevationModel(bool ignore) {
75  // if we have an elevation model and are not ignoring it,
76  // set p_hasElevationModel to true
77  if (!ignore) {
78  target()->restoreShape();
79  }
80  else {
82  }
83  }
84 
85 
96 
97  QString message = "Pixel Ifov offsets not implemented for this camera.";
99  }
100 
101 
111  void Sensor::setTime(const iTime &time) {
112  Spice::setTime(time);
114  }
115 
153  bool Sensor::SetLookDirection(const double v[3]) {
154  // The look vector must be in the camera coordinate system
155 
156  // copy v to LookC
157  // lookC[0] = v[0];
158  // lookC[1] = v[1];
159  // lookC[2] = v[2];
160  vector<double> lookC(v, v + 3);
161 
162  // Convert it to body-fixed
163  const vector<double> &lookJ = instrumentRotation()->J2000Vector(lookC);
164  const vector<double> &lookB = bodyRotation()->ReferenceVector(lookJ);
165 
166  // This memcpy does:
167  // m_lookB[0] = lookB[0];
168  // m_lookB[1] = lookB[1];
169  // m_lookB[2] = lookB[2];
170  memcpy(m_lookB, &lookB[0], sizeof(double) * 3);
171  m_newLookB = true;
172 
173  // Don't try to intersect the sky
174  if (target()->isSky()) {
175  target()->shape()->setHasIntersection(false);
176  return false;
177  }
178 
179  // See if it intersects the planet
180  const vector<double> &sB = bodyRotation()->ReferenceVector(
182 
183  // double tolerance = resolution() / 100.0; return
184  // target()->shape()->intersectSurface(sB, lookB, tolerance);
185  return target()->shape()->intersectSurface(sB, lookB);
186  }
187 
198  return target()->shape()->hasIntersection();
199  }
200 
201 
207  void Sensor::Coordinate(double p[3]) const {
208  ShapeModel *shape = target()->shape();
209  p[0] = shape->surfaceIntersection()->GetX().kilometers();
210  p[1] = shape->surfaceIntersection()->GetY().kilometers();
211  p[2] = shape->surfaceIntersection()->GetZ().kilometers();
212  }
213 
220  double Sensor::UniversalLatitude() const {
221  return target()->shape()->surfaceIntersection()->GetLatitude().degrees();
222  }
223 
224 
229  return target()->shape()->surfaceIntersection()->GetLatitude();
230  }
231 
232 
239  double Sensor::UniversalLongitude() const {
241  }
242 
243 
248  return target()->shape()->surfaceIntersection()->GetLongitude();
249  }
250 
255  return *(target()->shape()->surfaceIntersection());
256  }
257 
258 
265  //TODO: We probably need to be validating surface intersect point is not NULL
266  // Here? or in ShapeModel? or what, man?
268  }
269 
270 
280  return target()->shape()->localRadius(lat, lon);
281  }
282 
283 
292  Distance Sensor::LocalRadius(double lat, double lon) {
293  return target()->shape()->localRadius(Latitude(lat, Angle::Degrees),
294  Longitude(lon, Angle::Degrees));
295  }
296 
302  double Sensor::PhaseAngle() const {
303  std::vector<double> sunB(m_uB, m_uB+3);
304  return target()->shape()->phaseAngle(
305  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()), sunB);
306  }
307 
308 
314  double Sensor::EmissionAngle() const {
315  return target()->shape()->emissionAngle(
316  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()));
317  }
318 
319 
325  double Sensor::IncidenceAngle() const {
326  std::vector<double> sunB(m_uB, m_uB+3);
327  return target()->shape()->incidenceAngle(sunB);
328  }
329 
345  bool Sensor::SetUniversalGround(const double latitude,
346  const double longitude, bool backCheck) {
347 
348  ShapeModel *shape = target()->shape();
349  shape->clearSurfacePoint();
350 
351  // Can't intersect the sky
352  if (target()->isSky()) {
353  return false;
354  }
355 
356  // Load the latitude/longitude
357  Latitude lat(latitude, Angle::Degrees);
358  Longitude lon(longitude, Angle::Degrees);
359  shape->surfaceIntersection()->SetSpherical(lat, lon, LocalRadius(lat, lon));
360  return SetGroundLocal(backCheck);
361  }
362 
379  bool Sensor::SetUniversalGround(const double latitude,
380  const double longitude,
381  const double radius, bool backCheck) {
382 
383  ShapeModel *shape = target()->shape();
384  shape->clearSurfacePoint();
385 
386  // Can't intersect the sky
387  if (target()->isSky()) {
388  return false;
389  }
390 
391  Latitude lat(latitude, Angle::Degrees);
392  Longitude lon(longitude, Angle::Degrees);
393  Distance rad(radius, Distance::Meters);
394  shape->surfaceIntersection()->SetSpherical(lat, lon, rad);
395 
396  return SetGroundLocal(backCheck);
397  }
398 
399 
413  bool Sensor::SetGround(const SurfacePoint &surfacePt, bool backCheck) {
414  ShapeModel *shape = target()->shape();
415  shape->clearSurfacePoint();
416 
417  // Can't intersect the sky
418  if (target()->isSky()) {
419  return false;
420  }
421 
422  shape->setSurfacePoint(surfacePt);
423 
424  return SetGroundLocal(backCheck);
425  }
426 
439  bool Sensor::SetGroundLocal(bool backCheck) {
440  ShapeModel *shape = target()->shape();
441  // With the 3 spherical value compute the x/y/z coordinate
442  //latrec_c(m_radius, (m_longitude * PI / 180.0), (m_latitude * PI / 180.0), m_pB);
443 
444 
445  if (!(shape->surfaceIntersection()->Valid())) {
446  return false;
447  }
448 
449  // Make sure the point isn't on the backside of the body
450 
451  // This is static purely for performance reasons. A significant speedup
452  // is achieved here.
453  const vector<double> &sB =
455 
456  m_lookB[0] = shape->surfaceIntersection()->GetX().kilometers() - sB[0];
457  m_lookB[1] = shape->surfaceIntersection()->GetY().kilometers() - sB[1];
458  m_lookB[2] = shape->surfaceIntersection()->GetZ().kilometers() - sB[2];
459  m_newLookB = true;
460 
461  // See if the point is on the backside of the target
462 
463  if (backCheck) {
464  // Assume the intersection point is good in order to get the emission angle
465  shape->setHasIntersection(true);
466  if (fabs(shape->emissionAngle(sB)) > 90.) {
467  shape->clearSurfacePoint();
468  shape->setHasIntersection(false);
469  return false;
470  }
471  }
472 
473  // return with success
474  shape->setHasIntersection(true);
475 
476  return true;
477  }
478 
479 
480 
486  void Sensor::LookDirection(double v[3]) const {
487  vector<double> lookB(3);
488  lookB[0] = m_lookB[0];
489  lookB[1] = m_lookB[1];
490  lookB[2] = m_lookB[2];
491  vector<double> lookJ = bodyRotation()->J2000Vector(lookB);
492  vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
493  v[0] = lookC[0];
494  v[1] = lookC[1];
495  v[2] = lookC[2];
496  }
497 
502  if (m_newLookB) computeRaDec();
503  return m_ra;
504  }
505 
511  if (m_newLookB) computeRaDec();
512  return m_dec;
513  }
514 
519  m_newLookB = false;
520  vector<double> lookB(3);
521  lookB[0] = m_lookB[0];
522  lookB[1] = m_lookB[1];
523  lookB[2] = m_lookB[2];
524  vector<double> lookJ = bodyRotation()->J2000Vector(lookB);;
525 
526  SpiceDouble range;
527  recrad_c((SpiceDouble *)&lookJ[0], &range, &m_ra, &m_dec);
528  m_ra *= 180.0 / PI;
529  m_dec *= 180.0 / PI;
530  }
531 
540  bool Sensor::SetRightAscensionDeclination(const double ra, const double dec) {
541  vector<double> lookJ(3);
542  radrec_c(1.0, ra * PI / 180.0, dec * PI / 180.0, (SpiceDouble *)&lookJ[0]);
543 
544  vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
545  return SetLookDirection((double *)&lookC[0]);
546  }
547 
548 
554  void Sensor::SpacecraftSurfaceVector(double scSurfaceVector[3]) const {
555  scSurfaceVector[0] = m_lookB[0];
556  scSurfaceVector[1] = m_lookB[1];
557  scSurfaceVector[2] = m_lookB[2];
558  }
559 
560 
561 
566  double Sensor::SlantDistance() const {
567  SpiceDouble psB[3], upsB[3];
568  SpiceDouble dist;
569 
570  std::vector<double> sB = bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate());
571 
572  SpiceDouble pB[3];
573  ShapeModel *shape = target()->shape();
574  pB[0] = shape->surfaceIntersection()->GetX().kilometers();
575  pB[1] = shape->surfaceIntersection()->GetY().kilometers();
576  pB[2] = shape->surfaceIntersection()->GetZ().kilometers();
577 
578  vsub_c(pB, (SpiceDouble *) &sB[0], psB);
579  unorm_c(psB, upsB, &dist);
580  return dist;
581  }
582 
588  double slat, slon;
589  subSolarPoint(slat, slon);
590 
591  double lst = UniversalLongitude() - slon + 180.0;
592  lst = lst / 15.0; // 15 degress per hour
593  if (lst < 0.0) lst += 24.0;
594  if (lst > 24.0) lst -= 24.0;
595  return lst;
596  }
597 
602  double Sensor::SolarDistance() const {
603  // Get the sun coord
604  double sB[3];
605  Spice::sunPosition(sB);
606 
607  // Calc the change
608  ShapeModel *shape = target()->shape();
609  double xChange = sB[0] - shape->surfaceIntersection()->GetX().kilometers();
610  double yChange = sB[1] - shape->surfaceIntersection()->GetY().kilometers();
611  double zChange = sB[2] - shape->surfaceIntersection()->GetZ().kilometers();
612 
613  // Calc the distance and convert to AU
614  double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
615  dist /= 149597870.691;
616  return dist;
617  }
618 
619 
626  // Get the spacecraft coord
627  double spB[3];
629 
630  // Get subspacecraft point
631  double lat, lon;
632  subSpacecraftPoint(lat, lon);
633  double rlat = lat * PI / 180.0;
634  double rlon = lon * PI / 180.0;
635 
636  // Compute radius
637  Distance rad = LocalRadius(lat, lon);
638 
639  // Now with the 3 spherical value compute the x/y/z coordinate
640  double ssB[3];
641  latrec_c(rad.kilometers(), rlon, rlat, ssB);
642 
643  // Calc the change
644  double xChange = spB[0] - ssB[0];
645  double yChange = spB[1] - ssB[1];
646  double zChange = spB[2] - ssB[2];
647 
648  // Calc the distance
649  double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
650  return dist;
651  }
652 
653 
659 // Distance Sensor::DemRadius(const SurfacePoint &pt) {
660 // return DemRadius(pt.GetLatitude(), pt.GetLongitude());
661 // }
662 
663 
670 // Distance Sensor::DemRadius(const Latitude &lat, const Longitude &lon) {
671 // if (!m_hasElevationModel) return Distance();
672 // //if (!lat.Valid() || !lon.Valid()) return Distance();
673 // m_demProj->SetUniversalGround(lat.degrees(), lon.degrees());
674 // if (!m_demProj->IsGood()) {
675 // return Distance();
676 // }
677 
678 // m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
679 
680 // m_demCube->read(*m_portal);
681 
682 // const double &radius = m_interp->Interpolate(m_demProj->WorldX(),
683 // m_demProj->WorldY(),
684 // m_portal->DoubleBuffer());
685 
686 // return Distance(radius, Distance::Meters);
687 // Distance fred;
688 // return fred;
689 // }
690 
691 
702 // double Sensor::DemRadius(double lat, double lon) {
703 // if (!m_demProj->SetUniversalGround(lat, lon)) {
704 // return Isis::Null;
705 // }
706 
707 // m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
708 // m_demCube->read(*m_portal);
709 
710 // double radius = m_interp->Interpolate(m_demProj->WorldX(),
711 // m_demProj->WorldY(),
712 // m_portal->DoubleBuffer());
713 // if (Isis::IsSpecial(radius)) {
714 // return Isis::Null;
715 // }
716 
717 // return radius / 1000.0;
718 // double fred;
719 // return fred;
720 // }
727 // bool HasElevationModel() {
728 // return m_hasElevationModel;
729 // };
730 
731 }