Isis 3 Programmer Reference
Stereo.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include <cmath>
8 #include <cstdlib>
9 #include <sstream>
10 #include <iostream>
11 #include <iomanip>
12 
13 #include <SpiceUsr.h>
14 #include <SpiceZfc.h>
15 #include <SpiceZmc.h>
16 
17 #include "Camera.h"
18 #include "TProjection.h"
19 #include "SpecialPixel.h"
20 #include "Stereo.h"
21 
22 namespace Isis {
23 
24  bool Stereo::elevation(Camera &cam1, Camera &cam2, double &radius,
25  double &latitude, double &longitude,
26  double &sepang, double &error) {
27 
28  // Gut check on input Camera points
29  radius = latitude = longitude = Isis::Null;
30  if ( !cam1.HasSurfaceIntersection() ) return (false);
31  if ( !cam2.HasSurfaceIntersection() ) return (false);
32 
33  // Get spacecraft position from target
34  double TC1[3], TC2[3];
35  targetToSpacecraft(cam1, TC1);
36  targetToSpacecraft(cam2, TC2);
37 
38 
39  // Get surface vectors from center of body to surface
40  double TP1[3], TP2[3];
41  targetToSurface(cam1, TP1);
42  targetToSurface(cam2, TP2);
43 
44  // Stereo angle
45  sepang = vsep_c(TC1, TC2) * dpr_c();
46 
47  SpiceDouble CP1[3], CP2[3];
48  vsub_c(TC1, TP1, CP1);
49  vsub_c(TC2, TP2, CP2);
50 
51  sepang = vsep_c(CP1, CP2) * dpr_c();
52 
53  double DR1, DR2;
54  DR1 = vnorm_c(CP1);
55  DR2 = vnorm_c(CP2);
56 
57  vscl_c(1.0/DR1, CP1, CP1);
58  vscl_c(1.0/DR2, CP2, CP2);
59 
60  // Do stereo intersections
61  double aa = CP2[0];
62  double bb = CP2[1];
63  double cc = CP2[2];
64  double xx = CP1[0];
65  double yy = CP1[1];
66  double zz = CP1[2];
67 
68  // Vector between both spacecraft
69  double dd = TC2[0] - TC1[0];
70  double ee = TC2[1] - TC1[1];
71  double ff = TC2[2] - TC1[2];
72 
73  // Do the stereo intersection
74  double bzcy = bb*zz - cc*yy;
75  double cebf = cc*ee - bb*ff;
76  double cxaz = cc*xx - aa*zz;
77  double afcd = aa*ff - cc*dd;
78  double aybx = aa*yy - bb*xx;
79  double bdae = bb*dd - aa*ee;
80 
81  // Get fraction `T' along left vector to "intersection point"
82  double T=-(bzcy*cebf+cxaz*afcd+aybx*bdae)/
83  (bzcy*bzcy+cxaz*cxaz+aybx*aybx);
84  double lx=TC1[0] + T * CP1[0];
85  double ly=TC1[1] + T * CP1[1];
86  double lz=TC1[2] + T * CP1[2];
87 
88  // Find the Perp. vector between both lines (at shortest sep.)
89  double x = TC2[0] - lx;
90  double y = TC2[1] - ly;
91  double z = TC2[2] - lz;
92 
93  // Find the separation distance - useful later
94  double rx = y * CP2[2] - CP2[1] * z;
95  double ry = CP2[0] * z - x * CP2[2];
96  double rz = x * CP2[1] - CP2[0] * y;
97  double dr = std::sqrt(rx*rx+ry*ry+rz*rz);
98 
99  // Find position of intersection on lower line
100  rx = CP1[1] * CP2[2] - CP2[1] * CP1[2];
101  ry = CP2[0] * CP1[2] - CP1[0] * CP2[2];
102  rz = CP1[0] * CP2[1] - CP2[0] * CP1[1];
103  double raa = std::sqrt(rx*rx+ry*ry+rz*rz);
104 
105  // Normalize our new Perpendicular vector
106  rx = rx/raa;
107  ry = ry/raa;
108  rz = rz/raa;
109 
110  // Get the other intersection position
111  rx = lx - rx*dr;
112  ry = ly - ry*dr;
113  rz = lz - rz*dr;
114 
115  // Compute the mid point of the intersection on the planets
116  // surface
117  double mx = (lx+rx)/2.0;
118  double my = (ly+ry)/2.0;
119  double mz = (lz+rz)/2.0;
120  rectangular(mx, my, mz, latitude, longitude, radius);
121  radius *= 1000.0 ; // convert to meters
122  error = dr * 1000.0;
123  return (true);
124  }
125 
126 
127  void Stereo::spherical(const double latitude, const double longitude,
128  const double radius,
129  double &x, double &y, double &z) {
130  SpiceDouble rec[3];
131  latrec_c(radius/1000.0, longitude*rpd_c(), latitude*rpd_c(), &rec[0]);
132  x = rec[0];
133  y = rec[1];
134  z = rec[2];
135  return;
136  }
137 
138  void Stereo::rectangular(const double x, const double y, const double z,
139  double &latitude, double &longitude,
140  double &radius) {
141  SpiceDouble rec[3];
142  rec[0] = x;
143  rec[1] = y;
144  rec[2] = z;
145  reclat_c(&rec[0], &radius, &longitude, &latitude);
146  longitude *= dpr_c();
147  latitude *= dpr_c();
148  longitude = TProjection::To360Domain(longitude);
149  return;
150  return;
151  }
152 
153  std::vector<double> Stereo::array2StdVec(const double d[3]) {
154  std::vector<double> v;
155  for ( int i = 0 ; i < 3 ; i++ ) {
156  v.push_back(d[i]);
157  }
158  return (v);
159  }
160 
161  double *Stereo::stdVec2Array(const std::vector<double> &v, double *d) {
162  if ( d == NULL ) {
163  d = new double[v.size()];
164  }
165 
166  for ( unsigned int i = 0 ; i < v.size() ; i++ ) {
167  d[i] = v[i];
168  }
169  return (d);
170  }
171 
172  void Stereo::targetToSpacecraft(Camera &camera, double TP[3]) {
173  camera.instrumentPosition(TP);
174  return;
175  }
176 
177  void Stereo::targetToSurface(Camera &camera, double TC[3]) {
178  camera.Coordinate(TC);
179  return;
180  }
181 
182 }
Isis::Null
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:95
Isis::TProjection::To360Domain
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
Definition: TProjection.cpp:675
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16