USGS

Isis 3.0 Object Programmers' Reference

Home

ControlPoint.cpp
1 #include "IsisDebug.h"
2 #include "ControlPoint.h"
3 
4 #include <boost/numeric/ublas/symmetric.hpp>
5 #include <boost/numeric/ublas/io.hpp>
6 
7 #include <QDebug>
8 #include <QHash>
9 #include <QString>
10 #include <QStringList>
11 
12 #include "Application.h"
13 #include "CameraDetectorMap.h"
14 #include "CameraDistortionMap.h"
15 #include "CameraFocalPlaneMap.h"
16 #include "CameraGroundMap.h"
17 #include "ControlMeasure.h"
18 #include "ControlMeasureLogData.h"
19 #include "ControlNet.h"
20 #include "ControlNetFile.h"
21 #include "ControlNetFile.h"
22 #include "ControlNetFileV0002.pb.h"
23 #include "Cube.h"
24 #include "IString.h"
25 #include "Latitude.h"
26 #include "Longitude.h"
27 #include "PvlObject.h"
28 #include "SerialNumberList.h"
29 #include "SpecialPixel.h"
30 #include "Statistics.h"
31 
32 using boost::numeric::ublas::symmetric_matrix;
33 using boost::numeric::ublas::upper;
34 using namespace std;
35 
36 namespace Isis {
43  ControlPoint::ControlPoint() : invalid(false) {
44  measures = NULL;
45  cubeSerials = NULL;
46 
48  cubeSerials = new QStringList;
49 
50  type = Free;
51  dateTime = "";
52  editLock = false;
53  ignore = false;
54  jigsawRejected = false;
55  referenceExplicitlySet = false;
56  aprioriSurfacePointSource = SurfacePointSource::None;
57  aprioriRadiusSource = RadiusSource::None;
58  parentNetwork = NULL;
59  referenceMeasure = NULL;
61  constraintStatus.reset();
62  }
63 
64 
71  measures = NULL;
72  cubeSerials = NULL;
73  referenceMeasure = NULL;
74  parentNetwork = NULL;
75 
76  editLock = false;
77 
79  cubeSerials = new QStringList;
80 
81  QListIterator<QString> i(*other.cubeSerials);
82  while (i.hasNext()) {
83  QString sn = i.next();
84 
85  const ControlMeasure *otherCm = other.GetMeasure(sn);
86  ControlMeasure *newMeasure = new ControlMeasure(*otherCm);
87  AddMeasure(newMeasure);
88 
89  if (other.referenceMeasure == otherCm)
90  SetRefMeasure(newMeasure);
91  }
92 
93  id = other.id;
94  chooserName = other.chooserName;
95  dateTime = other.dateTime;
96  type = other.type;
97  invalid = other.invalid;
98  editLock = other.editLock;
101  ignore = other.ignore;
110  }
111 
112 
122  const Distance &majorRad, const Distance &minorRad,
123  const Distance &polarRad) {
124  measures = NULL;
125  cubeSerials = NULL;
126  referenceMeasure = NULL;
128  measures = new QHash< QString, ControlMeasure * >;
129  cubeSerials = new QStringList;
130 
131  id = fileEntry.id().c_str();
132  dateTime = "";
133  aprioriSurfacePointSource = SurfacePointSource::None;
134  aprioriRadiusSource = RadiusSource::None;
135 
136  chooserName = fileEntry.choosername().c_str();
137  dateTime = fileEntry.datetime().c_str();
138  editLock = false;
139 
140  parentNetwork = NULL;
141 
142  switch (fileEntry.type()) {
143  case ControlPointFileEntryV0002_PointType_obsolete_Tie:
144  case ControlPointFileEntryV0002_PointType_Free:
145  type = Free;
146  break;
147  case ControlPointFileEntryV0002_PointType_Constrained:
148  type = Constrained;
149  break;
150  case ControlPointFileEntryV0002_PointType_obsolete_Ground:
151  case ControlPointFileEntryV0002_PointType_Fixed:
152  type = Fixed;
153  break;
154  default:
155  QString msg = "Point type is invalid.";
157  }
158 
159  ignore = fileEntry.ignore();
160  jigsawRejected = fileEntry.jigsawrejected();
161 
162  // Read apriori keywords
163  if (fileEntry.has_apriorisurfpointsource()) {
164  switch (fileEntry.apriorisurfpointsource()) {
165  case ControlPointFileEntryV0002_AprioriSource_None:
166  aprioriSurfacePointSource = SurfacePointSource::None;
167  break;
168 
169  case ControlPointFileEntryV0002_AprioriSource_User:
170  aprioriSurfacePointSource = SurfacePointSource::User;
171  break;
172 
173  case ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures:
174  aprioriSurfacePointSource = SurfacePointSource::AverageOfMeasures;
175  break;
176 
177  case ControlPointFileEntryV0002_AprioriSource_Reference:
178  aprioriSurfacePointSource = SurfacePointSource::Reference;
179  break;
180 
181  case ControlPointFileEntryV0002_AprioriSource_Basemap:
182  aprioriSurfacePointSource = SurfacePointSource::Basemap;
183  break;
184 
185  case ControlPointFileEntryV0002_AprioriSource_BundleSolution:
186  aprioriSurfacePointSource = SurfacePointSource::BundleSolution;
187  break;
188 
189  case ControlPointFileEntryV0002_AprioriSource_Ellipsoid:
190  case ControlPointFileEntryV0002_AprioriSource_DEM:
191  break;
192  }
193  }
194 
195  if (fileEntry.has_apriorisurfpointsourcefile()) {
196  aprioriSurfacePointSourceFile = fileEntry.apriorisurfpointsourcefile().c_str();
197  }
198 
199  if (fileEntry.has_aprioriradiussource()) {
200  switch (fileEntry.aprioriradiussource()) {
201  case ControlPointFileEntryV0002_AprioriSource_None:
202  aprioriRadiusSource = RadiusSource::None;
203  break;
204  case ControlPointFileEntryV0002_AprioriSource_User:
205  aprioriRadiusSource = RadiusSource::User;
206  break;
207  case ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures:
208  aprioriRadiusSource = RadiusSource::AverageOfMeasures;
209  break;
210  case ControlPointFileEntryV0002_AprioriSource_Ellipsoid:
211  aprioriRadiusSource = RadiusSource::Ellipsoid;
212  break;
213  case ControlPointFileEntryV0002_AprioriSource_DEM:
214  aprioriRadiusSource = RadiusSource::DEM;
215  break;
216  case ControlPointFileEntryV0002_AprioriSource_BundleSolution:
217  aprioriRadiusSource = RadiusSource::BundleSolution;
218  break;
219 
220  case ControlPointFileEntryV0002_AprioriSource_Reference:
221  case ControlPointFileEntryV0002_AprioriSource_Basemap:
222  break;
223  }
224  }
225 
226  if (fileEntry.has_aprioriradiussourcefile()) {
227  aprioriRadiusSourceFile = fileEntry.aprioriradiussourcefile().c_str();
228  }
229 
230  constraintStatus.reset();
231 
232  if (fileEntry.has_apriorix() && fileEntry.has_aprioriy() &&
233  fileEntry.has_aprioriz()) {
234  SurfacePoint apriori(
235  Displacement(fileEntry.apriorix(), Displacement::Meters),
236  Displacement(fileEntry.aprioriy(), Displacement::Meters),
237  Displacement(fileEntry.aprioriz(), Displacement::Meters));
238 
239  if (fileEntry.aprioricovar_size() > 0) {
240  symmetric_matrix<double, upper> covar;
241  covar.resize(3);
242  covar.clear();
243  covar(0, 0) = fileEntry.aprioricovar(0);
244  covar(0, 1) = fileEntry.aprioricovar(1);
245  covar(0, 2) = fileEntry.aprioricovar(2);
246  covar(1, 1) = fileEntry.aprioricovar(3);
247  covar(1, 2) = fileEntry.aprioricovar(4);
248  covar(2, 2) = fileEntry.aprioricovar(5);
249  apriori.SetRectangularMatrix(covar);
250 
251  if (Displacement(covar(0, 0), Displacement::Meters).isValid() ||
252  Displacement(covar(1, 1), Displacement::Meters).isValid()) {
253  if (fileEntry.latitudeconstrained())
255  if (fileEntry.longitudeconstrained())
256  constraintStatus.set(LongitudeConstrained);
257  if (fileEntry.radiusconstrained())
258  constraintStatus.set(RadiusConstrained);
259  }
260  else if (Displacement(covar(2, 2), Displacement::Meters).isValid()) {
261  if (fileEntry.latitudeconstrained())
263  if (fileEntry.radiusconstrained())
264  constraintStatus.set(RadiusConstrained);
265  }
266  }
267 
268  aprioriSurfacePoint = apriori;
269  }
270 
271  if (fileEntry.has_adjustedx() &&
272  fileEntry.has_adjustedy() &&
273  fileEntry.has_adjustedz()) {
274  SurfacePoint adjusted(
275  Displacement(fileEntry.adjustedx(), Displacement::Meters),
276  Displacement(fileEntry.adjustedy(), Displacement::Meters),
277  Displacement(fileEntry.adjustedz(), Displacement::Meters));
278 
279  if (fileEntry.adjustedcovar_size() > 0) {
280  symmetric_matrix<double, upper> covar;
281  covar.resize(3);
282  covar.clear();
283  covar(0, 0) = fileEntry.adjustedcovar(0);
284  covar(0, 1) = fileEntry.adjustedcovar(1);
285  covar(0, 2) = fileEntry.adjustedcovar(2);
286  covar(1, 1) = fileEntry.adjustedcovar(3);
287  covar(1, 2) = fileEntry.adjustedcovar(4);
288  covar(2, 2) = fileEntry.adjustedcovar(5);
289  adjusted.SetRectangularMatrix(covar);
290  }
291 
292  adjustedSurfacePoint = adjusted;
293  }
294 
295  if (majorRad.isValid() && minorRad.isValid() && polarRad.isValid()) {
296  aprioriSurfacePoint.SetRadii(majorRad, minorRad, polarRad);
297  adjustedSurfacePoint.SetRadii(majorRad, minorRad, polarRad);
298  }
299 
300  referenceExplicitlySet = false;
301 
302  for (int m = 0 ; m < fileEntry.measures_size() ; m++) {
303  ControlMeasure *measure = new ControlMeasure(fileEntry.measures(m));
304  AddMeasure(measure);
305  }
306 
307  if (fileEntry.has_referenceindex()) {
308  SetRefMeasure((*measures)[cubeSerials->at(fileEntry.referenceindex())]);
309  }
310 
311  // Set edit lock last
312  editLock = fileEntry.editlock();
313  }
314 
315 
321  ControlPoint::ControlPoint(const QString &newId) : invalid(false) {
322  parentNetwork = NULL;
323  measures = NULL;
324  referenceMeasure = NULL;
326  measures = new QHash< QString, ControlMeasure * >;
327  cubeSerials = new QStringList;
328 
329  id = newId;
330  type = Free;
331  editLock = false;
332  jigsawRejected = false;
333  referenceExplicitlySet = false;
334  ignore = false;
335  aprioriSurfacePointSource = SurfacePointSource::None;
336  aprioriRadiusSource = RadiusSource::None;
337  constraintStatus.reset();
338  }
339 
345  if (measures != NULL) {
346  QList< QString > keys = measures->keys();
347  for (int i = 0; i < keys.size(); i++) {
348  delete(*measures)[keys[i]];
349  (*measures)[keys[i]] = NULL;
350  }
351 
352  delete measures;
353  measures = NULL;
354  }
355 
356  if (cubeSerials) {
357  delete cubeSerials;
358  cubeSerials = NULL;
359  }
360 
361  referenceMeasure = NULL;
362  }
363 
410 
411  }
412 
413 
421  PointModified();
422  AddMeasure(measure);
423  }
424 
425 
431  // Make sure measure is unique
432  foreach(ControlMeasure * m, measures->values()) {
433  if (m->GetCubeSerialNumber() == measure->GetCubeSerialNumber()) {
434  QString msg = "The SerialNumber is not unique. A measure with "
435  "serial number [" + measure->GetCubeSerialNumber() + "] already "
436  "exists for ControlPoint [" + GetId() + "]";
438  }
439  }
440 
441  if (!measures->size()) {
442  ASSERT(referenceMeasure == NULL);
443  referenceMeasure = measure;
444  }
445  else if (referenceMeasure->IsIgnored() && !measure->IsIgnored() &&
446  !IsReferenceExplicit() && !IsEditLocked()) {
447  // The current "implicit" reference is ignored, but this new measure
448  // isn't, and the point is not edit locked, so make this measure the new
449  // reference
450  referenceMeasure = measure;
451  }
452 
453  measure->parentPoint = this;
454  QString newSerial = measure->GetCubeSerialNumber();
455  measures->insert(newSerial, measure);
456  cubeSerials->append(newSerial);
457 
458  // notify parent network if we have one
459  if (parentNetwork) {
460  parentNetwork->measureAdded(measure);
461  parentNetwork->emitNetworkStructureModified();
462  }
463  }
464 
465 
473  void ControlPoint::ValidateMeasure(QString serialNumber) const {
474  if (!measures->contains(serialNumber)) {
475  QString msg = "No measure with serial number [" + serialNumber +
476  "] is owned by this point";
478  }
479  }
480 
481 
488  int ControlPoint::Delete(QString serialNumber) {
489  ValidateMeasure(serialNumber);
490  ControlMeasure *cm = (*measures)[serialNumber];
491 
492  if (cm->IsEditLocked())
493  return ControlMeasure::MeasureLocked;
494 
495  // remove measure from the point's data structures
496  measures->remove(serialNumber);
497  cubeSerials->removeAt(cubeSerials->indexOf(serialNumber));
498 
499  // update the reference measure
500  if (cubeSerials->size()) {
501  if (referenceMeasure == cm) {
502  referenceMeasure = (*measures)[cubeSerials->at(0)];
503  referenceExplicitlySet = false;
504  }
505  }
506  else {
507  referenceMeasure = NULL;
508  }
509 
510  // notify parent network of the change
511  if (parentNetwork) {
513 
514  if (!IsIgnored() && !cm->IsIgnored())
515  parentNetwork->emitNetworkStructureModified();
516  }
517 
518  delete cm;
519  cm = NULL;
520 
521  PointModified();
522 
523  return ControlMeasure::Success;
524  }
525 
526 
534  ASSERT(measure);
535  return Delete(measure->GetCubeSerialNumber());
536  }
537 
538 
545  int ControlPoint::Delete(int index) {
546  if (index < 0 || index >= cubeSerials->size()) {
547  QString msg = "index [" + QString(index) + "] out of bounds";
549  }
550 
551  return Delete(cubeSerials->at(index));
552  }
553 
554 
561  if (IsEditLocked())
562  return PointLocked;
563 
564  aprioriSurfacePointSource = SurfacePointSource::None;
566  aprioriRadiusSource = RadiusSource::None;
568 
570  constraintStatus.reset();
571 
572  return Success;
573  }
574 
575 
582  ControlMeasure *ControlPoint::GetMeasure(QString serialNumber) {
583  ValidateMeasure(serialNumber);
584  return (*measures)[serialNumber];
585  }
586 
587 
594  const ControlMeasure *ControlPoint::GetMeasure(QString serialNumber) const {
595  ValidateMeasure(serialNumber);
596  return measures->value(serialNumber);
597  }
598 
599 
600  const ControlMeasure *ControlPoint::GetMeasure(int index) const {
601  if (index < 0 || index >= cubeSerials->size()) {
602  QString msg = "Index [" + toString(index) + "] out of range";
604  }
605 
606  return GetMeasure(cubeSerials->at(index));
607  }
608 
609 
610  ControlMeasure *ControlPoint::GetMeasure(int index) {
611  if (index < 0 || index >= cubeSerials->size()) {
612  QString msg = "Index [" + toString(index) + "] out of range";
613  throw IException(IException::Programmer, msg, _FILEINFO_);
614  }
615 
616  return GetMeasure(cubeSerials->at(index));
617  }
618 
619 
626  if (referenceMeasure == NULL) {
627  QString msg = "Control point [" + GetId() + "] has no reference measure!";
629  }
630 
631  return referenceMeasure;
632  }
633 
634 
639  if (referenceMeasure == NULL) {
640  QString msg = "Control point [" + GetId() + "] has no reference measure!";
642  }
643 
644  return referenceMeasure;
645  }
646 
647 
656  if (editLock)
657  return PointLocked;
658  chooserName = name;
659  return Success;
660  }
661 
662 
672  if (editLock)
673  return PointLocked;
674  dateTime = newDateTime;
675  return Success;
676  }
677 
678 
689  editLock = lock;
690  return Success;
691  }
692 
693 
703  jigsawRejected = reject;
704  return Success;
705  }
706 
707 
716  if (editLock)
717  return PointLocked;
718  QString oldId = id;
719  id = newId;
720  if (parentNetwork)
721  parentNetwork->UpdatePointReference(this, oldId);
722  return Success;
723  }
724 
725 
732  if (editLock)
733  return PointLocked;
734 
735  ASSERT(cm);
737  return Success;
738  }
739 
740 
747  if (editLock)
748  return PointLocked;
749 
750  if (index < 0 || index >= cubeSerials->size()) {
751  QString msg = "Index [";
752  msg += toString(index) + "] out of range";
754  }
755 
756  SetExplicitReference((*measures)[cubeSerials->at(index)]);
757  return Success;
758  }
759 
760 
767  if (editLock)
768  return PointLocked;
769 
770  if (!cubeSerials->contains(sn)) {
771  QString msg = "Point [" + id + "] has no measure with serial number [" +
772  sn + "]";
774  }
775 
776  SetExplicitReference((*measures)[sn]);
777  return Success;
778  }
779 
780 
800  referenceExplicitlySet = true;
801  referenceMeasure = measure;
802  }
803 
804 
812  if (editLock)
813  return PointLocked;
814 
815  bool oldStatus = ignore;
816  ignore = newIgnoreStatus;
817 
818  // only update if there was a change in status
819  if (oldStatus != ignore) {
820  PointModified();
821  if (parentNetwork) {
822  foreach(ControlMeasure * cm, measures->values()) {
823  if (!cm->IsIgnored()) {
824  if (ignore)
825  parentNetwork->measureIgnored(cm);
826  else
828  }
829  }
830  parentNetwork->emitNetworkStructureModified();
831  }
832  }
833 
834  return Success;
835  }
836 
837 
852  SurfacePoint newSurfacePoint) {
853  PointModified();
854  adjustedSurfacePoint = newSurfacePoint;
855  return Success;
856  }
857 
858 
868  if (type != Fixed && type != Free && type != Constrained) {
869  QString msg = "Invalid Point Enumeration, [" + QString(type) + "], for "
870  "Control Point [" + GetId() + "]";
872  }
873 
874  if (editLock)
875  return PointLocked;
876  PointModified();
877  type = newType;
878  return Success;
879  }
880 
881 
890  RadiusSource::Source source) {
891  if (editLock)
892  return PointLocked;
893  PointModified();
894  aprioriRadiusSource = source;
895  return Success;
896  }
897 
898 
908  QString sourceFile) {
909  if (editLock)
910  return PointLocked;
911  PointModified();
912  aprioriRadiusSourceFile = sourceFile;
913  return Success;
914  }
915 
916 
931  SurfacePoint aprioriSP) {
932  if (parentNetwork) {
933  std::vector<Distance> targetRadii = parentNetwork->GetTargetRadii();
934  aprioriSurfacePoint.SetRadii(targetRadii[0], targetRadii[1], targetRadii[2]);
935  }
936  if (editLock)
937  return PointLocked;
938  if (aprioriSP.GetLatSigma().isValid())
940  if (aprioriSP.GetLonSigma().isValid())
941  constraintStatus.set(LongitudeConstrained);
942  if (aprioriSP.GetLocalRadiusSigma().isValid())
943  constraintStatus.set(RadiusConstrained);
944  PointModified();
945  aprioriSurfacePoint = aprioriSP;
946  return Success;
947  }
948 
949 
958  SurfacePointSource::Source source) {
959  if (editLock)
960  return PointLocked;
961  PointModified();
962  aprioriSurfacePointSource = source;
963  return Success;
964  }
965 
966 
975  QString sourceFile) {
976  if (editLock)
977  return PointLocked;
978  PointModified();
979  aprioriSurfacePointSourceFile = sourceFile;
980  return Success;
981  }
982 
983 
1018  PointModified();
1019 
1020  // Don't goof with fixed points. The lat/lon is what it is ... if
1021  // it exists!
1022  // 2013-11-12 KLE I think this check should include points with any
1023  // number of constrained coordinates???
1024  if (GetType() == Fixed) {
1025  if (!aprioriSurfacePoint.Valid()) {
1026  QString msg = "ControlPoint [" + GetId() + "] is a fixed point ";
1027  msg += "and requires an apriori x/y/z";
1028  throw IException(IException::User, msg, _FILEINFO_);
1029  }
1030  // Don't return until after the FocalPlaneMeasures have been set
1031  // return;
1032  }
1033 
1034  double xB = 0.0;
1035  double yB = 0.0;
1036  double zB = 0.0;
1037  double r2B = 0.0;
1038  int goodMeasures = 0;
1039 
1040  // Loop for each measure and compute the sum of the lat/lon/radii
1041  for (int j = 0; j < cubeSerials->size(); j++) {
1042  ControlMeasure *m = GetMeasure(j);
1043 
1044  // The comment code was really checking for candidate measures
1045  // Commented out 2011-03-24 by DAC
1046 // if (!m->IsMeasured()) {
1047 // // TODO: How do we deal with unmeasured measures
1048 // }
1049 // else if (m->IsIgnored()) {
1050  if (m->IsIgnored()) {
1051  // TODO: How do we deal with ignored measures
1052  }
1053  else {
1054  Camera *cam = m->Camera();
1055  if (cam == NULL) {
1056  QString msg = "The Camera must be set prior to calculating apriori";
1058  }
1059  if (cam->SetImage(m->GetSample(), m->GetLine())) {
1060  goodMeasures++;
1061  double pB[3];
1062  cam->Coordinate(pB);
1063  xB += pB[0];
1064  yB += pB[1];
1065  zB += pB[2];
1066  r2B += pB[0]*pB[0] + pB[1]*pB[1] + pB[2]*pB[2];
1067 
1068  double x = cam->DistortionMap()->UndistortedFocalPlaneX();
1069  double y = cam->DistortionMap()->UndistortedFocalPlaneY();
1070  m->SetFocalPlaneMeasured(x, y);
1071  }
1072  else {
1073  // JAA: Don't stop if we know the lat/lon. The SetImage may fail
1074  // but the FocalPlane measures have been set
1075  if (GetType() == Fixed)
1076  continue;
1077 
1078  // TODO: What do we do
1079 // QString msg = "Cannot compute lat/lon/radius (x/y/z) for "
1080 // "ControlPoint [" + GetId() + "], measure [" +
1081 // m->GetCubeSerialNumber() + "]";
1082 // throw IException(IException::User, msg, _FILEINFO_);
1083 
1084  // m->SetFocalPlaneMeasured(?,?);
1085  }
1086  }
1087  }
1088 
1089  // Don't update the apriori x/y/z for fixed points TODO This needs a closer look
1090  if (GetType() == Free ) {
1091  // point can be tagged as "Free" but still have constrained coordinates
1092  // if tagged "Free" we want to compute approximate a priori coordinates
1093  }
1094  // if point is "Fixed" or otherwise constrained in one, two, or all three
1095  // coordinates, then we use the a priori surface point coordinates that
1096  // have been given via other means (e.g. through qnet or cneteditor)
1097  // 2013-11-12 KLE Is the next check better as "if Fixed or if # of
1098  // constrained coordinates > 1" ???
1099  else if (GetType() == Fixed
1100  || NumberOfConstrainedCoordinates() == 3
1101  || IsLatitudeConstrained()
1102  || IsLongitudeConstrained()
1103  || IsRadiusConstrained()) {
1104 
1105  // Initialize the adjusted x/y/z to the a priori coordinates
1107 
1108  return Success;
1109  }
1110 
1111  // Did we have any measures?
1112  if (goodMeasures == 0) {
1113  QString msg = "ControlPoint [" + GetId() + "] has no measures which "
1114  "project to lat/lon/radius (x/y/z)";
1115  throw IException(IException::User, msg, _FILEINFO_);
1116  }
1117 
1118  // Compute the averages
1119  //if (NumberOfConstrainedCoordinates() == 0) {
1120  if (GetType() == Free || NumberOfConstrainedCoordinates() == 0) {
1121  double avgX = xB / goodMeasures;
1122  double avgY = yB / goodMeasures;
1123  double avgZ = zB / goodMeasures;
1124  double avgR2 = r2B / goodMeasures;
1125  double scale = sqrt(avgR2/(avgX*avgX+avgY*avgY+avgZ*avgZ));
1126 
1128  Displacement((avgX*scale), Displacement::Kilometers),
1129  Displacement((avgY*scale), Displacement::Kilometers),
1130  Displacement((avgZ*scale), Displacement::Kilometers));
1131  }
1132  // Since we are not solving yet for x,y,and z in the bundle directly,
1133  // longitude must be constrained. This constrains x and y as well.
1134  else {
1136  aprioriSurfacePoint.GetX(),
1137  aprioriSurfacePoint.GetY(),
1138  Displacement((zB / goodMeasures), Displacement::Kilometers));
1139  }
1140 
1142  SetAprioriSurfacePointSource(SurfacePointSource::AverageOfMeasures);
1143  SetAprioriRadiusSource(RadiusSource::AverageOfMeasures);
1144 
1145  return Success;
1146  }
1147 
1148 
1172  if (IsIgnored())
1173  return Failure;
1174 
1175  PointModified();
1176 
1177  // Loop for each measure to compute the error
1178  QList<QString> keys = measures->keys();
1179 
1180  for (int j = 0; j < keys.size(); j++) {
1181  ControlMeasure *m = (*measures)[keys[j]];
1182  if (m->IsIgnored())
1183  continue;
1184  // The following lines actually check for Candidate measures
1185  // Commented out on 2011-03-24 by DAC
1186 // if (!m->IsMeasured())
1187 // continue;
1188 
1189  // TODO: Should we use crater diameter?
1190  Camera *cam = m->Camera();
1191 
1192  double cuSamp;
1193  double cuLine;
1194  CameraFocalPlaneMap *fpmap = m->Camera()->FocalPlaneMap();
1195 
1196  // Map the lat/lon/radius of the control point through the Spice of the
1197  // measurement sample/line to get the computed sample/line. This must be
1198  // done manually because the camera will compute a new time for line scanners,
1199  // instead of using the measured time.
1201 
1202  if (cam->GetCameraType() != Isis::Camera::Radar) {
1203 
1204  // Now things get tricky. We want to produce errors in pixels not mm
1205  // but some of the camera maps could fail. One that won't is the
1206  // FocalPlaneMap which takes x/y to detector s/l. We will bypass the
1207  // distortion map and have residuals in undistorted pixels.
1208  if (!fpmap->SetFocalPlane(m->GetFocalPlaneComputedX(), m->GetFocalPlaneComputedY())) {
1209  QString msg = "Sanity check #1 for ControlPoint [" + GetId() +
1210  "], ControlMeasure [" + m->GetCubeSerialNumber() + "]";
1212  // This error shouldn't happen but check anyways
1213  }
1214 
1215  cuSamp = fpmap->DetectorSample();
1216  cuLine = fpmap->DetectorLine();
1217  }
1218 
1219  else {
1220  // For radar line is calculated from time in the camera. Use the
1221  // closest line to scale the focal plane y (doppler shift) to image line
1222  // for computing the line residual. Get a local ratio
1223  // measureLine = adjacentLine
1224  // ------------ -------------- in both cases, doppler shift
1225  // dopplerMLine dopplerAdjLine is calculated using SPICE
1226  // at the time of the measurement
1227  //
1228  // 1. Get the surface point mapped to by an adjacent pixel above (if
1229  // doppler is < 0) or below (if doppler is > 0) the measured pixel
1230  // 2. Set image to the measured sample/line to load the SPICE for the
1231  // time of the measurement.
1232  // 3. Map the surface point from the adjacent pixel through the SPICE
1233  // into the image plane to get a scale for mapping from doppler
1234  // shift to line. Apply the scale to get the line residual
1235  double sample = m->GetSample();
1236  double computedY = m->GetFocalPlaneComputedY();
1237  double computedX = m->GetFocalPlaneComputedX();
1238  double adjLine;
1239 
1240  // Step 1. What happens if measured line is 1??? TODO
1241  if (computedY < 0)
1242  adjLine = m->GetLine() - 1.;
1243  else
1244  adjLine = m->GetLine() + 1.;
1245 
1246  cam->SetImage(sample, adjLine);
1247  SurfacePoint sp = cam->GetSurfacePoint();
1248 
1249  // Step 2.
1250  cam->SetImage(sample, m->GetLine());
1251  double focalplaneX;
1252  double scalingY;
1253 
1254  // Step 3.
1255  cam->GroundMap()->GetXY(sp, &focalplaneX, &scalingY);
1256  double deltaLine;
1257 
1258  if (computedY < 0)
1259  deltaLine = -computedY/scalingY;
1260  else
1261  deltaLine = computedY/scalingY;
1262 
1263  // Now map through the camera steps to take X from slant range to ground
1264  // range to pixels. Y just tracks through as 0.
1265  if (cam->DistortionMap()->SetUndistortedFocalPlane(computedX,
1266  computedY)){
1267  double focalPlaneX = cam->DistortionMap()->FocalPlaneX();
1268  double focalPlaneY = cam->DistortionMap()->FocalPlaneY();
1269  fpmap->SetFocalPlane(focalPlaneX,focalPlaneY);
1270  }
1271  cuSamp = fpmap->DetectorSample();
1272  cuLine = m->GetLine() + deltaLine;
1273  }
1274 
1275  double muSamp;
1276  double muLine;
1277 
1278  if (cam->GetCameraType() != Isis::Camera::Radar) {
1279  // Again we will bypass the distortion map and have residuals in undistorted pixels.
1280  if (!fpmap->SetFocalPlane(m->GetFocalPlaneMeasuredX(), m->GetFocalPlaneMeasuredY())) {
1281  QString msg = "Sanity check #2 for ControlPoint [" + GetId() +
1282  "], ControlMeasure [" + m->GetCubeSerialNumber() + "]";
1284  // This error shouldn't happen but check anyways
1285  }
1286  muSamp = fpmap->DetectorSample();
1287  muLine = fpmap->DetectorLine();
1288  }
1289  else {
1290  muSamp = m->GetSample();
1291  muLine = m->GetLine();
1292  }
1293 
1294  // The units are in detector sample/lines. We will apply the instrument
1295  // summing mode to get close to real pixels. Note however we are in
1296  // undistorted pixels except for radar instruments.
1297  double sampResidual = muSamp - cuSamp;
1298  double lineResidual = muLine - cuLine;
1299  m->SetResidual(sampResidual, lineResidual);
1300  }
1301 
1302  return Success;
1303  }
1304 
1324  if (IsIgnored())
1325  return Failure;
1326 
1327  PointModified();
1328 
1329  // Loop for each measure to compute the error
1330  QList<QString> keys = measures->keys();
1331 
1332  for (int j = 0; j < keys.size(); j++) {
1333  ControlMeasure *m = (*measures)[keys[j]];
1334  if (m->IsIgnored())
1335  continue;
1336  // The following lines actually check for Candidate measures
1337  // Commented out on 2011-03-24 by DAC
1338 // if (!m->IsMeasured())
1339 // continue;
1340 
1341  // TODO: Should we use crater diameter?
1342  Camera *cam = m->Camera();
1343  double cudx, cudy;
1344 
1345  // Map the lat/lon/radius of the control point through the Spice of the
1346  // measurement sample/line to get the computed undistorted focal plane
1347  // coordinates (mm if not radar). This works for radar too because in
1348  // the undistorted focal plane, y has not been set to 0 (set to 0 when
1349  // going to distorted focal plane or ground range in this case), so we
1350  // can hold the Spice to calculate residuals in undistorted focal plane
1351  // coordinates.
1352  if (cam->GetCameraType() != 0) // no need to call setimage for framing camera
1353  cam->SetImage(m->GetSample(), m->GetLine());
1354 
1355  cam->GroundMap()->GetXY(GetAdjustedSurfacePoint(), &cudx, &cudy);
1356  // double mudx = m->GetFocalPlaneMeasuredX();
1357  // double mudy = m->GetFocalPlaneMeasuredY();
1358 
1359  m->SetFocalPlaneComputed(cudx, cudy);
1360 
1361  // This is wrong. The stored residual is in pixels (sample,line), not x and y
1362  // m->SetResidual(mudx - cudx, mudy - cudy);
1363  }
1364 
1365  return Success;
1366  }
1367 
1368  QString ControlPoint::GetChooserName() const {
1369  if (chooserName != "") {
1370  return chooserName;
1371  }
1372  else {
1373  return FileName(Application::Name()).name();
1374  }
1375  }
1376 
1377 
1378  QString ControlPoint::GetDateTime() const {
1379  if (dateTime != "") {
1380  return dateTime;
1381  }
1382  else {
1383  return Application::DateTime();
1384  }
1385  }
1386 
1387 
1388  bool ControlPoint::IsEditLocked() const {
1389  return editLock;
1390  }
1391 
1392 
1393  bool ControlPoint::IsRejected() const {
1394  return jigsawRejected;
1395  }
1396 
1397 
1398  SurfacePoint ControlPoint::GetAdjustedSurfacePoint() const {
1399  return adjustedSurfacePoint;
1400  }
1401 
1402 
1408  if (adjustedSurfacePoint.Valid())
1409  return adjustedSurfacePoint;
1410  else
1411  return aprioriSurfacePoint;
1412  }
1413 
1414 
1420  QString ControlPoint::GetId() const {
1421  return id;
1422  }
1423 
1424 
1425  bool ControlPoint::IsIgnored() const {
1426  return ignore;
1427  }
1428 
1429 
1430  bool ControlPoint::IsValid() const {
1431  return !invalid;
1432  }
1433 
1434 
1435  bool ControlPoint::IsInvalid() const {
1436  return invalid;
1437  }
1438 
1439 
1448  QString str;
1449 
1450  switch (pointType) {
1451  case Fixed:
1452  str = "Fixed";
1453  break;
1454  case Constrained:
1455  str = "Constrained";
1456  break;
1457  case Free:
1458  str = "Free";
1459  break;
1460  }
1461 
1462  return str;
1463  }
1464 
1465 
1474  QString pointTypeString) {
1475 
1476  // On failure assume Free
1478 
1479  QString errMsg = "There is no PointType that has a string representation"
1480  " of \"";
1481  errMsg += pointTypeString;
1482  errMsg += "\".";
1483 
1484  if (pointTypeString == "Fixed")
1485  type = ControlPoint::Fixed;
1486  else if (pointTypeString == "Constrained")
1488  else if (pointTypeString == "Free")
1489  type = ControlPoint::Free;
1490  else
1492 
1493  return type;
1494  }
1495 
1496 
1503  return PointTypeToString(GetType());
1504  }
1505 
1506 
1512  return type;
1513  }
1514 
1515 
1523  QString ControlPoint::RadiusSourceToString(RadiusSource::Source source) {
1524  QString str;
1525 
1526  switch (source) {
1527  case RadiusSource::None:
1528  str = "None";
1529  break;
1530  case RadiusSource::User:
1531  str = "User";
1532  break;
1533  case RadiusSource::AverageOfMeasures:
1534  str = "AverageOfMeasures";
1535  break;
1536  case RadiusSource::Ellipsoid:
1537  str = "Ellipsoid";
1538  break;
1539  case RadiusSource::DEM:
1540  str = "DEM";
1541  break;
1542  case RadiusSource::BundleSolution:
1543  str = "BundleSolution";
1544  break;
1545  }
1546 
1547  return str;
1548  }
1549 
1550 
1558  ControlPoint::RadiusSource::Source ControlPoint::StringToRadiusSource(
1559  QString str) {
1560 
1561  str = str.toLower();
1562  RadiusSource::Source source = RadiusSource::None;
1563 
1564  if (str == "user")
1565  source = RadiusSource::User;
1566  else if (str == "averageofmeasures")
1567  source = RadiusSource::AverageOfMeasures;
1568  else if (str == "ellipsoid")
1569  source = RadiusSource::Ellipsoid;
1570  else if (str == "dem")
1571  source = RadiusSource::DEM;
1572  else if (str == "bundlesolution")
1573  source = RadiusSource::BundleSolution;
1574 
1575  return source;
1576  }
1577 
1578 
1579 
1587  }
1588 
1589 
1598  SurfacePointSource::Source source) {
1599 
1600  QString str;
1601 
1602  switch (source) {
1603  case SurfacePointSource::None:
1604  str = "None";
1605  break;
1606  case SurfacePointSource::User:
1607  str = "User";
1608  break;
1609  case SurfacePointSource::AverageOfMeasures:
1610  str = "AverageOfMeasures";
1611  break;
1612  case SurfacePointSource::Reference:
1613  str = "Reference";
1614  break;
1615  case SurfacePointSource::Basemap:
1616  str = "Basemap";
1617  break;
1618  case SurfacePointSource::BundleSolution:
1619  str = "BundleSolution";
1620  break;
1621  }
1622 
1623  return str;
1624  }
1625 
1626 
1634  ControlPoint::SurfacePointSource::Source
1636  QString str) {
1637 
1638  str = str.toLower();
1639  SurfacePointSource::Source source = SurfacePointSource::None;
1640 
1641  if (str == "user")
1642  source = SurfacePointSource::User;
1643  else if (str == "averageofmeasures")
1644  source = SurfacePointSource::AverageOfMeasures;
1645  else if (str == "reference")
1646  source = SurfacePointSource::Reference;
1647  else if (str == "basemap")
1648  source = SurfacePointSource::Basemap;
1649  else if (str == "bundlesolution")
1650  source = SurfacePointSource::BundleSolution;
1651 
1652  return source;
1653  }
1654 
1655 
1663  }
1664 
1665 
1666  bool ControlPoint::IsFixed() const {
1667  return (type == Fixed);
1668  }
1669 
1670 
1671  SurfacePoint ControlPoint::GetAprioriSurfacePoint() const {
1672  return aprioriSurfacePoint;
1673  }
1674 
1675 
1676  ControlPoint::RadiusSource::Source ControlPoint::GetAprioriRadiusSource()
1677  const {
1678  return aprioriRadiusSource;
1679  }
1680 
1681  bool ControlPoint::HasAprioriCoordinates() {
1682  if (aprioriSurfacePoint.GetX().isValid() &&
1683  aprioriSurfacePoint.GetY().isValid() &&
1684  aprioriSurfacePoint.GetZ().isValid())
1685  return true;
1686 
1687  return false;
1688  }
1689 
1690  bool ControlPoint::IsConstrained() {
1691  return constraintStatus.any();
1692  }
1693 
1694  bool ControlPoint::IsLatitudeConstrained() {
1696  }
1697 
1698  bool ControlPoint::IsLongitudeConstrained() {
1699  return constraintStatus[LongitudeConstrained];
1700  }
1701 
1702  bool ControlPoint::IsRadiusConstrained() {
1703  return constraintStatus[RadiusConstrained];
1704  }
1705 
1706  int ControlPoint::NumberOfConstrainedCoordinates() {
1707  return constraintStatus.count();
1708  }
1709 
1710  QString ControlPoint::GetAprioriRadiusSourceFile() const {
1711  return aprioriRadiusSourceFile;
1712  }
1713 
1714  ControlPoint::SurfacePointSource::Source
1715  ControlPoint::GetAprioriSurfacePointSource() const {
1717  }
1718 
1719 
1720  QString ControlPoint::GetAprioriSurfacePointSourceFile() const {
1722  }
1723 
1724 
1725  int ControlPoint::GetNumMeasures() const {
1726  return measures->size();
1727  }
1728 
1729 
1735  int size = 0;
1736  QList<QString> keys = measures->keys();
1737  for (int cm = 0; cm < keys.size(); cm++) {
1738  if (!(*measures)[keys[cm]]->IsIgnored())
1739  size++;
1740  }
1741  return size;
1742  }
1743 
1744 
1751  int size = 0;
1752  QList<QString> keys = measures->keys();
1753  for (int cm = 0; cm < keys.size(); cm++) {
1754  if ((*measures)[keys[cm]]->IsEditLocked())
1755  size++;
1756  }
1757  return size;
1758  }
1759 
1760 
1767  bool ControlPoint::HasSerialNumber(QString serialNumber) const {
1768  return cubeSerials->contains(serialNumber);
1769  }
1770 
1771 
1777  return referenceExplicitlySet;
1778  }
1779 
1780 
1785  if (referenceMeasure == NULL) {
1786  QString msg = "There is no reference measure set in the ControlPoint [" +
1787  GetId() + "]";
1789  }
1790 
1791  return referenceMeasure->GetCubeSerialNumber();
1792  }
1793 
1794 
1803  int ControlPoint::IndexOf(ControlMeasure *cm, bool throws) const {
1804  ASSERT(cm);
1805  return IndexOf(cm->GetCubeSerialNumber(), throws);
1806  }
1807 
1808 
1817  int ControlPoint::IndexOf(QString sn, bool throws) const {
1818  int index = cubeSerials->indexOf(sn);
1819 
1820  if (throws && index == -1) {
1821  QString msg = "ControlMeasure [" + sn + "] does not exist in point [" +
1822  id + "]";
1824  }
1825 
1826  return index;
1827  }
1828 
1829 
1839  if (!referenceMeasure) {
1840  QString msg = "There is no reference measure for point [" + id + "]."
1841  " This also means of course that the point is empty!";
1843  }
1844 
1845  int index = cubeSerials->indexOf(referenceMeasure->GetCubeSerialNumber());
1846  ASSERT(index != -1)
1847 
1848  return index;
1849  }
1850 
1851 
1864  double(ControlMeasure::*statFunc)() const) const {
1865  Statistics stats;
1866  foreach(ControlMeasure * cm, *measures) {
1867  if (!cm->IsIgnored())
1868  stats.AddData((cm->*statFunc)());
1869  }
1870 
1871  return stats;
1872  }
1873 
1874 
1875  Statistics ControlPoint::GetStatistic(long dataType) const {
1876  Statistics stats;
1877  foreach(ControlMeasure * cm, *measures) {
1878  if (!cm->IsIgnored())
1879  stats.AddData(cm->GetLogData(dataType).GetNumericalValue());
1880  }
1881 
1882  return stats;
1883  }
1884 
1885 
1893  bool excludeIgnored) const {
1894  QList< ControlMeasure * > orderedMeasures;
1895  for (int i = 0; i < cubeSerials->size(); i++) {
1896  ControlMeasure *measure = measures->value((*cubeSerials)[i]);
1897  if (!excludeIgnored || !measure->IsIgnored())
1898  orderedMeasures.append(measures->value((*cubeSerials)[i]));
1899  }
1900  return orderedMeasures;
1901  }
1902 
1903 
1908  return *cubeSerials;
1909  }
1910 
1911 
1919  const ControlMeasure *ControlPoint::operator[](QString serialNumber) const {
1920  return GetMeasure(serialNumber);
1921  }
1922 
1923 
1931  ControlMeasure *ControlPoint::operator[](QString serialNumber) {
1932  return GetMeasure(serialNumber);
1933  }
1934 
1935 
1944  const ControlMeasure *ControlPoint::operator[](int index) const {
1945  return GetMeasure(index);
1946  }
1947 
1948 
1958  return GetMeasure(index);
1959  }
1960 
1961 
1969  bool ControlPoint::operator!=(const ControlPoint &other) const {
1970  return !(*this == other);
1971  }
1972 
1973 
1982  bool ControlPoint::operator==(const ControlPoint &other) const {
1983  return other.GetNumMeasures() == GetNumMeasures() &&
1984  other.id == id &&
1985  other.type == type &&
1986  other.chooserName == chooserName &&
1987  other.editLock == editLock &&
1988  other.ignore == ignore &&
1995  other.invalid == invalid &&
1996  other.measures == measures &&
1997  other.dateTime == dateTime &&
1998  other.jigsawRejected == jigsawRejected &&
2002  other.cubeSerials == cubeSerials &&
2003  other.referenceMeasure == referenceMeasure;
2004  }
2005 
2006 
2024 
2025  if (this != &other) {
2026  editLock = false;
2027  for (int i = cubeSerials->size() - 1; i >= 0; i--) {
2028  (*measures)[cubeSerials->at(i)]->SetEditLock(false);
2029  Delete(cubeSerials->at(i));
2030  }
2031 
2032  //measures->clear(); = new QHash< QString, ControlMeasure * >;
2033 
2034  QHashIterator< QString, ControlMeasure * > i(*other.measures);
2035  while (i.hasNext()) {
2036  i.next();
2037  ControlMeasure *newMeasure = new ControlMeasure;
2038  *newMeasure = *i.value();
2039  AddMeasure(newMeasure);
2040  if (other.referenceMeasure == i.value())
2041  SetRefMeasure(newMeasure);
2042  }
2043 
2044  id = other.id;
2045  chooserName = other.chooserName;
2046  dateTime = other.dateTime;
2047  type = other.type;
2048  invalid = other.invalid;
2049  editLock = other.editLock;
2052  ignore = other.ignore;
2061  }
2062 
2063  return *this;
2064  }
2065 
2066 
2067  void ControlPoint::PointModified() {
2068  dateTime = "";
2069  }
2070 
2071 
2074 
2075  {
2077  }
2078 
2079 
2087  numberOfRejectedMeasures = numRejected;
2088  }
2089 
2090 
2098  return numberOfRejectedMeasures;
2099  }
2100 
2108  int nmeasures = measures->size();
2109  if( nmeasures <= 0 )
2110  return 0.0;
2111 
2112  Statistics stats;
2113 
2114  for( int i = 0; i < nmeasures; i++) {
2115  const ControlMeasure* m = GetMeasure(i);
2116  if( !m )
2117  continue;
2118 
2119  if( !m->IsIgnored() || m->IsRejected() )
2120  continue;
2121 
2122  stats.AddData(m->GetSampleResidual());
2123  }
2124 
2125  return stats.Rms();
2126  }
2127 
2128 
2136  int nmeasures = measures->size();
2137  if( nmeasures <= 0 )
2138  return 0.0;
2139 
2140  Statistics stats;
2141 
2142  for( int i = 0; i < nmeasures; i++) {
2143  const ControlMeasure* m = GetMeasure(i);
2144  if( !m )
2145  continue;
2146 
2147  if( !m->IsIgnored() || m->IsRejected() )
2148  continue;
2149 
2150  stats.AddData(m->GetLineResidual());
2151  }
2152 
2153  return stats.Rms();
2154  }
2155 
2156 
2164  int nmeasures = measures->size();
2165  if( nmeasures <= 0 )
2166  return 0.0;
2167 
2168  Statistics stats;
2169 
2170  for( int i = 0; i < nmeasures; i++) {
2171  const ControlMeasure* m = GetMeasure(i);
2172  if( !m )
2173  continue;
2174 
2175  if( m->IsIgnored() || m->IsRejected() )
2176  continue;
2177 
2178  stats.AddData(m->GetSampleResidual());
2179  stats.AddData(m->GetLineResidual());
2180  }
2181 
2182  return stats.Rms();
2183  }
2184 
2190  int nmeasures = measures->size();
2191  if( nmeasures <= 0 )
2192  return;
2193 
2194  for( int i = 0; i < nmeasures; i++) {
2195  ControlMeasure* m = GetMeasure(i);
2196  if( !m )
2197  continue;
2198 
2199  m->SetRejected(false);
2200  }
2201 
2202  SetRejected(false);
2203  }
2204 
2205 
2206  ControlPointFileEntryV0002 ControlPoint::ToFileEntry() const {
2207  ControlPointFileEntryV0002 fileEntry;
2208 
2209  fileEntry.set_id(GetId().toAscii().data());
2210  switch (GetType()) {
2211  case ControlPoint::Free:
2212  fileEntry.set_type(ControlPointFileEntryV0002::Free);
2213  break;
2215  fileEntry.set_type(ControlPointFileEntryV0002::Constrained);
2216  break;
2217  case ControlPoint::Fixed:
2218  fileEntry.set_type(ControlPointFileEntryV0002::Fixed);
2219  break;
2220  }
2221 
2222  if (!GetChooserName().isEmpty()) {
2223  fileEntry.set_choosername(GetChooserName().toAscii().data());
2224  }
2225  if (!GetDateTime().isEmpty()) {
2226  fileEntry.set_datetime(GetDateTime().toAscii().data());
2227  }
2228  if (IsEditLocked())
2229  fileEntry.set_editlock(true);
2230  if (IsIgnored())
2231  fileEntry.set_ignore(true);
2232  if (IsRejected())
2233  fileEntry.set_jigsawrejected(true);
2234 
2235  if (referenceMeasure && referenceExplicitlySet) {
2236  fileEntry.set_referenceindex(IndexOfRefMeasure());
2237  }
2238 
2239  switch (GetAprioriSurfacePointSource()) {
2240  case ControlPoint::SurfacePointSource::None:
2241  break;
2242  case ControlPoint::SurfacePointSource::User:
2243  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_User);
2244  break;
2245  case ControlPoint::SurfacePointSource::AverageOfMeasures:
2246  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures);
2247  break;
2248  case ControlPoint::SurfacePointSource::Reference:
2249  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_Reference);
2250  break;
2251  case ControlPoint::SurfacePointSource::Basemap:
2252  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_Basemap);
2253  break;
2254  case ControlPoint::SurfacePointSource::BundleSolution:
2255  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_BundleSolution);
2256  break;
2257  default:
2258  break;
2259  }
2260  if (!GetAprioriSurfacePointSourceFile().isEmpty()) {
2261  fileEntry.set_apriorisurfpointsourcefile(GetAprioriSurfacePointSourceFile().toAscii().data());
2262  }
2263 
2264  switch (GetAprioriRadiusSource()) {
2265  case ControlPoint::RadiusSource::None:
2266  break;
2267  case ControlPoint::RadiusSource::User:
2268  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_User);
2269  break;
2270  case ControlPoint::RadiusSource::AverageOfMeasures:
2271  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures);
2272  break;
2273  case ControlPoint::RadiusSource::Ellipsoid:
2274  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_Ellipsoid);
2275  break;
2276  case ControlPoint::RadiusSource::DEM:
2277  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_DEM);
2278  break;
2279  case ControlPoint::RadiusSource::BundleSolution:
2280  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_BundleSolution);
2281  break;
2282  default:
2283  break;
2284  }
2285 
2286  if (!GetAprioriRadiusSourceFile().isEmpty()) {
2287  fileEntry.set_aprioriradiussourcefile(GetAprioriRadiusSourceFile().toAscii().data());
2288  }
2289 
2290  if (GetAprioriSurfacePoint().Valid()) {
2291  SurfacePoint apriori = GetAprioriSurfacePoint();
2292  fileEntry.set_apriorix(apriori.GetX().meters());
2293  fileEntry.set_aprioriy(apriori.GetY().meters());
2294  fileEntry.set_aprioriz(apriori.GetZ().meters());
2295 
2296  symmetric_matrix< double, upper > covar = apriori.GetRectangularMatrix();
2297  if (covar(0, 0) != 0. || covar(0, 1) != 0. ||
2298  covar(0, 2) != 0. || covar(1, 1) != 0. ||
2299  covar(1, 2) != 0. || covar(2, 2) != 0.) {
2300  fileEntry.add_aprioricovar(covar(0, 0));
2301  fileEntry.add_aprioricovar(covar(0, 1));
2302  fileEntry.add_aprioricovar(covar(0, 2));
2303  fileEntry.add_aprioricovar(covar(1, 1));
2304  fileEntry.add_aprioricovar(covar(1, 2));
2305  fileEntry.add_aprioricovar(covar(2, 2));
2306  }
2308 // if (!IsLatitudeConstrained())
2309  fileEntry.set_latitudeconstrained(true);
2310  if (constraintStatus.test(LongitudeConstrained))
2311 // if (!IsLongitudeConstrained())
2312  fileEntry.set_longitudeconstrained(true);
2313  if (constraintStatus.test(RadiusConstrained))
2314 // if (!IsRadiusConstrained())
2315  fileEntry.set_radiusconstrained(true);
2316  }
2317 
2318 
2319  if (GetAdjustedSurfacePoint().Valid()) {
2320  SurfacePoint adjusted = GetAdjustedSurfacePoint();
2321  fileEntry.set_adjustedx(adjusted.GetX().meters());
2322  fileEntry.set_adjustedy(adjusted.GetY().meters());
2323  fileEntry.set_adjustedz(adjusted.GetZ().meters());
2324 
2325  symmetric_matrix< double, upper > covar = adjusted.GetRectangularMatrix();
2326  if (covar(0, 0) != 0. || covar(0, 1) != 0. ||
2327  covar(0, 2) != 0. || covar(1, 1) != 0. ||
2328  covar(1, 2) != 0. || covar(2, 2) != 0.) {
2329  fileEntry.add_adjustedcovar(covar(0, 0));
2330  fileEntry.add_adjustedcovar(covar(0, 1));
2331  fileEntry.add_adjustedcovar(covar(0, 2));
2332  fileEntry.add_adjustedcovar(covar(1, 1));
2333  fileEntry.add_adjustedcovar(covar(1, 2));
2334  fileEntry.add_adjustedcovar(covar(2, 2));
2335  }
2336  }
2337 
2338  // Process all measures in the point
2339  for (int i = 0; i < cubeSerials->size(); i++) {
2340  *fileEntry.add_measures() =
2341  (*measures)[cubeSerials->at(i)]->ToProtocolBuffer();
2342  }
2343 
2344  return fileEntry;
2345  }
2346 }