USGS

Isis 3.0 Object Programmers' Reference

Home

CubeCalculator.cpp
Go to the documentation of this file.
1 
23 #include <QVector>
24 
25 #include "CubeCalculator.h"
26 #include "IString.h"
27 #include "Statistics.h"
28 #include "Camera.h"
29 #include "Distance.h"
30 #include "Angle.h"
31 
32 using namespace std;
33 
34 namespace Isis {
35 
37  CubeCalculator::CubeCalculator() {
38  m_calculations = NULL;
39  m_methods = NULL;
40  // m_data was never used anywhere
41 // m_data = NULL;
42  m_dataDefinitions = NULL;
43  m_cubeStats = NULL;
44  m_cubeCameras = NULL;
45  m_cameraBuffers = NULL;
46 
47  m_calculations = new QVector<Calculations>();
48  m_methods = new QVector<void (Calculator:: *)(void)>();
49  // m_data was never used anywhere
50 // m_data = new QVector<QVector<double> >();
51  m_dataDefinitions = new QVector<DataValue>();
52  m_cubeStats = new QVector<Statistics *>();
53  m_cubeCameras = new QVector<Camera *>();
54  m_cameraBuffers = new QVector<CameraBuffers *>();
55 
56  m_outputSamples = 0;
57  }
58 
59 
61  CubeCalculator::~CubeCalculator() {
62  delete m_calculations;
63  delete m_methods;
64  delete m_dataDefinitions;
65  delete m_cubeStats;
66  delete m_cubeCameras;
67  delete m_cameraBuffers;
68 
69  m_calculations = NULL;
70  m_methods = NULL;
71  m_dataDefinitions = NULL;
72  m_cubeStats = NULL;
73  m_cubeCameras = NULL;
74  m_cameraBuffers = NULL;
75  }
76 
77 
78  void CubeCalculator::Clear() {
79  Calculator::Clear();
80 
81  if (m_calculations) {
82  m_calculations->clear();
83  }
84 
85  if (m_methods) {
86  m_methods->clear();
87  }
88 
89 // if (m_data) {
90 // m_data->clear();
91 // }
92 
93  if (m_dataDefinitions) {
94  m_dataDefinitions->clear();
95  }
96 
97  // m_cubeStats contains pointers to dynamic memory - need to free
98  if (m_cubeStats) {
99  for (int i = 0; i < m_cubeStats->size(); i++) {
100  delete (*m_cubeStats)[i];
101  (*m_cubeStats)[i] = NULL;
102  }
103  m_cubeStats->clear();
104  }
105 
106  if (m_cubeCameras) {
107  m_cubeCameras->clear();
108  }
109 
110  // m_cameraBuffers contains pointers to dynamic memory - need to free
111  if (m_cameraBuffers) {
112  for (int i = 0; i < m_cameraBuffers->size(); i++) {
113  delete (*m_cameraBuffers)[i];
114  (*m_cameraBuffers)[i] = NULL;
115  }
116  m_cameraBuffers->clear();
117  }
118  }
119 
120 
132  QVector<double> CubeCalculator::runCalculations(QVector<Buffer *> &cubeData, int curLine, int curBand) {
133  // For now we'll only process a single line in this method for our results. In order
134  // to do more powerful indexing, passing a list of cubes and the output cube will
135  // be necessary.
136  int methodIndex = 0;
137  int dataIndex = 0;
138  for (int currentCalculation = 0; currentCalculation < m_calculations->size();
139  currentCalculation++) {
140  if ((*m_calculations)[currentCalculation] == CallNextMethod) {
141  void (Calculator::*aMethod)() = (*m_methods)[methodIndex];
142  (this->*aMethod)();
143  methodIndex ++;
144  }
145  else {
146  DataValue &data = (*m_dataDefinitions)[dataIndex];
147  if (data.getType() == DataValue::Constant) {
148  Push(data.getConstant());
149  }
150  else if (data.getType() == DataValue::Band) {
151  Push(curBand);
152  }
153  else if (data.getType() == DataValue::Line) {
154  Push(curLine);
155  }
156  else if (data.getType() == DataValue::Sample) {
157  QVector<double> samples;
158  samples.resize(m_outputSamples);
159 
160  for (int i = 0; i < m_outputSamples; i++) {
161  samples[i] = i + 1;
162  }
163 
164  Push(samples);
165  }
166  else if (data.getType() == DataValue::CubeData) {
167  Push(*cubeData[data.getCubeIndex()]);
168  }
169  else if (data.getType() == DataValue::InaData) {
170  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getInaBuffer(curLine,m_outputSamples)));
171  }
172  else if (data.getType() == DataValue::EmaData) {
173  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getEmaBuffer(curLine,m_outputSamples)));
174  }
175  else if (data.getType() == DataValue::PhaData) {
176  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getPhaBuffer(curLine,m_outputSamples)));
177  }
178  else if (data.getType() == DataValue::InalData) {
179  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getInalBuffer(curLine,m_outputSamples)));
180  }
181  else if (data.getType() == DataValue::EmalData) {
182  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getEmalBuffer(curLine,m_outputSamples)));
183  }
184  else if (data.getType() == DataValue::PhalData) {
185  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getPhalBuffer(curLine,m_outputSamples)));
186  }
187  else if (data.getType() == DataValue::LatData) {
188  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getLatBuffer(curLine,m_outputSamples)));
189  }
190  else if (data.getType() == DataValue::LonData) {
191  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getLonBuffer(curLine,m_outputSamples)));
192  }
193  else if (data.getType() == DataValue::ResData) {
194  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getResBuffer(curLine,m_outputSamples)));
195  }
196  else if (data.getType() == DataValue::RadiusData) {
197  Push(*((*m_cameraBuffers)[data.getCubeIndex()]->getRadiusBuffer(curLine,m_outputSamples)));
198  }
199  else {
200  }
201 
202  dataIndex ++;
203  }
204  }
205 
206  if (StackSize() != 1) {
207  string msg = "Too many operands in the equation.";
208  throw IException(IException::Unknown, msg, _FILEINFO_);
209  }
210 
211  return Pop(true);
212  }
213 
214 
226  void CubeCalculator::prepareCalculations(QString equation,
227  QVector<Cube *> &inCubes,
228  Cube *outCube) {
229  Clear();
230 
231  m_outputSamples = outCube->sampleCount();
232 
233  IString eq = equation;
234  while (eq != "") {
235  IString token = eq.Token(" ");
236 
237  // Step through every part of the postfix equation and set up the appropriate
238  // action list based on the current token. Attempting to order if-else conditions
239  // in terms of what would probably be encountered more often.
240 
241  // Scalars
242  if (isdigit(token[0]) || token[0] == '.') {
243  m_calculations->push_back(PushNextData);
244  m_dataDefinitions->push_back(DataValue(DataValue::Constant,
245  token.ToDouble()));
246  }
247  // File, e.g. F1 = first file in list. Must come after any functions starting with 'f' that
248  // is not a cube.
249  else if (token[0] == 'f') {
250  IString tok(token.substr(1));
251  int file = tok.ToInteger() - 1;
252  if (file < 0 || file >= (int)inCubes.size()) {
253  QString msg = "Invalid file number [" + tok.ToQt() + "]";
254  throw IException(IException::Unknown, msg, _FILEINFO_);
255  }
256 
257  m_calculations->push_back(PushNextData);
258  m_dataDefinitions->push_back(DataValue(DataValue::CubeData, file));
259  }
260  else if (token == "band") {
261  m_calculations->push_back(PushNextData);
262  m_dataDefinitions->push_back(DataValue(DataValue::Band));
263  }
264  else if (token == "line") {
265  m_calculations->push_back(PushNextData);
266  m_dataDefinitions->push_back(DataValue(DataValue::Line));
267  }
268  else if (token == "sample") {
269  m_calculations->push_back(PushNextData);
270  m_dataDefinitions->push_back(DataValue(DataValue::Sample));
271  }
272  // Addition
273  else if (token == "+") {
274  addMethodCall(&Calculator::Add);
275  }
276 
277  // Subtraction
278  else if (token == "-") {
279  addMethodCall(&Calculator::Subtract);
280  }
281 
282  // Multiplication
283  else if (token == "*") {
284  addMethodCall(&Calculator::Multiply);
285  }
286 
287  // Division
288  else if (token == "/") {
289  addMethodCall(&Calculator::Divide);
290  }
291 
292  // Modulus
293  else if (token == "%") {
294  addMethodCall(&Calculator::Modulus);
295  }
296 
297  // Exponent
298  else if (token == "^") {
299  addMethodCall(&Calculator::Exponent);
300  }
301 
302  // Negative
303  else if (token == "--") {
304  addMethodCall(&Calculator::Negative);
305  }
306 
307  // Negative
308  else if (token == "neg") {
309  addMethodCall(&Calculator::Negative);
310  }
311 
312  // Left shift
313  else if (token == "<<") {
314  addMethodCall(&Calculator::LeftShift);
315  }
316 
317  // Right shift
318  else if (token == ">>") {
319  addMethodCall(&Calculator::RightShift);
320  }
321 
322  // Maximum In The Line
323  else if (token == "linemax") {
324  addMethodCall(&Calculator::MaximumLine);
325  }
326 
327  // Maximum Pixel on a per-pixel basis
328  else if (token == "max") {
329  addMethodCall(&Calculator::MaximumPixel);
330  }
331 
332  // Minimum In The Line
333  else if (token == "linemin") {
334  addMethodCall(&Calculator::MinimumLine);
335  }
336 
337  // Minimum Pixel on a per-pixel basis
338  else if (token == "min") {
339  addMethodCall(&Calculator::MinimumPixel);
340  }
341 
342  // Absolute value
343  else if (token == "abs") {
344  addMethodCall(&Calculator::AbsoluteValue);
345  }
346 
347  // Square root
348  else if (token == "sqrt") {
349  addMethodCall(&Calculator::SquareRoot);
350  }
351 
352  // Natural Log
353  else if (token == "log" || token == "ln") {
354  addMethodCall(&Calculator::Log);
355  }
356 
357  // Log base 10
358  else if (token == "log10") {
359  addMethodCall(&Calculator::Log10);
360  }
361 
362  // Pi
363  else if (token == "pi") {
364  m_calculations->push_back(PushNextData);
365  m_dataDefinitions->push_back(
366  DataValue(DataValue::Constant, PI)
367  );
368  }
369 
370  // e
371  else if (token == "e") {
372  m_calculations->push_back(PushNextData);
373  m_dataDefinitions->push_back(
374  DataValue(DataValue::Constant, E)
375  );
376  }
377 
378  else if (token == "rads") {
379  m_calculations->push_back(PushNextData);
380  m_dataDefinitions->push_back(
381  DataValue(DataValue::Constant, PI / 180.0)
382  );
383 
384  addMethodCall(&Calculator::Multiply);
385  }
386 
387  else if (token == "degs") {
388  m_calculations->push_back(PushNextData);
389  m_dataDefinitions->push_back(
390  DataValue(DataValue::Constant, 180.0 / PI)
391  );
392  addMethodCall(&Calculator::Multiply);
393  }
394 
395  // Sine
396  else if (token == "sin") {
397  addMethodCall(&Calculator::Sine);
398  }
399 
400  // Cosine
401  else if (token == "cos") {
402  addMethodCall(&Calculator::Cosine);
403  }
404 
405  // Tangent
406  else if (token == "tan") {
407  addMethodCall(&Calculator::Tangent);
408  }
409 
410  // Secant
411  else if (token == "sec") {
412  addMethodCall(&Calculator::Secant);
413  }
414 
415  // Cosecant
416  else if (token == "csc") {
417  addMethodCall(&Calculator::Cosecant);
418  }
419 
420  // Cotangent
421  else if (token == "cot") {
422  addMethodCall(&Calculator::Cotangent);
423  }
424 
425  // Arcsin
426  else if (token == "asin") {
427  addMethodCall(&Calculator::Arcsine);
428  }
429 
430  // Arccos
431  else if (token == "acos") {
432  addMethodCall(&Calculator::Arccosine);
433  }
434 
435  // Arctan
436  else if (token == "atan") {
437  addMethodCall(&Calculator::Arctangent);
438  }
439 
440  // Arctan2
441  else if (token == "atan2") {
442  addMethodCall(&Calculator::Arctangent2);
443  }
444 
445  // SineH
446  else if (token == "sinh") {
447  addMethodCall(&Calculator::SineH);
448  }
449 
450  // CosH
451  else if (token == "cosh") {
452  addMethodCall(&Calculator::CosineH);
453  }
454 
455  // TanH
456  else if (token == "tanh") {
457  addMethodCall(&Calculator::TangentH);
458  }
459 
460  // Less than
461  else if (token == "<") {
462  addMethodCall(&Calculator::LessThan);
463  }
464 
465  // Greater than
466  else if (token == ">") {
467  addMethodCall(&Calculator::GreaterThan);
468  }
469 
470  // Less than or equal
471  else if (token == "<=") {
472  addMethodCall(&Calculator::LessThanOrEqual);
473  }
474 
475  // Greater than or equal
476  else if (token == ">=") {
477  addMethodCall(&Calculator::GreaterThanOrEqual);
478  }
479 
480  // Equal
481  else if (token == "==") {
482  addMethodCall(&Calculator::Equal);
483  }
484 
485  // Not equal
486  else if (token == "!=") {
487  addMethodCall(&Calculator::NotEqual);
488  }
489 
490  // Maximum in a cube
491  else if (token == "cubemax") {
492  int cubeIndex = lastPushToCubeStats(inCubes);
493 
494  m_calculations->push_back(PushNextData);
495  m_dataDefinitions->push_back(
496  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->Maximum())
497  );
498  //TODO: Test for NULL Maximum
499  }
500 
501  // Maximum in a cube
502  else if (token == "cubemin") {
503  int cubeIndex = lastPushToCubeStats(inCubes);
504 
505  m_calculations->push_back(PushNextData);
506  m_dataDefinitions->push_back(
507  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->Minimum())
508  );
509  //TODO: Test for NULL Minimum
510  }
511 
512  // Average of a cube
513  else if (token == "cubeavg") {
514  int cubeIndex = lastPushToCubeStats(inCubes);
515 
516  m_calculations->push_back(PushNextData);
517  m_dataDefinitions->push_back(
518  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->Average())
519  );
520  //TODO: Test for NULL Average
521  }
522 
523  // Standard deviation of a cube
524  else if (token == "cubestd") {
525  int cubeIndex = lastPushToCubeStats(inCubes);
526 
527  m_calculations->push_back(PushNextData);
528  m_dataDefinitions->push_back(
529  DataValue(DataValue::Constant, (*m_cubeStats)[cubeIndex]->StandardDeviation())
530  );
531  //TODO: Test for NULL standard deviation
532  }
533 
534  // Center phase in a cube
535  else if ((token == "phac") || (token == "inac") || (token == "emac")) {
536  int cubeIndex = lastPushToCubeCameras(inCubes);
537 
538  double centerLine = inCubes[cubeIndex]->lineCount() / 2.0 + 0.5;
539  double centerSamp = inCubes[cubeIndex]->sampleCount() / 2.0 + 0.5;
540  Camera *cam = (*m_cubeCameras)[cubeIndex];
541 
542  if (cam->SetImage(centerSamp, centerLine)) {
543  m_calculations->push_back(PushNextData);
544  if (token == "inac") {
545  m_dataDefinitions->push_back(DataValue(DataValue::Constant, cam->IncidenceAngle()));
546  }
547  else if (token == "emac") {
548  m_dataDefinitions->push_back(DataValue(DataValue::Constant, cam->EmissionAngle()));
549  }
550  else {
551  m_dataDefinitions->push_back(DataValue(DataValue::Constant, cam->PhaseAngle()));
552  }
553  }
554  else {
555  string msg = "Unable to compute illumination angles at image center for operator [";
556  msg += token + "] using input file [f" + IString(cubeIndex + 1) + "]";
557  throw IException(IException::Unknown, msg, _FILEINFO_);
558  }
559  }
560 
561  // Incidence on the ellipsoid
562  else if (token == "ina") {
563  int cubeIndex = lastPushToCubeCameras(inCubes);
564  (*m_cameraBuffers)[cubeIndex]->enableInaBuffer();
565 
566  m_calculations->push_back(PushNextData);
567  m_dataDefinitions->push_back(DataValue(DataValue::InaData, cubeIndex));
568  }
569 
570  // Emission on the ellipsoid
571  else if (token == "ema") {
572  int cubeIndex = lastPushToCubeCameras(inCubes);
573  (*m_cameraBuffers)[cubeIndex]->enableEmaBuffer();
574 
575  m_calculations->push_back(PushNextData);
576  m_dataDefinitions->push_back(DataValue(DataValue::EmaData, cubeIndex));
577  }
578 
579  // Phase on the ellipsoid
580  else if (token == "pha") {
581  int cubeIndex = lastPushToCubeCameras(inCubes);
582  (*m_cameraBuffers)[cubeIndex]->enablePhaBuffer();
583 
584  m_calculations->push_back(PushNextData);
585  m_dataDefinitions->push_back(DataValue(DataValue::PhaData, cubeIndex));
586  }
587 
588  // Incidence on the DTM
589  else if (token == "inal") {
590  int cubeIndex = lastPushToCubeCameras(inCubes);
591  (*m_cameraBuffers)[cubeIndex]->enableInalBuffer();
592 
593  m_calculations->push_back(PushNextData);
594  m_dataDefinitions->push_back(DataValue(DataValue::InalData, cubeIndex));
595  }
596 
597  // Emission on the DTM
598  else if (token == "emal") {
599  int cubeIndex = lastPushToCubeCameras(inCubes);
600  (*m_cameraBuffers)[cubeIndex]->enableEmalBuffer();
601 
602  m_calculations->push_back(PushNextData);
603  m_dataDefinitions->push_back(DataValue(DataValue::EmalData, cubeIndex));
604  }
605 
606  // Phase on the ellipsoid
607  else if (token == "phal") {
608  int cubeIndex = lastPushToCubeCameras(inCubes);
609  (*m_cameraBuffers)[cubeIndex]->enablePhalBuffer();
610 
611  m_calculations->push_back(PushNextData);
612  m_dataDefinitions->push_back(DataValue(DataValue::PhalData, cubeIndex));
613  }
614 
615  // Latitude
616  else if (token == "lat") {
617  int cubeIndex = lastPushToCubeCameras(inCubes);
618  (*m_cameraBuffers)[cubeIndex]->enableLatBuffer();
619 
620  m_calculations->push_back(PushNextData);
621  m_dataDefinitions->push_back(DataValue(DataValue::LatData, cubeIndex));
622  }
623 
624  // Longitude
625  else if (token == "lon") {
626  int cubeIndex = lastPushToCubeCameras(inCubes);
627  (*m_cameraBuffers)[cubeIndex]->enableLonBuffer();
628 
629  m_calculations->push_back(PushNextData);
630  m_dataDefinitions->push_back(DataValue(DataValue::LonData, cubeIndex));
631  }
632 
633  // Pixel resolution
634  else if (token == "res") {
635  int cubeIndex = lastPushToCubeCameras(inCubes);
636  (*m_cameraBuffers)[cubeIndex]->enableResBuffer();
637 
638  m_calculations->push_back(PushNextData);
639  m_dataDefinitions->push_back(DataValue(DataValue::ResData, cubeIndex));
640  }
641 
642  // Local Radius
643  else if (token == "radius") {
644  int cubeIndex = lastPushToCubeCameras(inCubes);
645  (*m_cameraBuffers)[cubeIndex]->enableRadiusBuffer();
646 
647  m_calculations->push_back(PushNextData);
648  m_dataDefinitions->push_back(DataValue(DataValue::RadiusData, cubeIndex));
649  }
650 
651  // Ignore empty token
652  else if (token == "") {
653  }
654 
655  else {
656  string msg = "Unidentified operator [";
657  msg += token + "]";
658  throw IException(IException::Unknown, msg, _FILEINFO_);
659  }
660  } // while loop
661  }
662 
663  int CubeCalculator::lastPushToCubeStats(QVector<Cube *> &inCubes) {
664  if (!m_calculations->size()) {
665  string msg = "Not sure which file to get statistics from";
666  throw IException(IException::Unknown, msg, _FILEINFO_);
667  }
668 
669  if ((*m_calculations)[m_calculations->size() - 1] != PushNextData) {
670  string msg = "This function must not contain calculations,";
671  msg += " only input cubes may be specified.";
672  throw IException(IException::Unknown, msg, _FILEINFO_);
673  }
674 
675  m_calculations->pop_back();
676 
677  // This must have data if calculations had data that equaled push data
678  DataValue lastData = (*m_dataDefinitions)[m_dataDefinitions->size() - 1];
679 
680  if (lastData.getType() != DataValue::CubeData) {
681  string msg = "This function must not contain constants,";
682  msg += " only input cubes may be specified.";
683  throw IException(IException::Unknown, msg, _FILEINFO_);
684  }
685 
686  int cubeStatsIndex = lastData.getCubeIndex();
687  m_dataDefinitions->pop_back();
688 
689  // Member variables are now cleaned up, we need to verify the stats exists
690 
691  // Make sure room exists in the vector
692  while (m_cubeStats->size() < cubeStatsIndex + 1) {
693  m_cubeStats->push_back(NULL);
694  }
695 
696  // Now we can for sure put the stats object in the right place... put it
697  // there
698  if ((*m_cubeStats)[cubeStatsIndex] == NULL) {
699  (*m_cubeStats)[cubeStatsIndex] = inCubes[cubeStatsIndex]->statistics();
700  }
701 
702  return cubeStatsIndex;
703  }
704 
705 
706  int CubeCalculator::lastPushToCubeCameras(QVector<Cube *> &inCubes) {
707  if (!m_calculations->size()) {
708  string msg = "Not sure which file to get cameras from";
709  throw IException(IException::Unknown, msg, _FILEINFO_);
710  }
711 
712  if ((*m_calculations)[m_calculations->size() - 1] != PushNextData) {
713  string msg = "This function must not contain calculations,";
714  msg += " only input cubes may be specified.";
715  throw IException(IException::Unknown, msg, _FILEINFO_);
716  }
717 
718  m_calculations->pop_back();
719 
720  // This must have data if calculations had data that equaled push data
721  DataValue lastData = (*m_dataDefinitions)[m_dataDefinitions->size() - 1];
722 
723  if (lastData.getType() != DataValue::CubeData) {
724  string msg = "This function must not contain constants,";
725  msg += " only input cubes may be specified.";
726  throw IException(IException::Unknown, msg, _FILEINFO_);
727  }
728 
729  int cubeIndex = lastData.getCubeIndex();
730  m_dataDefinitions->pop_back();
731 
732  // Member variables are now cleaned up, we need to verify the camera exists
733 
734  // Make sure room exists in the vector
735  while (m_cubeCameras->size() < cubeIndex + 1) {
736  m_cubeCameras->push_back(NULL);
737  }
738 
739  while (m_cameraBuffers->size() < cubeIndex + 1) {
740  m_cameraBuffers->push_back(NULL);
741  }
742 
743  // Now we can for sure put the camera object in the right place... put it
744  // there
745  if ((*m_cubeCameras)[cubeIndex] == NULL) {
746  Camera *cam;
747  try {
748  cam = inCubes[cubeIndex]->camera();
749  if (cam == NULL) {
750  string msg = "This function requires a camera and the input cube does";
751  msg += " not have one. You may need to run spiceinit";
752  throw IException(IException::Unknown, msg, _FILEINFO_);
753  }
754  }
755  catch (IException &e) {
756  string msg = "This function requires a camera and the input cube does";
757  msg += " not have one. You may need to run spiceinit";
758  throw IException(e, IException::Unknown, msg, _FILEINFO_);
759  }
760 
761  (*m_cubeCameras)[cubeIndex] = cam;
762  (*m_cameraBuffers)[cubeIndex] = new CameraBuffers(cam);
763  }
764 
765  return cubeIndex;
766  }
767 
768 
775  void CubeCalculator::addMethodCall(void (Calculator::*method)(void)) {
776  m_calculations->push_back(CallNextMethod);
777  m_methods->push_back(method);
778  }
779 
780 
781 
782 
783 
784  CameraBuffers::CameraBuffers(Camera *camera) {
785  m_camera = camera;
786  m_phaBuffer = NULL;
787  m_inaBuffer = NULL;
788  m_emaBuffer = NULL;
789  m_phalBuffer = NULL;
790  m_inalBuffer = NULL;
791  m_emalBuffer = NULL;
792  m_resBuffer = NULL;
793  m_latBuffer = NULL;
794  m_lonBuffer = NULL;
795  m_radiusBuffer = NULL;
796 
797  m_lastLine = -1;
798  }
799 
800  CameraBuffers::~CameraBuffers() {
801  delete m_phaBuffer;
802  delete m_inaBuffer;
803  delete m_emaBuffer;
804  delete m_phalBuffer;
805  delete m_inalBuffer;
806  delete m_emalBuffer;
807  delete m_resBuffer;
808  delete m_latBuffer;
809  delete m_lonBuffer;
810  delete m_radiusBuffer;
811 
812  m_phaBuffer = NULL;
813  m_inaBuffer = NULL;
814  m_emaBuffer = NULL;
815  m_phalBuffer = NULL;
816  m_inalBuffer = NULL;
817  m_emalBuffer = NULL;
818  m_resBuffer = NULL;
819  m_latBuffer = NULL;
820  m_lonBuffer = NULL;
821  m_radiusBuffer = NULL;
822  }
823 
824  void CameraBuffers::enablePhaBuffer() {
825  if (!m_phaBuffer) m_phaBuffer = new QVector<double>;
826  }
827 
828  void CameraBuffers::enableInaBuffer() {
829  if (!m_inaBuffer) m_inaBuffer = new QVector<double>;
830  }
831 
832  void CameraBuffers::enableEmaBuffer() {
833  if (!m_emaBuffer) m_emaBuffer = new QVector<double>;
834  }
835 
836  void CameraBuffers::enableLatBuffer() {
837  if (!m_latBuffer) m_latBuffer = new QVector<double>;
838  }
839 
840  void CameraBuffers::enableLonBuffer() {
841  if (!m_lonBuffer) m_lonBuffer = new QVector<double>;
842  }
843 
844  void CameraBuffers::enableResBuffer() {
845  if (!m_resBuffer) m_resBuffer = new QVector<double>;
846  }
847 
848  void CameraBuffers::enableRadiusBuffer() {
849  if (!m_radiusBuffer) m_radiusBuffer = new QVector<double>;
850  }
851 
852  void CameraBuffers::enablePhalBuffer() {
853  if (!m_phalBuffer) m_phalBuffer = new QVector<double>;
854  }
855 
856  void CameraBuffers::enableInalBuffer() {
857  if (!m_inalBuffer) m_inalBuffer = new QVector<double>;
858  }
859 
860  void CameraBuffers::enableEmalBuffer() {
861  if (!m_emalBuffer) m_emalBuffer = new QVector<double>;
862  }
863 
864  QVector<double> *CameraBuffers::getPhaBuffer(int currentLine, int ns) {
865  loadBuffers(currentLine,ns);
866  return m_phaBuffer;
867  }
868 
869  QVector<double> *CameraBuffers::getInaBuffer(int currentLine, int ns) {
870  loadBuffers(currentLine,ns);
871  return m_inaBuffer;
872  }
873 
874  QVector<double> *CameraBuffers::getEmaBuffer(int currentLine, int ns) {
875  loadBuffers(currentLine,ns);
876  return m_emaBuffer;
877  }
878 
879  QVector<double> *CameraBuffers::getLatBuffer(int currentLine, int ns) {
880  loadBuffers(currentLine,ns);
881  return m_latBuffer;
882  }
883 
884  QVector<double> *CameraBuffers::getLonBuffer(int currentLine, int ns) {
885  loadBuffers(currentLine,ns);
886  return m_lonBuffer;
887  }
888 
889  QVector<double> *CameraBuffers::getResBuffer(int currentLine, int ns) {
890  loadBuffers(currentLine,ns);
891  return m_resBuffer;
892  }
893 
894  QVector<double> *CameraBuffers::getRadiusBuffer(int currentLine, int ns) {
895  loadBuffers(currentLine,ns);
896  return m_radiusBuffer;
897  }
898 
899  QVector<double> *CameraBuffers::getPhalBuffer(int currentLine, int ns) {
900  loadBuffers(currentLine,ns);
901  return m_phalBuffer;
902  }
903 
904  QVector<double> *CameraBuffers::getInalBuffer(int currentLine, int ns) {
905  loadBuffers(currentLine,ns);
906  return m_inalBuffer;
907  }
908 
909  QVector<double> *CameraBuffers::getEmalBuffer(int currentLine, int ns) {
910  loadBuffers(currentLine,ns);
911  return m_emalBuffer;
912  }
913 
914  void CameraBuffers::loadBuffers(int currentLine, int ns) {
915  if (currentLine != m_lastLine) {
916  m_lastLine = currentLine;
917 
918  // Resize buffers if necessary
919  if (m_phaBuffer) m_phaBuffer->resize(ns);
920  if (m_inaBuffer) m_inaBuffer->resize(ns);
921  if (m_emaBuffer) m_emaBuffer->resize(ns);
922  if (m_latBuffer) m_latBuffer->resize(ns);
923  if (m_lonBuffer) m_lonBuffer->resize(ns);
924  if (m_resBuffer) m_resBuffer->resize(ns);
925  if (m_radiusBuffer) m_radiusBuffer->resize(ns);
926  if (m_phalBuffer) m_phalBuffer->resize(ns);
927  if (m_inalBuffer) m_inalBuffer->resize(ns);
928  if (m_emalBuffer) m_emalBuffer->resize(ns);
929 
930  for (int i = 0; i < ns; i++) {
931  if (m_camera->SetImage(i + 1, currentLine)) {
932  if (m_phaBuffer) (*m_phaBuffer)[i] = m_camera->PhaseAngle();
933  if (m_inaBuffer) (*m_inaBuffer)[i] = m_camera->IncidenceAngle();
934  if (m_emaBuffer) (*m_emaBuffer)[i] = m_camera->EmissionAngle();
935  if (m_latBuffer) (*m_latBuffer)[i] = m_camera->UniversalLatitude();
936  if (m_lonBuffer) (*m_lonBuffer)[i] = m_camera->UniversalLongitude();
937  if (m_resBuffer) (*m_resBuffer)[i] = m_camera->PixelResolution();
938  if (m_radiusBuffer) (*m_radiusBuffer)[i] = m_camera->LocalRadius().meters();
939  if (m_phalBuffer || m_inalBuffer || m_emalBuffer) {
940  Angle phal, inal, emal;
941  bool okay;
942  m_camera->LocalPhotometricAngles(phal, inal, emal, okay);
943  if (okay) {
944  if (m_phalBuffer) (*m_phalBuffer)[i] = phal.degrees();
945  if (m_inalBuffer) (*m_inalBuffer)[i] = inal.degrees();
946  if (m_emalBuffer) (*m_emalBuffer)[i] = emal.degrees();
947  }
948  else {
949  if (m_phalBuffer) (*m_phalBuffer)[i] = NAN;
950  if (m_inalBuffer) (*m_inalBuffer)[i] = NAN;
951  if (m_emalBuffer) (*m_emalBuffer)[i] = NAN;
952  }
953  }
954  }
955  else {
956  if (m_phaBuffer) (*m_phaBuffer)[i] = NAN;
957  if (m_inaBuffer) (*m_inaBuffer)[i] = NAN;
958  if (m_emaBuffer) (*m_emaBuffer)[i] = NAN;
959  if (m_latBuffer) (*m_latBuffer)[i] = NAN;
960  if (m_lonBuffer) (*m_lonBuffer)[i] = NAN;
961  if (m_resBuffer) (*m_resBuffer)[i] = NAN;
962  if (m_radiusBuffer) (*m_radiusBuffer)[i] = NAN;
963  if (m_phalBuffer) (*m_phalBuffer)[i] = NAN;
964  if (m_inalBuffer) (*m_inalBuffer)[i] = NAN;
965  if (m_emalBuffer) (*m_emalBuffer)[i] = NAN;
966  }
967  }
968  }
969  }
970 
971 } // End of namespace Isis
972