Isis 3 Programmer Reference
ApolloPanIO.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "ApolloPanIO.h"
10
11#include <math.h>
12#include <iostream>
13
14#include "Ransac.h"
15#include "stdio.h"
16
17
18#define FIDL 5344.186 //nominal line spread of fiducials in 5 micro pixels
19#define FIDS 22980 //nominal sample spread of fiducials in 5 micron pixels
20
21using namespace std;
22
23namespace Isis {
24
31
36 //empty destructor....
37 }
38
43 int i;
44
45 //the number of affines to be calculated
46 n=0;
47
48 //zero solved flags in discrete affines
49 for (i=0; i<44; i++)
50 affines[i].flag=0;
51
52 //initial residuals statistic variable to nonsense values
53 maxR = -1.0;
54 meanR = -1.0;
55 stdevR= -1.0;
56
57 //zero observed flags in fiducial observations
58 for (i=0; i<90; i++) {
59 obs[i].flag=0;
60
61 //also calculate theoretical image observation of the fiducial marks
62 if (i%2 == 0)
63 obs[i].image[0] = FIDS/2;
64 else
65 obs[i].image[0] = -FIDS/2;
66
67 obs[i].image[1] = (-21.5 + double(int(i/2)))*FIDL;
68
69 //adjustment to account for the half spacing among the 22nd, 23rd, and 24th
70 // fiducials on each side
71 if (int(i/2)==22)
72 obs[i].image[1] -= FIDL/2;
73 else if ( int(i/2) > 22)
74 obs[i].image[1] -= FIDL;
75
76 obs[i].image[1] = -obs[i].image[1]; //sign reversal to match camera layout
77 }
78
79 }
80
96 int ApolloPanIO::fiducialObservation(int fiducialNumber, double machineX, double machineY) {
97 /*
98 used to enter/overwrite observations of fiducial marks
99
100 fiducial_number -> number indicating which fiducial mark, see diagram at the top of the file
101 machineX -> x machine coordinate
102 machineY -> y machine coordinate
103
104 returns 1 if the input data is reasonable otherwise -1
105 */
106
107
108 //first check the range of the fiducial number
109 if (fiducialNumber < 0 || fiducialNumber > 89)
110 return -1;
111
112 //next check the range of the machine coordinates
113 // (this is just a nonsense number check)
114 if (fabs(machineX) > 1e20)
115 return -1;
116
117 if (fabs(machineY) > 1e20)
118 return -1;
119
120 //if all looks OK record the data
121 obs[fiducialNumber].mach[0] = machineX;
122 obs[fiducialNumber].mach[1] = machineY;
123
124 //and mark the point observed
125 obs[fiducialNumber].flag = 1;
126
127 return 1;
128 }
129
141 //first check the range of the fiducial number
142 if (fiducialNumber < 0 || fiducialNumber > 89)
143 return -1;
144
145 //and mark the point unobserved
146 obs[fiducialNumber].flag = 0;
147
148 return 1;
149
150 }
151
161 {
162 int i,j,k,l,m; //indeces-counters for linear algebra computations
163
164 double cdot[43][4][6],
165 angle, //angle of rotation to vertical for determining rotation coefficients
166 det, //determinate of 2x2 affine matrices used for matrix inversions
167 //wcdot[43][4], //all conditions are identically zero.. no need to store that..
168 ndot[44][21],
169 cndot[43][4][12],
170 cxstar[172], //cX* matrix, Uotila course notes page 122
171 cnct[14878], //CNCt matrix, Uotila course notes page 122
172 atw[44][6]; //right side of normal equation (see Uotila course notes)
173 // NOTE: I store w with reversed signs compared to Uotila's notes
174
175 double adot[2][6],wdot[2];
176
177 //adot is a sub matrix of A (see Uotila Course notes page 122).
178 // It is composed of partials WRT to unknowns.
179 //some affine partials are the same for every point so might as well hard code them now...
180 adot[0][2] = 0.0;
181 adot[0][3] = 0.0;
182
183 adot[0][4] = 1.0;
184 adot[0][5] = 0.0;
185
186 adot[1][0] = 0.0;
187 adot[1][1] = 0.0;
188
189 adot[1][4] = 0.0;
190 adot[1][5] = 1.0;
191
192 //first order of business...
193 // figure out how many affines there will be and which fiducial measures belong to each
194
195 //the first affine always begins with point zero
196 affines[0].indeces[0] =0;
197 affines[0].flag = 1;
198
199 for (i=2, n=0; i<90; i+=2) {
200 // i is counting the fiducials
201 // n is counting the affines
202
203 //every time both fiducials in a horizontal (equal x coordinate) pair have been measured start
204 // a new affine
205 if (obs[i].flag && obs[i+1].flag) {
206 affines[n ].indeces[1] = i+1;
207 affines[n+1].indeces[0] = i ;
208 affines[n+1].flag=1;
209 n++;
210 }
211 }
212
213 //check for sufficient data
214 if (n ==0) return -1;
215
216 //now that we know how many affines will be needed we can get started
217
218 //solve each affine individually
219
220 //for each affine
221 for (i =0; i<n; i++) {
222 //initialize the appropriate ndot and atw matrices
223 for (j=0; j<21;j++)
224 ndot[i][j] =0.0;
225
226 for (j=0; j<6; j++)
227 atw[i][j]=0.0;
228
229 //for each point pertaining to each affine
230 for (j=affines[i].indeces[0]; j<=affines[i].indeces[1]; j++) {
231 //if the point has been observed use the observation to build the normal
232 if(obs[j].flag) {
233 //store the partials that change...
234 adot[0][0] = obs[j].mach[0];
235 adot[0][1] = obs[j].mach[1];
236
237 adot[1][2] = obs[j].mach[0];
238 adot[1][3] = obs[j].mach[1];
239
240 wdot[0] = obs[j].image[0];
241 wdot[1] = obs[j].image[1];
242
243
244 //build up the appropriate normal equations
245 for (k=0; k<6; k++)
246 for (l=0; l<=k; l++)
247 for (m=0; m<2; m++)
248 ndot[i][Isis::isymp(k,l)] += adot[m][k]*adot[m][l];
249
250 for (k=0; k<6; k++)
251 atw[i][k] += adot[0][k]*wdot[0] + adot[1][k]*wdot[1];
252 }
253 }
254
255 //copy the atw matrix into the affine class structure so that it isn't lost when the solution
256 // is done
257 for (j=0; j<6; j++)
258 affines[i].A2I[j] = atw[i][j];
259
260 //solve this affine
261 //NOTE: it must also be inverted for later calculations, hence three instead of two for the
262 // last argument
263 if (!Isis::choleski_solve(ndot[i],affines[i].A2I,6,3))
264 j=0;
265 }
266
267
268 //now the contributions of the continuity conditions must be added....
269
270 //cdot[i] are sub matrices of C matrix (Uotila page 122)
271 //Note: the cdot matrices are 4x12 (4 continuity conditions between 2 six paramter affines)
272 // however the left 4x6 portion of the cdot matrix and right 4x6 portion are equal but
273 // opposite so it's only necessary to calc/store one of them
274 for (i=0; i<n-1; i++) {
275 //build cdot matrix for continuity condition between affine i and i+1
276 cdot[i][0][0 ] = obs[affines[i].indeces[1]-1].mach[0];
277 cdot[i][0][1 ] = obs[affines[i].indeces[1]-1].mach[1];
278 cdot[i][0][2 ] = 0.0;
279 cdot[i][0][3 ] = 0.0;
280 cdot[i][0][4 ] = 1.0;
281 cdot[i][0][5 ] = 0.0;
282
283 cdot[i][1][0 ] = 0.0;
284 cdot[i][1][1 ] = 0.0;
285 cdot[i][1][2 ] = obs[affines[i].indeces[1]-1].mach[0];
286 cdot[i][1][3 ] = obs[affines[i].indeces[1]-1].mach[1];
287 cdot[i][1][4 ] = 0.0;
288 cdot[i][1][5 ] = 1.0;
289
290 cdot[i][2][0 ] = obs[affines[i].indeces[1] ].mach[0];
291 cdot[i][2][1 ] = obs[affines[i].indeces[1] ].mach[1];
292 cdot[i][2][2 ] = 0.0;
293 cdot[i][2][3 ] = 0.0;
294 cdot[i][2][4 ] = 1.0;
295 cdot[i][2][5 ] = 0.0;
296
297 cdot[i][3][0 ] = 0.0;
298 cdot[i][3][1 ] = 0.0;
299 cdot[i][3][2 ] = obs[affines[i].indeces[1] ].mach[0];
300 cdot[i][3][3 ] = obs[affines[i].indeces[1] ].mach[1];
301 cdot[i][3][4 ] = 0.0;
302 cdot[i][3][5 ] = 1.0;
303 }
304
305 //calculate cndot sub matrices of Uotila's C(AtM-A)- page122
306 for (i=0; i<n-1; i++) {
307 //initialize the matrix
308 for (j=0; j<4; j++)
309 for (k=0; k<12; k++)
310 cndot[i][j][k] = 0.0;
311
312 for (j=0; j<4; j++)
313 for (k=0; k<6; k++)
314 for (l=0; l<6; l++) {
315 cndot[i][j][k ] += cdot[i][j][l] * ndot[i ][Isis::isymp(l,k)];
316 cndot[i][j][k+6] -= cdot[i][j][l] * ndot[i+1][Isis::isymp(l,k)];
317 }
318 }
319
320 //calculate the CX* matrix -page 122
321 for (i=0; i<(n-1)*4; i++) {
322 j= int(i/4); //which c sub matrix
323 k= i%4; //row of the c sub matrix
324
325 cxstar[i] = 0;
326
327 for (l=0; l<6; l++) {
328 cxstar[i] -= cdot[j][k][l]*affines[j ].A2I[l];
329 cxstar[i] += cdot[j][k][l]*affines[j+1].A2I[l];
330 }
331 }
332
333 //initialize CNCt matrix
334 for (i=0; i<14878; i++)
335 cnct[i] = 0.0;
336
337 //calculate all of the diagonal portions
338 for (i=0; i<n-1; i++) {
339 for (j=0; j<4; j++)
340 for (k=0; k<=j; k++) //remember that this matrix is a memory optimized symmetric matrix
341 for (l=0; l<12; l++) {
342 if(l<6)
343 cnct[Isis::isymp(j+4*i,k+4*i)] += cndot[i][j][l] * cdot[i][k][l];
344 else
345 cnct[Isis::isymp(j+4*i,k+4*i)] -= cndot[i][j][l] * cdot[i][k][l-6];
346 }
347 }
348
349 //calculate all of the diagonal portions
350 for (i=0; i<n-2; i++) {
351 for (j=0; j<4; j++)
352 for (k=0; k<4; k++)
353 for (l=0; l<6; l++)
354 cnct[Isis::isymp(j+i*4,k+4+i*4)] += cndot[i][j][l+6]*cdot[i+1][k][l];
355 }
356
357
358 Isis::choleski_solve(cnct,cxstar,4*(n-1),2);
359
360 //cxstar are now Kc Lagrange multipliers
361 //now (CN)tKc = NCtKc are the secondary corrections to the unknowns and they can be added
362 // directly to the previously calculated values
363
364 //corrections to the first affine
365 for (i=0; i<6; i++) {
366 for (j=0; j<4;j ++)
367 affines[0].A2I[i] += cxstar[j]*cndot[0][j][i];
368 }
369
370 //for all the middle affines
371 for (i=1; i<n-1; i++) {
372 for (j=0; j<6; j++) {
373 for (k=0; k<4; k++)
374 affines[i].A2I[j] += cxstar[(i-1)*4+k]*cndot[i-1][k][j+6];
375 for (k=0; k<4; k++)
376 affines[i].A2I[j] += cxstar[(i )*4+k]*cndot[i ][k][j ];
377 }
378 }
379
380 //corrections for the last affine
381 for (i=0; i<6; i++) {
382 for (j=0; j<4; j++)
383 affines[n-1].A2I[i] += cxstar[4*(n-2)+j]*cndot[n-2][j][i+6];
384 }
385
386
387 //now compute the reverse affines
388 for (i=0; i<n; i++) {
389 det = affines[i].A2I[0]*affines[i].A2I[3] - affines[i].A2I[1]*affines[i].A2I[2];
390
391 affines[i].A2M[0] = affines[i].A2I[3]/det;
392 affines[i].A2M[3] = affines[i].A2I[0]/det;
393
394 affines[i].A2M[1] = -affines[i].A2I[1]/det;
395 affines[i].A2M[2] = -affines[i].A2I[2]/det;
396
397 affines[i].A2M[4] = - affines[i].A2M[0]*affines[i].A2I[4]
398 - affines[i].A2M[1]*affines[i].A2I[5];
399 affines[i].A2M[5] = - affines[i].A2M[2]*affines[i].A2I[4]
400 - affines[i].A2M[3]*affines[i].A2I[5];
401 }
402
403 //now define the rotation coefficients that will transform any image/machine y coordinate into
404 // a reference frame where the two right most fiducials are have the exact same y value and
405 // it is thus easy to determine where a point lies on the left side of the line
406
407 double pt1[2], pt2[2],v[2];
408
409 for (i=0; i<n; i++) {
410 //rotations in machine space,
411
412 //the two points obs[affines[i].indeces[1]-1] and obs[affines[i].indeces[1]] define a line
413
414 pt1[0] = obs[affines[i].indeces[1]-1].mach[0];
415 pt1[1] = obs[affines[i].indeces[1]-1].mach[1];
416
417 pt2[0] = obs[affines[i].indeces[1] ].mach[0];
418 pt2[1] = obs[affines[i].indeces[1] ].mach[1];
419
420
421 //find the point on the line closest to the origin
422
423 //vector in the direction of a line
424 v[0] = pt1[0] - pt2[0];
425 v[1] = pt1[1] - pt2[1];
426
427 //using det as the scale factor along the line from pt1 to the point nearest the origin
428 det = -(pt1[0]*v[0] + pt1[1]*v[1])/(v[0]*v[0]+v[1]*v[1]);
429
430 //pt1 + det*v is the point closest to the origin and the angle needed to rotate that
431 // point so that it lies on the y axis is...
432 angle = atan2((pt1[0]+det*v[0]),(pt1[1]+det*v[1]));
433
434 //and since we're only ever going to be concerned with rotating the y coordinates and z's
435 // are alwyas zero there are only two values we need to save to elements of the rotation
436 // matrix
437 affines[i].rotM[0] = sin(angle);
438 affines[i].rotM[1] = cos(angle);
439
440 //any machine coordinate [u,v] can be rotated into a system where the greatest y values of
441 // the fiducial marks are the same, and therefore the greatest y value in a particular
442 // affine is:
443 affines[i].mM = pt1[0]*affines[i].rotM[0] + pt1[1]*affines[i].rotM[1];
444
445 //or equivalently...
446 //affines[i].mM = pt2[0]*affines[i].rotM[0] + pt2[1]*affines[i].rotM[1];
447
448
449
450 //rotations in image space
451
452 //for this calculation the transformed Machine (measured coordinates) are used rather than
453 // the theoretical/expected coordinates of the fiducial marks. They should be close to
454 // identical, but it is the affines and therefore the transformed points that define the
455 // actual work space.
456 pt1[0] = affines[i].A2I[0] * obs[affines[i].indeces[1]-1].mach[0] +
457 affines[i].A2I[1] * obs[affines[i].indeces[1]-1].mach[1] +
458 affines[i].A2I[4];
459
460 pt1[1] = affines[i].A2I[2] * obs[affines[i].indeces[1]-1].mach[0] +
461 affines[i].A2I[3] * obs[affines[i].indeces[1]-1].mach[1] +
462 affines[i].A2I[5];
463
464 pt2[0] = affines[i].A2I[0] * obs[affines[i].indeces[1] ].mach[0] +
465 affines[i].A2I[1] * obs[affines[i].indeces[1] ].mach[1] +
466 affines[i].A2I[4];
467
468 pt2[1] = affines[i].A2I[2] * obs[affines[i].indeces[1] ].mach[0] +
469 affines[i].A2I[3] * obs[affines[i].indeces[1] ].mach[1] +
470 affines[i].A2I[5];
471
472
473 //find the point on the line closest to the origin
474
475 //vector in the direction of a line
476 v[0] = pt1[0] - pt2[0];
477 v[1] = pt1[1] - pt2[1];
478
479 //using det as the scale factor along the line from pt1 to the point nearest the origin
480 det = -(pt1[0]*v[0] + pt1[1]*v[1])/(v[0]*v[0]+v[1]*v[1]);
481
482 //pt1 + det*v is the point closest to the origin and the angle needed to rotate that point
483 // so that it lies on the y axis is...
484 angle = atan((pt1[0]+det*v[0])/(pt1[1]+det*v[1]));
485
486 //and since we're only ever going to be concerned with rotating the y coordinates and z's
487 // are alwyas zero there are only two values we need to save to elements of the rotation
488 // matrix
489 affines[i].rotI[0] = sin(angle);
490 affines[i].rotI[1] = cos(angle);
491
492 //any machine coordinate [u,v] can be rotated into a system where greatest y values of the
493 // affine border are the same that is the border is a line parrallel to the image x axis,
494 // and therefore the greatest y value in a particular affine is
495 affines[i].mI = pt1[0]*affines[i].rotI[0] + pt1[1]*affines[i].rotI[1];
496
497 //or equivalently...
499 }
500
501
502
503
504
505
506 //all the parameters necessary for the machine2image and image2machin coordinate
507 // transformations are now computed and stored
508
509
510
511
512
513
514 //calculate and store residuals
515 for (i=0; i<90; i++) {
516 if (obs[i].flag) { //if the point has been observed...
517 //convert the theoretical image coordinate to machine space and compare it to the
518 // measured coordinate--this way residuals are in pixels
519 image2Machine(obs[i].image[0],obs[i].image[1],&pt1[0],&pt1[1]);
520
521 obs[i].residuals[0] = pt1[0] - obs[i].mach[0];
522 obs[i].residuals[1] = pt1[1] - obs[i].mach[1];
523 }
524 }
525
526 calc_residual_stats(); //DEBUG
527
528 return 1;
529 }
530
546 int ApolloPanIO::machine2Image(double *machineX, double *machineY) {
547
548 double temp,npt[2];
549 int i;
550
551 //first do a domain check to be sure this point is in the last affine
552 temp = *machineX * affines[n-2].rotM[0] + *machineY * affines[n-2].rotM[1];
553
554 if (temp > affines[n-2].mM) {
555 i=n-1;
556 }
557 else {//now step through the affines to determine in the domain of which one this point lies
558 for (i=0; i<n-1; i++) {
559 temp = *machineX * affines[i].rotM[0] + *machineY * affines[i].rotM[1];
560
561 //if the point is in the domain of this affine do the conversion...
562 if (temp <= affines[i].mM)
563 break;
564 }
565 }
566 //cout << "DEBUG: affine index: " << i << endl;
567 //cout << "affine " << affines[i].A2I[0] << " " << affines[i].A2I[1] << " "<< affines[i].A2I[2] << " "<< affines[i].A2I[3] << " "<< affines[i].A2I[4] << " "<< affines[i].A2I[5];
568 npt[0] = affines[i].A2I[0] * *machineX + affines[i].A2I[1] * *machineY + affines[i].A2I[4];
569 npt[1] = affines[i].A2I[2] * *machineX + affines[i].A2I[3] * *machineY + affines[i].A2I[5];
570
571 *machineX = npt[0]; //overwrite the input
572 *machineY = npt[1]; //overwrite the input
573
574 return 1; //point successfully converted
575 }
576
599 int ApolloPanIO::machine2Image(double machineX,
600 double machineY,
601 double *imageX,
602 double *imageY) {
603
604 int i;
605
606 *imageX = machineX;
607 *imageY = machineY;
608
609 i = machine2Image(imageX,imageY);
610
611 return i;
612 }
613
629 int ApolloPanIO::image2Machine(double *imageX, double *imageY) {
630
631 double temp, npt[2];
632 int i;
633
634 //first do a domain check if this point is in the last affine
635 temp = *imageX * affines[n-2].rotI[0] + *imageY * affines[n-2].rotI[1];
636
637 if( temp < affines[n-2].mI)
638 i = n-1;
639 else {
640 //now step through the affines to determine in the domain of which one this point lies
641 for (i=0; i<n-1; i++) {
642 temp = *imageX * affines[i].rotI[0] + *imageY * affines[i].rotI[1];
643
644 //if the point is in the domain of this affine do the conversion...
645 if( temp >= affines[i].mI)
646 break;
647 }
648 }
649 //cout << "DEBUG: affine index: " << i << endl;
650 //cout << "affine " << affines[i].A2M[0] << " " << affines[i].A2M[1] << " "<< affines[i].A2M[2] << " "<< affines[i].A2M[3] << " "<< affines[i].A2M[4] << " "<< affines[i].A2M[5];
651 npt[0] = affines[i].A2M[0] * *imageX + affines[i].A2M[1] * *imageY + affines[i].A2M[4];
652 npt[1] = affines[i].A2M[2] * *imageX + affines[i].A2M[3] * *imageY + affines[i].A2M[5];
653
654 *imageX = npt[0]; //overwrite the input
655 *imageY = npt[1]; //overwrite the input
656
657 return 1; //point successfully converted
658 }
659
682 int ApolloPanIO::image2Machine(double imageX,
683 double imageY,
684 double *machineX,
685 double *machineY) {
686 /* This class method converts a machine coordinate to an image coordinate
687 (overwriting the input arguments)
688
689 imageX -> machine x input
690 imageY -> machine y input
691 machineX <- to be overwritten as the converted coordinate
692 machineY <- to be overwritten as the converted coordinate
693 */
694
695 *machineX = imageX;
696 *machineY = imageY;
697
698 return image2Machine(machineX,machineY);
699 }
700
708 maxR = 0.0;
709
710 meanR = 0.0;
711
712 stdevR = 0.0;
713
714 int i,n=0;
715
716 double l;
717
718 for (i=0; i<90; i++) {
719 if (obs[i].flag) {
720 l = sqrt(obs[i].residuals[0]*obs[i].residuals[0] +
721 obs[i].residuals[1]*obs[i].residuals[1]);
722
723 if( l > maxR)
724 maxR = l;
725
726 meanR += l;
727
728 n++;
729 }
730 }
731
732 meanR /=n;
733
734 for (i=0; i<90; i++) {
735 if(obs[i].flag) {
736 l = sqrt(obs[i].residuals[0]*obs[i].residuals[0] +
737 obs[i].residuals[1]*obs[i].residuals[1]);
738
739 stdevR += (l-meanR)*(l-meanR);
740 }
741 }
742
743 stdevR = sqrt(stdevR/(n-1));
744
745 return;
746 }
747
755 //returns the standard deviation of the length of the 2D residual vectors
756 //if it hasn't been calucated a nonsense number (-1.0) will be returned
757 return stdevR;
758 }
759
767 {
768 return meanR;
769 }
770
778 {
779 return maxR;
780 }
781} //end namespace Isis
void initialize()
Initilizes member variables in preparation for solving for the interior orientation affines.
double maxR
maximum residual vector length
Definition ApolloPanIO.h:88
FidObs obs[90]
array to hold all possible observations of fiducial marks
Definition ApolloPanIO.h:86
Affine2D affines[44]
an array of discreet affine transformations pertaining to regions of the image (there can never be mo...
Definition ApolloPanIO.h:84
int machine2Image(double *machineX, double *machineY)
This method does an in place (overwriting input) conversion of a cube coordinate (sample,...
int n
the number of affines used to model the image
Definition ApolloPanIO.h:87
double meanR
mean of residual vector lenghts
Definition ApolloPanIO.h:89
double maxResiduals()
Accessor for the mean (average) of the residual vector lenghts Call after computeInteriorOrienation()...
double stdevResiduals()
Accessor for the standard deviation of the residual vector lenghts Call after computeInteriorOrienati...
ApolloPanIO()
Constructs an ApolloPanIO object.
double meanResiduals()
Accessor for the mean (average) of the residual vector lenghts Call after computeInteriorOrienation()...
void calc_residual_stats()
This method calculates summary statistics for the residual vector lenths for all measured fiducial ma...
int image2Machine(double *imageX, double *imageY)
This method does an in place (overwriting input) conversion of an image coordinate into cube (machine...
~ApolloPanIO()
Destroys the ApolloPanObject.
int fiducialObservation(int fiducialNumber, double machine_x, double machine_y)
This method adds a measurement of the center of an apollo panoramic image fiducial mark for considera...
int clearFiducialObservation(int fiducialNumber)
This method removes a measurement of the center of an apollo panoramic image fiducial mark from consi...
double stdevR
standard deviation of residual vector lengths
Definition ApolloPanIO.h:90
int computeInteriorOrienation()
This method leverages all the fiducial obersatvions to caculate a series of affine transformations fo...
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.
double rotI[2]
Coefficients to rotate Image coordinates so that the right edge of the region is vertical.
Definition ApolloPanIO.h:63
int indeces[2]
indeces of the first and last fiducial marks included in this region
Definition ApolloPanIO.h:67
double rotM[2]
Coefficients to rotate machine coordinates so that the right edge of the region is vertical.
Definition ApolloPanIO.h:58
double mI
max rotated image y coordinate in the region
Definition ApolloPanIO.h:65
double A2I[6]
transformation coefficients to go to image coordinates
Definition ApolloPanIO.h:52
double mM
max rotate machine y coordinate in the region
Definition ApolloPanIO.h:66
double A2M[6]
transformation coefficients to go to machine coordinates
Definition ApolloPanIO.h:53
int flag
flag to tell if the observation has been made
Definition ApolloPanIO.h:74
double image[2]
theoretically perfect image coordinates
Definition ApolloPanIO.h:76
double mach[2]
machine coordinates of the fiducial mark
Definition ApolloPanIO.h:75
double residuals[2]
residuals of the fiducial mark measurement in machine coordinates
Definition ApolloPanIO.h:77