Isis 3.0 Programmer Reference
Back | Home
CameraGroundMap.cpp
Go to the documentation of this file.
1 
23 #include "CameraGroundMap.h"
24 
25 #include <iostream>
26 
27 #include <QDebug>
28 
29 #include <SpiceUsr.h>
30 
31 #include "IException.h"
32 #include "Latitude.h"
33 #include "Longitude.h"
34 #include "NaifStatus.h"
35 #include "SurfacePoint.h"
36 #include "Target.h"
37 
38 using namespace std;
39 
40 namespace Isis {
41 
47  CameraGroundMap::CameraGroundMap(Camera *parent) {
48  p_camera = parent;
49  p_camera->SetGroundMap(this);
50  }
51 
52 
66  bool CameraGroundMap::SetFocalPlane(const double ux, const double uy, const double uz) {
67  NaifStatus::CheckErrors();
68 
69  SpiceDouble lookC[3];
70  lookC[0] = ux;
71  lookC[1] = uy;
72  lookC[2] = uz;
73 
74  SpiceDouble unitLookC[3];
75  vhat_c(lookC, unitLookC);
76 
77  NaifStatus::CheckErrors();
78 
79  bool result = p_camera->SetLookDirection(unitLookC);
80  return result;
81  }
82 
83 
92  bool CameraGroundMap::SetGround(const Latitude &lat, const Longitude &lon) {
93  if (p_camera->target()->shape()->name() == "Plane") {
94  double radius = lat.degrees();
95  // double azimuth = lon.degrees();
96  Latitude lat(0., Angle::Degrees);
97  if (radius < 0.0) radius = 0.0; // TODO: massive, temporary kluge to get around testing
98  // latitude at -90 in caminfo app (are there
99  // more issues like this? Probably)KE
100  if (p_camera->Sensor::SetGround(SurfacePoint(lat, lon, Distance(radius, Distance::Meters)))) {
101  LookCtoFocalPlaneXY();
102  return true;
103  }
104  }
105  else {
106  Distance radius(p_camera->LocalRadius(lat, lon));
107  if (radius.isValid()) {
108  if (p_camera->Sensor::SetGround(SurfacePoint(lat, lon, radius))) {
109  LookCtoFocalPlaneXY();
110  return true;
111  }
112  }
113  }
114 
115  return false;
116  }
117 
118 
122  void CameraGroundMap::LookCtoFocalPlaneXY() {
123  double lookC[3];
124  p_camera->Sensor::LookDirection(lookC);
125 
126  //Get the fl as the z coordinate to handle instruments looking down the -z axis 2013-02-22.
127  double focalLength = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
128  double scale = focalLength / lookC[2];
129 
130  p_focalPlaneX = lookC[0] * scale;
131  p_focalPlaneY = lookC[1] * scale;
132  }
133 
134 
142  bool CameraGroundMap::SetGround(const SurfacePoint &surfacePoint) {
143  if (p_camera->Sensor::SetGround(surfacePoint)) {
144  LookCtoFocalPlaneXY();
145  return true;
146  }
147 
148  return false;
149  }
150 
151 
167  bool CameraGroundMap::GetXY(const SurfacePoint &point, double *cudx, double *cudy) {
168 
169  vector<double> pB(3);
170  pB[0] = point.GetX().kilometers();
171  pB[1] = point.GetY().kilometers();
172  pB[2] = point.GetZ().kilometers();
173 
174  // Check for Sky images
175  if (p_camera->target()->isSky()) {
176  return false;
177  }
178 
179  // Should a check be added to make sure SetImage has been called???
180 
181  // Get spacecraft vector in j2000 coordinates
182  SpiceRotation *bodyRot = p_camera->bodyRotation();
183  SpiceRotation *instRot = p_camera->instrumentRotation();
184  vector<double> pJ = bodyRot->J2000Vector(pB);
185  vector<double> sJ = p_camera->instrumentPosition()->Coordinate();
186 
187  // Calculate lookJ
188  vector<double> lookJ(3);
189  for (int ic = 0; ic < 3; ic++) {
190  lookJ[ic] = pJ[ic] - sJ[ic];
191  }
192 
193  // Save pB for target body partial derivative calculations NEW *** DAC 8-14-2015
194  m_pB = pB;
195 
196  // Check for point on back of planet by checking to see if surface point is viewable
197  // (test emission angle)
198  // During iterations, we may not want to do the back of planet test???
199  vector<double> lookB = bodyRot->ReferenceVector(lookJ);
200  double upsB[3], upB[3], dist;
201  vminus_c((SpiceDouble *) &lookB[0], upsB);
202  unorm_c(upsB, upsB, &dist);
203  unorm_c((SpiceDouble *) &pB[0], upB, &dist);
204  double angle = vdot_c(upB, upsB);
205  double emission;
206  if (angle > 1) {
207  emission = 0;
208  }
209  else if (angle < -1) {
210  emission = 180.;
211  }
212  else {
213  emission = acos(angle) * 180.0 / Isis::PI;
214  }
215 
216  if (fabs(emission) > 90.) {
217  return false;
218  }
219 
220  // Get the look vector in the camera frame and the instrument rotation
221  m_lookJ.resize(3);
222  m_lookJ = lookJ;
223  vector<double> lookC(3);
224  lookC = instRot->ReferenceVector(m_lookJ);
225 
226  // Get focal length with direction for scaling coordinates
227  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
228 
229  *cudx = lookC[0] * fl / lookC[2];
230  *cudy = lookC[1] * fl / lookC[2];
231  return true;
232  }
233 
234 
252  bool CameraGroundMap::GetXY(const double lat, const double lon,
253  const double radius, double *cudx, double *cudy) {
254  SurfacePoint spoint(Latitude(lat, Angle::Degrees),
255  Longitude(lon, Angle::Degrees),
256  Distance(radius, Distance::Meters));
257  return GetXY(spoint, cudx, cudy);
258  }
259 
260 
277  bool CameraGroundMap::GetdXYdPosition(const SpicePosition::PartialType varType, int coefIndex,
278  double *dx, double *dy) {
279 
280  //TODO add a check to make sure m_lookJ has been set
281 
282  // Get directional fl for scaling coordinates
283  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
284 
285  // Rotate look vector into camera frame
286  SpiceRotation *instRot = p_camera->instrumentRotation();
287  vector<double> lookC(3);
288  lookC = instRot->ReferenceVector(m_lookJ);
289 
290  SpicePosition *instPos = p_camera->instrumentPosition();
291 
292  vector<double> d_lookJ = instPos->CoordinatePartial(varType, coefIndex);
293  for (int j = 0; j < 3; j++) d_lookJ[j] *= -1.0;
294  vector<double> d_lookC = instRot->ReferenceVector(d_lookJ);
295  *dx = fl * DQuotient(lookC, d_lookC, 0);
296  *dy = fl * DQuotient(lookC, d_lookC, 1);
297  return true;
298  }
299 
300 
316  bool CameraGroundMap::GetdXYdOrientation(const SpiceRotation::PartialType varType, int coefIndex,
317  double *dx, double *dy) {
318 
319  //TODO add a check to make sure m_lookJ has been set
320 
321  // Get directional fl for scaling coordinates
322  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
323 
324  // Rotate J2000 look vector into camera frame
325  SpiceRotation *instRot = p_camera->instrumentRotation();
326  vector<double> lookC(3);
327  lookC = instRot->ReferenceVector(m_lookJ);
328 
329  // Rotate J2000 look vector into camera frame through the derivative rotation
330  vector<double> d_lookC = instRot->ToReferencePartial(m_lookJ, varType, coefIndex);
331 
332  *dx = fl * DQuotient(lookC, d_lookC, 0);
333  *dy = fl * DQuotient(lookC, d_lookC, 1);
334  return true;
335  }
336 
337 
352  bool CameraGroundMap::GetdXYdTOrientation(const SpiceRotation::PartialType varType, int coefIndex,
353  double *dx, double *dy) {
354 
355  //TODO add a check to make sure m_pB and m_lookJ have been set.
356  // 0. calculate or save from previous GetXY call lookB. We need toJ2000Partial that is
357  // like a derivative form of J2000Vector
358  // 1. we will call d_lookJ = bodyrot->toJ2000Partial (Make sure the partials are correct for
359  // the target body orientation matrix.
360  // 2. we will then call d_lookC = instRot->ReferenceVector(d_lookJ)
361  // 3. the rest should be the same.
362 
363  // Get directional fl for scaling coordinates
364  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
365 
366  // Rotate body-fixed look vector into J2000 through the derivative rotation
367  SpiceRotation *bodyRot = p_camera->bodyRotation();
368  SpiceRotation *instRot = p_camera->instrumentRotation();
369  vector<double> dlookJ = bodyRot->toJ2000Partial(m_pB, varType, coefIndex);
370  vector<double> lookC(3);
371  vector<double> dlookC(3);
372 
373  // Rotate both the J2000 look vector and the derivative J2000 look vector into the camera
374  lookC = instRot->ReferenceVector(m_lookJ);
375  dlookC = instRot->ReferenceVector(dlookJ);
376 
377  *dx = fl * DQuotient(lookC, dlookC, 0);
378  *dy = fl * DQuotient(lookC, dlookC, 1);
379  return true;
380  }
381 
382 
396  bool CameraGroundMap::GetdXYdPoint(vector<double> d_pB, double *dx, double *dy) {
397 
398  // TODO add a check to make sure m_lookJ has been set
399 
400  // Get directional fl for scaling coordinates
401  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
402 
403  // Rotate look vector into camera frame
404  SpiceRotation *instRot = p_camera->instrumentRotation();
405  vector<double> lookC(3);
406  lookC = instRot->ReferenceVector(m_lookJ);
407 
408  SpiceRotation *bodyRot = p_camera->bodyRotation();
409  vector<double> d_lookJ = bodyRot->J2000Vector(d_pB);
410  vector<double> d_lookC = instRot->ReferenceVector(d_lookJ);
411 
412  *dx = fl * DQuotient(lookC, d_lookC, 0);
413  *dy = fl * DQuotient(lookC, d_lookC, 1);
414  return true;
415  }
416 
417 
434  vector<double> CameraGroundMap::EllipsoidPartial(SurfacePoint spoint, PartialType raxis) {
435  double rlat = spoint.GetLatitude().radians();
436  double rlon = spoint.GetLongitude().radians();
437  double sinLon = sin(rlon);
438  double cosLon = cos(rlon);
439  double sinLat = sin(rlat);
440  double cosLat = cos(rlat);
441 
442  vector<double> v(3);
443 
444  switch (raxis) {
445  case WRT_MajorAxis:
446  v[0] = cosLat * cosLon;
447  v[1] = 0.0;
448  v[2] = 0.0;
449  break;
450  case WRT_MinorAxis:
451  v[0] = 0.0;
452  v[1] = cosLat * sinLon;
453  v[2] = 0.0;
454  break;
455  case WRT_PolarAxis:
456  v[0] = 0.0;
457  v[1] = 0.0;
458  v[2] = sinLat;
459  break;
460  default:
461  QString msg = "Invalid partial type for this method";
462  throw IException(IException::Programmer, msg, _FILEINFO_);
463  }
464 
465  return v;
466  }
467 
468 
484  vector<double> CameraGroundMap::MeanRadiusPartial(SurfacePoint spoint, Distance meanRadius) {
485  double radkm = meanRadius.kilometers();
486 
487  vector<double> v(3);
488 
489  v[0] = spoint.GetX().kilometers() / radkm;
490  v[1] = spoint.GetY().kilometers() / radkm;
491  v[2] = spoint.GetZ().kilometers() / radkm;
492 
493  return v;
494  }
495 
496 
506  vector<double> CameraGroundMap::PointPartial(SurfacePoint spoint, PartialType wrt) {
507  double rlat = spoint.GetLatitude().radians();
508  double rlon = spoint.GetLongitude().radians();
509  double sinLon = sin(rlon);
510  double cosLon = cos(rlon);
511  double sinLat = sin(rlat);
512  double cosLat = cos(rlat);
513  double radkm = spoint.GetLocalRadius().kilometers();
514 
515  vector<double> v(3);
516  if (wrt == WRT_Latitude) {
517  v[0] = -radkm * sinLat * cosLon;
518  v[1] = -radkm * sinLon * sinLat;
519  v[2] = radkm * cosLat;
520  }
521  else if (wrt == WRT_Longitude) {
522  v[0] = -radkm * cosLat * sinLon;
523  v[1] = radkm * cosLat * cosLon;
524  v[2] = 0.0;
525  }
526  else {
527  v[0] = cosLon * cosLat;
528  v[1] = sinLon * cosLat;
529  v[2] = sinLat;
530  }
531 
532  return v;
533  }
534 
535 
548  double CameraGroundMap::DQuotient(vector<double> &look,
549  vector<double> &dlook,
550  int index) {
551  return (look[2] * dlook[index] - look[index] * dlook[2]) /
552  (look[2] * look[2]);
553  }
554 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:86
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:245
Distance GetLocalRadius() const
Return the radius of the surface point.
double radians() const
Convert an angle to a double.
Definition: Angle.h:239
void SetGroundMap(CameraGroundMap *map)
Sets the Ground Map.
Definition: Camera.cpp:2456
const double PI(3.14159265358979323846)
The mathematical constant PI.
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:59
std::vector< double > CoordinatePartial(SpicePosition::PartialType partialVar, int coeffIndex)
Set the coefficients of a polynomial fit to each of the three coordinates of the position vector for ...
Distance measurement, usually in meters.
Definition: Distance.h:47
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
PartialType
Radius axes types to use when computing partials.
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
double kilometers() const
Get the displacement in kilometers.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
Obtain SPICE rotation information for a body.
PartialType
This enumeration indicates whether the partial derivative is taken with respect to Right Ascension...
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
std::vector< double > toJ2000Partial(const std::vector< double > &lookT, PartialType partialVar, int coeffIndex)
Given a direction vector in the reference frame, compute the derivative with respect to one of the co...
std::vector< double > J2000Vector(const std::vector< double > &rVec)
Given a direction vector in the reference frame, return a J2000 direction.
Isis exception class.
Definition: IException.h:99
Obtain SPICE position information for a body.
double kilometers() const
Get the distance in kilometers.
Definition: Distance.cpp:118
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
std::vector< double > ToReferencePartial(std::vector< double > &lookJ, PartialType partialVar, int coeffIndex)
Compute the derivative with respect to one of the coefficients in the angle polynomial fit equation o...

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:15:36