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
22namespace 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}
static double To360Domain(const double lon)
This method converts a longitude into the 0 to 360 domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double Null
Value for an Isis Null pixel.