Isis 3.0 Programmer Reference
Back | 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 
123  const Distance &majorRad, const Distance &minorRad,
124  const Distance &polarRad) : invalid(false) {
125  measures = NULL;
126  cubeSerials = NULL;
127  referenceMeasure = NULL;
129  measures = new QHash< QString, ControlMeasure * >;
130  cubeSerials = new QStringList;
131 
132  id = fileEntry.id().c_str();
133  dateTime = "";
134  aprioriSurfacePointSource = SurfacePointSource::None;
135  aprioriRadiusSource = RadiusSource::None;
136 
137  chooserName = fileEntry.choosername().c_str();
138  dateTime = fileEntry.datetime().c_str();
139  editLock = false;
140 
141  parentNetwork = NULL;
142 
143  switch (fileEntry.type()) {
144  case ControlPointFileEntryV0002_PointType_obsolete_Tie:
145  case ControlPointFileEntryV0002_PointType_Free:
146  type = Free;
147  break;
148  case ControlPointFileEntryV0002_PointType_Constrained:
149  type = Constrained;
150  break;
151  case ControlPointFileEntryV0002_PointType_obsolete_Ground:
152  case ControlPointFileEntryV0002_PointType_Fixed:
153  type = Fixed;
154  break;
155  default:
156  QString msg = "Point type is invalid.";
158  }
159 
160  ignore = fileEntry.ignore();
161  jigsawRejected = fileEntry.jigsawrejected();
162 
163  // Read apriori keywords
164  if (fileEntry.has_apriorisurfpointsource()) {
165  switch (fileEntry.apriorisurfpointsource()) {
166  case ControlPointFileEntryV0002_AprioriSource_None:
167  aprioriSurfacePointSource = SurfacePointSource::None;
168  break;
169 
170  case ControlPointFileEntryV0002_AprioriSource_User:
171  aprioriSurfacePointSource = SurfacePointSource::User;
172  break;
173 
174  case ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures:
175  aprioriSurfacePointSource = SurfacePointSource::AverageOfMeasures;
176  break;
177 
178  case ControlPointFileEntryV0002_AprioriSource_Reference:
179  aprioriSurfacePointSource = SurfacePointSource::Reference;
180  break;
181 
182  case ControlPointFileEntryV0002_AprioriSource_Basemap:
183  aprioriSurfacePointSource = SurfacePointSource::Basemap;
184  break;
185 
186  case ControlPointFileEntryV0002_AprioriSource_BundleSolution:
187  aprioriSurfacePointSource = SurfacePointSource::BundleSolution;
188  break;
189 
190  case ControlPointFileEntryV0002_AprioriSource_Ellipsoid:
191  case ControlPointFileEntryV0002_AprioriSource_DEM:
192  break;
193  }
194  }
195 
196  if (fileEntry.has_apriorisurfpointsourcefile()) {
197  aprioriSurfacePointSourceFile = fileEntry.apriorisurfpointsourcefile().c_str();
198  }
199 
200  if (fileEntry.has_aprioriradiussource()) {
201  switch (fileEntry.aprioriradiussource()) {
202  case ControlPointFileEntryV0002_AprioriSource_None:
203  aprioriRadiusSource = RadiusSource::None;
204  break;
205  case ControlPointFileEntryV0002_AprioriSource_User:
206  aprioriRadiusSource = RadiusSource::User;
207  break;
208  case ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures:
209  aprioriRadiusSource = RadiusSource::AverageOfMeasures;
210  break;
211  case ControlPointFileEntryV0002_AprioriSource_Ellipsoid:
212  aprioriRadiusSource = RadiusSource::Ellipsoid;
213  break;
214  case ControlPointFileEntryV0002_AprioriSource_DEM:
215  aprioriRadiusSource = RadiusSource::DEM;
216  break;
217  case ControlPointFileEntryV0002_AprioriSource_BundleSolution:
218  aprioriRadiusSource = RadiusSource::BundleSolution;
219  break;
220 
221  case ControlPointFileEntryV0002_AprioriSource_Reference:
222  case ControlPointFileEntryV0002_AprioriSource_Basemap:
223  break;
224  }
225  }
226 
227  if (fileEntry.has_aprioriradiussourcefile()) {
228  aprioriRadiusSourceFile = fileEntry.aprioriradiussourcefile().c_str();
229  }
230 
231  constraintStatus.reset();
232 
233  if (fileEntry.has_apriorix() && fileEntry.has_aprioriy() &&
234  fileEntry.has_aprioriz()) {
235  SurfacePoint apriori(
236  Displacement(fileEntry.apriorix(), Displacement::Meters),
237  Displacement(fileEntry.aprioriy(), Displacement::Meters),
238  Displacement(fileEntry.aprioriz(), Displacement::Meters));
239 
240  if (fileEntry.aprioricovar_size() > 0) {
241  symmetric_matrix<double, upper> covar;
242  covar.resize(3);
243  covar.clear();
244  covar(0, 0) = fileEntry.aprioricovar(0);
245  covar(0, 1) = fileEntry.aprioricovar(1);
246  covar(0, 2) = fileEntry.aprioricovar(2);
247  covar(1, 1) = fileEntry.aprioricovar(3);
248  covar(1, 2) = fileEntry.aprioricovar(4);
249  covar(2, 2) = fileEntry.aprioricovar(5);
250  apriori.SetRectangularMatrix(covar);
251 
252  if (Displacement(covar(0, 0), Displacement::Meters).isValid() ||
253  Displacement(covar(1, 1), Displacement::Meters).isValid()) {
254  if (fileEntry.latitudeconstrained())
256  if (fileEntry.longitudeconstrained())
257  constraintStatus.set(LongitudeConstrained);
258  if (fileEntry.radiusconstrained())
259  constraintStatus.set(RadiusConstrained);
260  }
261  else if (Displacement(covar(2, 2), Displacement::Meters).isValid()) {
262  if (fileEntry.latitudeconstrained())
264  if (fileEntry.radiusconstrained())
265  constraintStatus.set(RadiusConstrained);
266  }
267  }
268 
269  aprioriSurfacePoint = apriori;
270  }
271 
272  if (fileEntry.has_adjustedx() &&
273  fileEntry.has_adjustedy() &&
274  fileEntry.has_adjustedz()) {
275  SurfacePoint adjusted(
276  Displacement(fileEntry.adjustedx(), Displacement::Meters),
277  Displacement(fileEntry.adjustedy(), Displacement::Meters),
278  Displacement(fileEntry.adjustedz(), Displacement::Meters));
279 
280  if (fileEntry.adjustedcovar_size() > 0) {
281  symmetric_matrix<double, upper> covar;
282  covar.resize(3);
283  covar.clear();
284  covar(0, 0) = fileEntry.adjustedcovar(0);
285  covar(0, 1) = fileEntry.adjustedcovar(1);
286  covar(0, 2) = fileEntry.adjustedcovar(2);
287  covar(1, 1) = fileEntry.adjustedcovar(3);
288  covar(1, 2) = fileEntry.adjustedcovar(4);
289  covar(2, 2) = fileEntry.adjustedcovar(5);
290  adjusted.SetRectangularMatrix(covar);
291  }
292 
293  adjustedSurfacePoint = adjusted;
294  }
295 
296  if (majorRad.isValid() && minorRad.isValid() && polarRad.isValid()) {
297  aprioriSurfacePoint.SetRadii(majorRad, minorRad, polarRad);
298  adjustedSurfacePoint.SetRadii(majorRad, minorRad, polarRad);
299  }
300 
301  referenceExplicitlySet = false;
302 
303  for (int m = 0 ; m < fileEntry.measures_size() ; m++) {
304  ControlMeasure *measure = new ControlMeasure(fileEntry.measures(m));
305  AddMeasure(measure);
306  }
307 
308  if (fileEntry.has_referenceindex()) {
309  SetRefMeasure((*measures)[cubeSerials->at(fileEntry.referenceindex())]);
310  }
311 
312  // Set edit lock last
313  editLock = fileEntry.editlock();
314  }
315 
316 
322  ControlPoint::ControlPoint(const QString &newId) : invalid(false) {
323  parentNetwork = NULL;
324  measures = NULL;
325  referenceMeasure = NULL;
327  measures = new QHash< QString, ControlMeasure * >;
328  cubeSerials = new QStringList;
329 
330  id = newId;
331  type = Free;
332  editLock = false;
333  jigsawRejected = false;
334  referenceExplicitlySet = false;
335  ignore = false;
336  aprioriSurfacePointSource = SurfacePointSource::None;
337  aprioriRadiusSource = RadiusSource::None;
338  constraintStatus.reset();
339  }
340 
346  if (measures != NULL) {
347  QList< QString > keys = measures->keys();
348  for (int i = 0; i < keys.size(); i++) {
349  delete(*measures)[keys[i]];
350  (*measures)[keys[i]] = NULL;
351  }
352 
353  delete measures;
354  measures = NULL;
355  }
356 
357  if (cubeSerials) {
358  delete cubeSerials;
359  cubeSerials = NULL;
360  }
361 
362  referenceMeasure = NULL;
363  }
364 
411 
412  }
413 
414 
422  PointModified();
423  AddMeasure(measure);
424  }
425 
426 
432  // Make sure measure is unique
433  foreach(ControlMeasure * m, measures->values()) {
434  if (m->GetCubeSerialNumber() == measure->GetCubeSerialNumber()) {
435  QString msg = "The SerialNumber is not unique. A measure with "
436  "serial number [" + measure->GetCubeSerialNumber() + "] already "
437  "exists for ControlPoint [" + GetId() + "]";
439  }
440  }
441 
442  if (!measures->size()) {
443  ASSERT(referenceMeasure == NULL);
444  referenceMeasure = measure;
445  }
446  else if (referenceMeasure->IsIgnored() && !measure->IsIgnored() &&
447  !IsReferenceExplicit() && !IsEditLocked()) {
448  // The current "implicit" reference is ignored, but this new measure
449  // isn't, and the point is not edit locked, so make this measure the new
450  // reference
451  referenceMeasure = measure;
452  }
453 
454  measure->parentPoint = this;
455  QString newSerial = measure->GetCubeSerialNumber();
456  measures->insert(newSerial, measure);
457  cubeSerials->append(newSerial);
458 
459  // notify parent network if we have one
460  if (parentNetwork) {
461  parentNetwork->measureAdded(measure);
462  parentNetwork->emitNetworkStructureModified();
463  }
464  }
465 
466 
474  void ControlPoint::ValidateMeasure(QString serialNumber) const {
475  if (!measures->contains(serialNumber)) {
476  QString msg = "No measure with serial number [" + serialNumber +
477  "] is owned by this point";
479  }
480  }
481 
482 
489  int ControlPoint::Delete(QString serialNumber) {
490  ValidateMeasure(serialNumber);
491  ControlMeasure *cm = (*measures)[serialNumber];
492 
493  if (cm->IsEditLocked())
494  return ControlMeasure::MeasureLocked;
495 
496  // remove measure from the point's data structures
497  measures->remove(serialNumber);
498  cubeSerials->removeAt(cubeSerials->indexOf(serialNumber));
499 
500  // update the reference measure
501  if (cubeSerials->size()) {
502  if (referenceMeasure == cm) {
503  referenceMeasure = (*measures)[cubeSerials->at(0)];
504  referenceExplicitlySet = false;
505  }
506  }
507  else {
508  referenceMeasure = NULL;
509  }
510 
511  // notify parent network of the change
512  if (parentNetwork) {
514 
515  if (!IsIgnored() && !cm->IsIgnored())
516  parentNetwork->emitNetworkStructureModified();
517  }
518 
519  delete cm;
520  cm = NULL;
521 
522  PointModified();
523 
524  return ControlMeasure::Success;
525  }
526 
527 
535  ASSERT(measure);
536  return Delete(measure->GetCubeSerialNumber());
537  }
538 
539 
546  int ControlPoint::Delete(int index) {
547  if (index < 0 || index >= cubeSerials->size()) {
548  QString msg = "index [" + QString(index) + "] out of bounds";
550  }
551 
552  return Delete(cubeSerials->at(index));
553  }
554 
555 
562  if (IsEditLocked())
563  return PointLocked;
564 
565  aprioriSurfacePointSource = SurfacePointSource::None;
567  aprioriRadiusSource = RadiusSource::None;
569 
571  constraintStatus.reset();
572 
573  return Success;
574  }
575 
576 
583  ControlMeasure *ControlPoint::GetMeasure(QString serialNumber) {
584  ValidateMeasure(serialNumber);
585  return (*measures)[serialNumber];
586  }
587 
588 
595  const ControlMeasure *ControlPoint::GetMeasure(QString serialNumber) const {
596  ValidateMeasure(serialNumber);
597  return measures->value(serialNumber);
598  }
599 
600 
601  const ControlMeasure *ControlPoint::GetMeasure(int index) const {
602  if (index < 0 || index >= cubeSerials->size()) {
603  QString msg = "Index [" + toString(index) + "] out of range";
605  }
606 
607  return GetMeasure(cubeSerials->at(index));
608  }
609 
610 
611  ControlMeasure *ControlPoint::GetMeasure(int index) {
612  if (index < 0 || index >= cubeSerials->size()) {
613  QString msg = "Index [" + toString(index) + "] out of range";
614  throw IException(IException::Programmer, msg, _FILEINFO_);
615  }
616 
617  return GetMeasure(cubeSerials->at(index));
618  }
619 
620 
627  if (referenceMeasure == NULL) {
628  QString msg = "Control point [" + GetId() + "] has no reference measure!";
630  }
631 
632  return referenceMeasure;
633  }
634 
635 
640  if (referenceMeasure == NULL) {
641  QString msg = "Control point [" + GetId() + "] has no reference measure!";
643  }
644 
645  return referenceMeasure;
646  }
647 
648 
657  if (editLock)
658  return PointLocked;
659  chooserName = name;
660  return Success;
661  }
662 
663 
673  if (editLock)
674  return PointLocked;
675  dateTime = newDateTime;
676  return Success;
677  }
678 
679 
690  editLock = lock;
691  return Success;
692  }
693 
694 
704  jigsawRejected = reject;
705  return Success;
706  }
707 
708 
717  if (editLock)
718  return PointLocked;
719  QString oldId = id;
720  id = newId;
721  if (parentNetwork)
722  parentNetwork->UpdatePointReference(this, oldId);
723  return Success;
724  }
725 
726 
733  if (editLock)
734  return PointLocked;
735 
736  ASSERT(cm);
738  return Success;
739  }
740 
741 
748  if (editLock)
749  return PointLocked;
750 
751  if (index < 0 || index >= cubeSerials->size()) {
752  QString msg = "Index [";
753  msg += toString(index) + "] out of range";
755  }
756 
757  SetExplicitReference((*measures)[cubeSerials->at(index)]);
758  return Success;
759  }
760 
761 
768  if (editLock)
769  return PointLocked;
770 
771  if (!cubeSerials->contains(sn)) {
772  QString msg = "Point [" + id + "] has no measure with serial number [" +
773  sn + "]";
775  }
776 
777  SetExplicitReference((*measures)[sn]);
778  return Success;
779  }
780 
781 
801  referenceExplicitlySet = true;
802  referenceMeasure = measure;
803  }
804 
805 
813  if (editLock)
814  return PointLocked;
815 
816  bool oldStatus = ignore;
817  ignore = newIgnoreStatus;
818 
819  // only update if there was a change in status
820  if (oldStatus != ignore) {
821  PointModified();
822  if (parentNetwork) {
823  foreach(ControlMeasure * cm, measures->values()) {
824  if (!cm->IsIgnored()) {
825  if (ignore)
826  parentNetwork->measureIgnored(cm);
827  else
829  }
830  }
831  parentNetwork->emitNetworkStructureModified();
832  }
833  }
834 
835  return Success;
836  }
837 
838 
853  SurfacePoint newSurfacePoint) {
854  PointModified();
855  adjustedSurfacePoint = newSurfacePoint;
856  return Success;
857  }
858 
859 
869  if (type != Fixed && type != Free && type != Constrained) {
870  QString msg = "Invalid Point Enumeration, [" + QString(type) + "], for "
871  "Control Point [" + GetId() + "]";
873  }
874 
875  if (editLock)
876  return PointLocked;
877  PointModified();
878  type = newType;
879  return Success;
880  }
881 
882 
891  RadiusSource::Source source) {
892  if (editLock)
893  return PointLocked;
894  PointModified();
895  aprioriRadiusSource = source;
896  return Success;
897  }
898 
899 
909  QString sourceFile) {
910  if (editLock)
911  return PointLocked;
912  PointModified();
913  aprioriRadiusSourceFile = sourceFile;
914  return Success;
915  }
916 
917 
932  SurfacePoint aprioriSP) {
933  if (parentNetwork) {
934  std::vector<Distance> targetRadii = parentNetwork->GetTargetRadii();
935  aprioriSurfacePoint.SetRadii(targetRadii[0], targetRadii[1], targetRadii[2]);
936  }
937  if (editLock)
938  return PointLocked;
939  if (aprioriSP.GetLatSigma().isValid())
941  if (aprioriSP.GetLonSigma().isValid())
942  constraintStatus.set(LongitudeConstrained);
943  if (aprioriSP.GetLocalRadiusSigma().isValid())
944  constraintStatus.set(RadiusConstrained);
945  PointModified();
946  aprioriSurfacePoint = aprioriSP;
947  return Success;
948  }
949 
950 
959  SurfacePointSource::Source source) {
960  if (editLock)
961  return PointLocked;
962  PointModified();
963  aprioriSurfacePointSource = source;
964  return Success;
965  }
966 
967 
976  QString sourceFile) {
977  if (editLock)
978  return PointLocked;
979  PointModified();
980  aprioriSurfacePointSourceFile = sourceFile;
981  return Success;
982  }
983 
984 
1019  PointModified();
1020 
1021  // Don't goof with fixed points. The lat/lon is what it is ... if
1022  // it exists!
1023  // 2013-11-12 KLE I think this check should include points with any
1024  // number of constrained coordinates???
1025  if (GetType() == Fixed) {
1026  if (!aprioriSurfacePoint.Valid()) {
1027  QString msg = "ControlPoint [" + GetId() + "] is a fixed point ";
1028  msg += "and requires an apriori x/y/z";
1029  throw IException(IException::User, msg, _FILEINFO_);
1030  }
1031  // Don't return until after the FocalPlaneMeasures have been set
1032  // return;
1033  }
1034 
1035  double xB = 0.0;
1036  double yB = 0.0;
1037  double zB = 0.0;
1038  double r2B = 0.0;
1039  int goodMeasures = 0;
1040 
1041  // Loop for each measure and compute the sum of the lat/lon/radii
1042  for (int j = 0; j < cubeSerials->size(); j++) {
1043  ControlMeasure *m = GetMeasure(j);
1044 
1045  // The comment code was really checking for candidate measures
1046  // Commented out 2011-03-24 by DAC
1047 // if (!m->IsMeasured()) {
1048 // // TODO: How do we deal with unmeasured measures
1049 // }
1050 // else if (m->IsIgnored()) {
1051  if (m->IsIgnored()) {
1052  // TODO: How do we deal with ignored measures
1053  }
1054  else {
1055  Camera *cam = m->Camera();
1056  if (cam == NULL) {
1057  QString msg = "The Camera must be set prior to calculating apriori";
1059  }
1060  if (cam->SetImage(m->GetSample(), m->GetLine())) {
1061  goodMeasures++;
1062  double pB[3];
1063  cam->Coordinate(pB);
1064  xB += pB[0];
1065  yB += pB[1];
1066  zB += pB[2];
1067  r2B += pB[0]*pB[0] + pB[1]*pB[1] + pB[2]*pB[2];
1068 
1069  double x = cam->DistortionMap()->UndistortedFocalPlaneX();
1070  double y = cam->DistortionMap()->UndistortedFocalPlaneY();
1071  m->SetFocalPlaneMeasured(x, y);
1072  }
1073  else {
1074  // JAA: Don't stop if we know the lat/lon. The SetImage may fail
1075  // but the FocalPlane measures have been set
1076  if (GetType() == Fixed)
1077  continue;
1078 
1079  // TODO: What do we do
1080 // QString msg = "Cannot compute lat/lon/radius (x/y/z) for "
1081 // "ControlPoint [" + GetId() + "], measure [" +
1082 // m->GetCubeSerialNumber() + "]";
1083 // throw IException(IException::User, msg, _FILEINFO_);
1084 
1085  // m->SetFocalPlaneMeasured(?,?);
1086  }
1087  }
1088  }
1089 
1090  // Don't update the apriori x/y/z for fixed points TODO This needs a closer look
1091  if (GetType() == Free ) {
1092  // point can be tagged as "Free" but still have constrained coordinates
1093  // if tagged "Free" we want to compute approximate a priori coordinates
1094  }
1095  // if point is "Fixed" or otherwise constrained in one, two, or all three
1096  // coordinates, then we use the a priori surface point coordinates that
1097  // have been given via other means (e.g. through qnet or cneteditor)
1098  // 2013-11-12 KLE Is the next check better as "if Fixed or if # of
1099  // constrained coordinates > 1" ???
1100  else if (GetType() == Fixed
1101  || NumberOfConstrainedCoordinates() == 3
1102  || IsLatitudeConstrained()
1103  || IsLongitudeConstrained()
1104  || IsRadiusConstrained()) {
1105 
1106  // Initialize the adjusted x/y/z to the a priori coordinates
1108 
1109  return Success;
1110  }
1111 
1112  // Did we have any measures?
1113  if (goodMeasures == 0) {
1114  QString msg = "ControlPoint [" + GetId() + "] has no measures which "
1115  "project to lat/lon/radius (x/y/z)";
1116  throw IException(IException::User, msg, _FILEINFO_);
1117  }
1118 
1119  // Compute the averages
1120  //if (NumberOfConstrainedCoordinates() == 0) {
1121  if (GetType() == Free || NumberOfConstrainedCoordinates() == 0) {
1122  double avgX = xB / goodMeasures;
1123  double avgY = yB / goodMeasures;
1124  double avgZ = zB / goodMeasures;
1125  double avgR2 = r2B / goodMeasures;
1126  double scale = sqrt(avgR2/(avgX*avgX+avgY*avgY+avgZ*avgZ));
1127 
1129  Displacement((avgX*scale), Displacement::Kilometers),
1130  Displacement((avgY*scale), Displacement::Kilometers),
1131  Displacement((avgZ*scale), Displacement::Kilometers));
1132  }
1133  // Since we are not solving yet for x,y,and z in the bundle directly,
1134  // longitude must be constrained. This constrains x and y as well.
1135  else {
1137  aprioriSurfacePoint.GetX(),
1138  aprioriSurfacePoint.GetY(),
1139  Displacement((zB / goodMeasures), Displacement::Kilometers));
1140  }
1141 
1143  SetAprioriSurfacePointSource(SurfacePointSource::AverageOfMeasures);
1144  SetAprioriRadiusSource(RadiusSource::AverageOfMeasures);
1145 
1146  return Success;
1147  }
1148 
1149 
1173  if (IsIgnored())
1174  return Failure;
1175 
1176  PointModified();
1177 
1178  // Loop for each measure to compute the error
1179  QList<QString> keys = measures->keys();
1180 
1181  for (int j = 0; j < keys.size(); j++) {
1182  ControlMeasure *m = (*measures)[keys[j]];
1183  if (m->IsIgnored())
1184  continue;
1185  // The following lines actually check for Candidate measures
1186  // Commented out on 2011-03-24 by DAC
1187 // if (!m->IsMeasured())
1188 // continue;
1189 
1190  // TODO: Should we use crater diameter?
1191  Camera *cam = m->Camera();
1192 
1193  double cuSamp;
1194  double cuLine;
1195  CameraFocalPlaneMap *fpmap = m->Camera()->FocalPlaneMap();
1196 
1197  // Map the lat/lon/radius of the control point through the Spice of the
1198  // measurement sample/line to get the computed sample/line. This must be
1199  // done manually because the camera will compute a new time for line scanners,
1200  // instead of using the measured time.
1202 
1203  if (cam->GetCameraType() != Isis::Camera::Radar) {
1204 
1205  // Now things get tricky. We want to produce errors in pixels not mm
1206  // but some of the camera maps could fail. One that won't is the
1207  // FocalPlaneMap which takes x/y to detector s/l. We will bypass the
1208  // distortion map and have residuals in undistorted pixels.
1209  if (!fpmap->SetFocalPlane(m->GetFocalPlaneComputedX(), m->GetFocalPlaneComputedY())) {
1210  QString msg = "Sanity check #1 for ControlPoint [" + GetId() +
1211  "], ControlMeasure [" + m->GetCubeSerialNumber() + "]";
1213  // This error shouldn't happen but check anyways
1214  }
1215 
1216  cuSamp = fpmap->DetectorSample();
1217  cuLine = fpmap->DetectorLine();
1218  }
1219 
1220  else {
1221  // For radar line is calculated from time in the camera. Use the
1222  // closest line to scale the focal plane y (doppler shift) to image line
1223  // for computing the line residual. Get a local ratio
1224  // measureLine = adjacentLine
1225  // ------------ -------------- in both cases, doppler shift
1226  // dopplerMLine dopplerAdjLine is calculated using SPICE
1227  // at the time of the measurement
1228  //
1229  // 1. Get the surface point mapped to by an adjacent pixel above (if
1230  // doppler is < 0) or below (if doppler is > 0) the measured pixel
1231  // 2. Set image to the measured sample/line to load the SPICE for the
1232  // time of the measurement.
1233  // 3. Map the surface point from the adjacent pixel through the SPICE
1234  // into the image plane to get a scale for mapping from doppler
1235  // shift to line. Apply the scale to get the line residual
1236  double sample = m->GetSample();
1237  double computedY = m->GetFocalPlaneComputedY();
1238  double computedX = m->GetFocalPlaneComputedX();
1239  double adjLine;
1240 
1241  // Step 1. What happens if measured line is 1??? TODO
1242  if (computedY < 0)
1243  adjLine = m->GetLine() - 1.;
1244  else
1245  adjLine = m->GetLine() + 1.;
1246 
1247  cam->SetImage(sample, adjLine);
1248  SurfacePoint sp = cam->GetSurfacePoint();
1249 
1250  // Step 2.
1251  cam->SetImage(sample, m->GetLine());
1252  double focalplaneX;
1253  double scalingY;
1254 
1255  // Step 3.
1256  cam->GroundMap()->GetXY(sp, &focalplaneX, &scalingY);
1257  double deltaLine;
1258 
1259  if (computedY < 0)
1260  deltaLine = -computedY/scalingY;
1261  else
1262  deltaLine = computedY/scalingY;
1263 
1264  // Now map through the camera steps to take X from slant range to ground
1265  // range to pixels. Y just tracks through as 0.
1266  if (cam->DistortionMap()->SetUndistortedFocalPlane(computedX,
1267  computedY)){
1268  double focalPlaneX = cam->DistortionMap()->FocalPlaneX();
1269  double focalPlaneY = cam->DistortionMap()->FocalPlaneY();
1270  fpmap->SetFocalPlane(focalPlaneX,focalPlaneY);
1271  }
1272  cuSamp = fpmap->DetectorSample();
1273  cuLine = m->GetLine() + deltaLine;
1274  }
1275 
1276  double muSamp;
1277  double muLine;
1278 
1279  if (cam->GetCameraType() != Isis::Camera::Radar) {
1280  // Again we will bypass the distortion map and have residuals in undistorted pixels.
1281  if (!fpmap->SetFocalPlane(m->GetFocalPlaneMeasuredX(), m->GetFocalPlaneMeasuredY())) {
1282  QString msg = "Sanity check #2 for ControlPoint [" + GetId() +
1283  "], ControlMeasure [" + m->GetCubeSerialNumber() + "]";
1285  // This error shouldn't happen but check anyways
1286  }
1287  muSamp = fpmap->DetectorSample();
1288  muLine = fpmap->DetectorLine();
1289  }
1290  else {
1291  muSamp = m->GetSample();
1292  muLine = m->GetLine();
1293  }
1294 
1295  // The units are in detector sample/lines. We will apply the instrument
1296  // summing mode to get close to real pixels. Note however we are in
1297  // undistorted pixels except for radar instruments.
1298  double sampResidual = muSamp - cuSamp;
1299  double lineResidual = muLine - cuLine;
1300  m->SetResidual(sampResidual, lineResidual);
1301  }
1302 
1303  return Success;
1304  }
1305 
1325  if (IsIgnored())
1326  return Failure;
1327 
1328  PointModified();
1329 
1330  // Loop for each measure to compute the error
1331  QList<QString> keys = measures->keys();
1332 
1333  for (int j = 0; j < keys.size(); j++) {
1334  ControlMeasure *m = (*measures)[keys[j]];
1335  if (m->IsIgnored())
1336  continue;
1337  // The following lines actually check for Candidate measures
1338  // Commented out on 2011-03-24 by DAC
1339 // if (!m->IsMeasured())
1340 // continue;
1341 
1342  // TODO: Should we use crater diameter?
1343  Camera *cam = m->Camera();
1344  double cudx, cudy;
1345 
1346  // Map the lat/lon/radius of the control point through the Spice of the
1347  // measurement sample/line to get the computed undistorted focal plane
1348  // coordinates (mm if not radar). This works for radar too because in
1349  // the undistorted focal plane, y has not been set to 0 (set to 0 when
1350  // going to distorted focal plane or ground range in this case), so we
1351  // can hold the Spice to calculate residuals in undistorted focal plane
1352  // coordinates.
1353  if (cam->GetCameraType() != 0) // no need to call setimage for framing camera
1354  cam->SetImage(m->GetSample(), m->GetLine());
1355 
1356  cam->GroundMap()->GetXY(GetAdjustedSurfacePoint(), &cudx, &cudy);
1357  // double mudx = m->GetFocalPlaneMeasuredX();
1358  // double mudy = m->GetFocalPlaneMeasuredY();
1359 
1360  m->SetFocalPlaneComputed(cudx, cudy);
1361 
1362  // This is wrong. The stored residual is in pixels (sample,line), not x and y
1363  // m->SetResidual(mudx - cudx, mudy - cudy);
1364  }
1365 
1366  return Success;
1367  }
1368 
1369  QString ControlPoint::GetChooserName() const {
1370  if (chooserName != "") {
1371  return chooserName;
1372  }
1373  else {
1374  return FileName(Application::Name()).name();
1375  }
1376  }
1377 
1378 
1379  QString ControlPoint::GetDateTime() const {
1380  if (dateTime != "") {
1381  return dateTime;
1382  }
1383  else {
1384  return Application::DateTime();
1385  }
1386  }
1387 
1388 
1389  bool ControlPoint::IsEditLocked() const {
1390  return editLock;
1391  }
1392 
1393 
1394  bool ControlPoint::IsRejected() const {
1395  return jigsawRejected;
1396  }
1397 
1398 
1399  SurfacePoint ControlPoint::GetAdjustedSurfacePoint() const {
1400  return adjustedSurfacePoint;
1401  }
1402 
1403 
1409  if (adjustedSurfacePoint.Valid())
1410  return adjustedSurfacePoint;
1411  else
1412  return aprioriSurfacePoint;
1413  }
1414 
1415 
1421  QString ControlPoint::GetId() const {
1422  return id;
1423  }
1424 
1425 
1426  bool ControlPoint::IsIgnored() const {
1427  return ignore;
1428  }
1429 
1430 
1431  bool ControlPoint::IsValid() const {
1432  return !invalid;
1433  }
1434 
1435 
1436  bool ControlPoint::IsInvalid() const {
1437  return invalid;
1438  }
1439 
1440 
1449  QString str;
1450 
1451  switch (pointType) {
1452  case Fixed:
1453  str = "Fixed";
1454  break;
1455  case Constrained:
1456  str = "Constrained";
1457  break;
1458  case Free:
1459  str = "Free";
1460  break;
1461  }
1462 
1463  return str;
1464  }
1465 
1466 
1475  QString pointTypeString) {
1476 
1477  // On failure assume Free
1479 
1480  QString errMsg = "There is no PointType that has a string representation"
1481  " of \"";
1482  errMsg += pointTypeString;
1483  errMsg += "\".";
1484 
1485  if (pointTypeString == "Fixed")
1486  type = ControlPoint::Fixed;
1487  else if (pointTypeString == "Constrained")
1489  else if (pointTypeString == "Free")
1490  type = ControlPoint::Free;
1491  else
1493 
1494  return type;
1495  }
1496 
1497 
1504  return PointTypeToString(GetType());
1505  }
1506 
1507 
1513  return type;
1514  }
1515 
1516 
1524  QString ControlPoint::RadiusSourceToString(RadiusSource::Source source) {
1525  QString str;
1526 
1527  switch (source) {
1528  case RadiusSource::None:
1529  str = "None";
1530  break;
1531  case RadiusSource::User:
1532  str = "User";
1533  break;
1534  case RadiusSource::AverageOfMeasures:
1535  str = "AverageOfMeasures";
1536  break;
1537  case RadiusSource::Ellipsoid:
1538  str = "Ellipsoid";
1539  break;
1540  case RadiusSource::DEM:
1541  str = "DEM";
1542  break;
1543  case RadiusSource::BundleSolution:
1544  str = "BundleSolution";
1545  break;
1546  }
1547 
1548  return str;
1549  }
1550 
1551 
1559  ControlPoint::RadiusSource::Source ControlPoint::StringToRadiusSource(
1560  QString str) {
1561 
1562  str = str.toLower();
1563  RadiusSource::Source source = RadiusSource::None;
1564 
1565  if (str == "user")
1566  source = RadiusSource::User;
1567  else if (str == "averageofmeasures")
1568  source = RadiusSource::AverageOfMeasures;
1569  else if (str == "ellipsoid")
1570  source = RadiusSource::Ellipsoid;
1571  else if (str == "dem")
1572  source = RadiusSource::DEM;
1573  else if (str == "bundlesolution")
1574  source = RadiusSource::BundleSolution;
1575 
1576  return source;
1577  }
1578 
1579 
1580 
1588  }
1589 
1590 
1599  SurfacePointSource::Source source) {
1600 
1601  QString str;
1602 
1603  switch (source) {
1604  case SurfacePointSource::None:
1605  str = "None";
1606  break;
1607  case SurfacePointSource::User:
1608  str = "User";
1609  break;
1610  case SurfacePointSource::AverageOfMeasures:
1611  str = "AverageOfMeasures";
1612  break;
1613  case SurfacePointSource::Reference:
1614  str = "Reference";
1615  break;
1616  case SurfacePointSource::Basemap:
1617  str = "Basemap";
1618  break;
1619  case SurfacePointSource::BundleSolution:
1620  str = "BundleSolution";
1621  break;
1622  }
1623 
1624  return str;
1625  }
1626 
1627 
1635  ControlPoint::SurfacePointSource::Source
1637  QString str) {
1638 
1639  str = str.toLower();
1640  SurfacePointSource::Source source = SurfacePointSource::None;
1641 
1642  if (str == "user")
1643  source = SurfacePointSource::User;
1644  else if (str == "averageofmeasures")
1645  source = SurfacePointSource::AverageOfMeasures;
1646  else if (str == "reference")
1647  source = SurfacePointSource::Reference;
1648  else if (str == "basemap")
1649  source = SurfacePointSource::Basemap;
1650  else if (str == "bundlesolution")
1651  source = SurfacePointSource::BundleSolution;
1652 
1653  return source;
1654  }
1655 
1656 
1664  }
1665 
1666 
1667  bool ControlPoint::IsFixed() const {
1668  return (type == Fixed);
1669  }
1670 
1671 
1672  SurfacePoint ControlPoint::GetAprioriSurfacePoint() const {
1673  return aprioriSurfacePoint;
1674  }
1675 
1676 
1677  ControlPoint::RadiusSource::Source ControlPoint::GetAprioriRadiusSource()
1678  const {
1679  return aprioriRadiusSource;
1680  }
1681 
1682  bool ControlPoint::HasAprioriCoordinates() {
1683  if (aprioriSurfacePoint.GetX().isValid() &&
1684  aprioriSurfacePoint.GetY().isValid() &&
1685  aprioriSurfacePoint.GetZ().isValid())
1686  return true;
1687 
1688  return false;
1689  }
1690 
1691  bool ControlPoint::IsConstrained() {
1692  return constraintStatus.any();
1693  }
1694 
1695  bool ControlPoint::IsLatitudeConstrained() {
1697  }
1698 
1699  bool ControlPoint::IsLongitudeConstrained() {
1700  return constraintStatus[LongitudeConstrained];
1701  }
1702 
1703  bool ControlPoint::IsRadiusConstrained() {
1704  return constraintStatus[RadiusConstrained];
1705  }
1706 
1707  int ControlPoint::NumberOfConstrainedCoordinates() {
1708  return constraintStatus.count();
1709  }
1710 
1711  QString ControlPoint::GetAprioriRadiusSourceFile() const {
1712  return aprioriRadiusSourceFile;
1713  }
1714 
1715  ControlPoint::SurfacePointSource::Source
1716  ControlPoint::GetAprioriSurfacePointSource() const {
1718  }
1719 
1720 
1721  QString ControlPoint::GetAprioriSurfacePointSourceFile() const {
1723  }
1724 
1725 
1726  int ControlPoint::GetNumMeasures() const {
1727  return measures->size();
1728  }
1729 
1730 
1736  int size = 0;
1737  QList<QString> keys = measures->keys();
1738  for (int cm = 0; cm < keys.size(); cm++) {
1739  if (!(*measures)[keys[cm]]->IsIgnored())
1740  size++;
1741  }
1742  return size;
1743  }
1744 
1745 
1752  int size = 0;
1753  QList<QString> keys = measures->keys();
1754  for (int cm = 0; cm < keys.size(); cm++) {
1755  if ((*measures)[keys[cm]]->IsEditLocked())
1756  size++;
1757  }
1758  return size;
1759  }
1760 
1761 
1768  bool ControlPoint::HasSerialNumber(QString serialNumber) const {
1769  return cubeSerials->contains(serialNumber);
1770  }
1771 
1772 
1778  return referenceExplicitlySet;
1779  }
1780 
1781 
1786  if (referenceMeasure == NULL) {
1787  QString msg = "There is no reference measure set in the ControlPoint [" +
1788  GetId() + "]";
1790  }
1791 
1792  return referenceMeasure->GetCubeSerialNumber();
1793  }
1794 
1795 
1804  int ControlPoint::IndexOf(ControlMeasure *cm, bool throws) const {
1805  ASSERT(cm);
1806  return IndexOf(cm->GetCubeSerialNumber(), throws);
1807  }
1808 
1809 
1818  int ControlPoint::IndexOf(QString sn, bool throws) const {
1819  int index = cubeSerials->indexOf(sn);
1820 
1821  if (throws && index == -1) {
1822  QString msg = "ControlMeasure [" + sn + "] does not exist in point [" +
1823  id + "]";
1825  }
1826 
1827  return index;
1828  }
1829 
1830 
1840  if (!referenceMeasure) {
1841  QString msg = "There is no reference measure for point [" + id + "]."
1842  " This also means of course that the point is empty!";
1844  }
1845 
1846  int index = cubeSerials->indexOf(referenceMeasure->GetCubeSerialNumber());
1847  ASSERT(index != -1)
1848 
1849  return index;
1850  }
1851 
1852 
1865  double(ControlMeasure::*statFunc)() const) const {
1866  Statistics stats;
1867  foreach(ControlMeasure * cm, *measures) {
1868  if (!cm->IsIgnored())
1869  stats.AddData((cm->*statFunc)());
1870  }
1871 
1872  return stats;
1873  }
1874 
1875 
1876  Statistics ControlPoint::GetStatistic(long dataType) const {
1877  Statistics stats;
1878  foreach(ControlMeasure * cm, *measures) {
1879  if (!cm->IsIgnored())
1880  stats.AddData(cm->GetLogData(dataType).GetNumericalValue());
1881  }
1882 
1883  return stats;
1884  }
1885 
1886 
1894  bool excludeIgnored) const {
1895  QList< ControlMeasure * > orderedMeasures;
1896  for (int i = 0; i < cubeSerials->size(); i++) {
1897  ControlMeasure *measure = measures->value((*cubeSerials)[i]);
1898  if (!excludeIgnored || !measure->IsIgnored())
1899  orderedMeasures.append(measures->value((*cubeSerials)[i]));
1900  }
1901  return orderedMeasures;
1902  }
1903 
1904 
1909  return *cubeSerials;
1910  }
1911 
1912 
1920  const ControlMeasure *ControlPoint::operator[](QString serialNumber) const {
1921  return GetMeasure(serialNumber);
1922  }
1923 
1924 
1932  ControlMeasure *ControlPoint::operator[](QString serialNumber) {
1933  return GetMeasure(serialNumber);
1934  }
1935 
1936 
1945  const ControlMeasure *ControlPoint::operator[](int index) const {
1946  return GetMeasure(index);
1947  }
1948 
1949 
1959  return GetMeasure(index);
1960  }
1961 
1962 
1970  bool ControlPoint::operator!=(const ControlPoint &other) const {
1971  return !(*this == other);
1972  }
1973 
1974 
1983  bool ControlPoint::operator==(const ControlPoint &other) const {
1984  return other.GetNumMeasures() == GetNumMeasures() &&
1985  other.id == id &&
1986  other.type == type &&
1987  other.chooserName == chooserName &&
1988  other.editLock == editLock &&
1989  other.ignore == ignore &&
1996  other.invalid == invalid &&
1997  other.measures == measures &&
1998  other.dateTime == dateTime &&
1999  other.jigsawRejected == jigsawRejected &&
2003  other.cubeSerials == cubeSerials &&
2004  other.referenceMeasure == referenceMeasure;
2005  }
2006 
2007 
2025 
2026  if (this != &other) {
2027  editLock = false;
2028  for (int i = cubeSerials->size() - 1; i >= 0; i--) {
2029  (*measures)[cubeSerials->at(i)]->SetEditLock(false);
2030  Delete(cubeSerials->at(i));
2031  }
2032 
2033  //measures->clear(); = new QHash< QString, ControlMeasure * >;
2034 
2035  QHashIterator< QString, ControlMeasure * > i(*other.measures);
2036  while (i.hasNext()) {
2037  i.next();
2038  ControlMeasure *newMeasure = new ControlMeasure;
2039  *newMeasure = *i.value();
2040  AddMeasure(newMeasure);
2041  if (other.referenceMeasure == i.value())
2042  SetRefMeasure(newMeasure);
2043  }
2044 
2045  id = other.id;
2046  chooserName = other.chooserName;
2047  dateTime = other.dateTime;
2048  type = other.type;
2049  invalid = other.invalid;
2050  editLock = other.editLock;
2053  ignore = other.ignore;
2062  }
2063 
2064  return *this;
2065  }
2066 
2067 
2068  void ControlPoint::PointModified() {
2069  dateTime = "";
2070  }
2071 
2072 
2075 
2076  {
2078  }
2079 
2080 
2088  numberOfRejectedMeasures = numRejected;
2089  }
2090 
2091 
2099  return numberOfRejectedMeasures;
2100  }
2101 
2109  int nmeasures = measures->size();
2110  if( nmeasures <= 0 )
2111  return 0.0;
2112 
2113  Statistics stats;
2114 
2115  for( int i = 0; i < nmeasures; i++) {
2116  const ControlMeasure* m = GetMeasure(i);
2117  if( !m )
2118  continue;
2119 
2120  if( !m->IsIgnored() || m->IsRejected() )
2121  continue;
2122 
2123  stats.AddData(m->GetSampleResidual());
2124  }
2125 
2126  return stats.Rms();
2127  }
2128 
2129 
2137  int nmeasures = measures->size();
2138  if( nmeasures <= 0 )
2139  return 0.0;
2140 
2141  Statistics stats;
2142 
2143  for( int i = 0; i < nmeasures; i++) {
2144  const ControlMeasure* m = GetMeasure(i);
2145  if( !m )
2146  continue;
2147 
2148  if( !m->IsIgnored() || m->IsRejected() )
2149  continue;
2150 
2151  stats.AddData(m->GetLineResidual());
2152  }
2153 
2154  return stats.Rms();
2155  }
2156 
2157 
2165  int nmeasures = measures->size();
2166  if( nmeasures <= 0 )
2167  return 0.0;
2168 
2169  Statistics stats;
2170 
2171  for( int i = 0; i < nmeasures; i++) {
2172  const ControlMeasure* m = GetMeasure(i);
2173  if( !m )
2174  continue;
2175 
2176  if( m->IsIgnored() || m->IsRejected() )
2177  continue;
2178 
2179  stats.AddData(m->GetSampleResidual());
2180  stats.AddData(m->GetLineResidual());
2181  }
2182 
2183  return stats.Rms();
2184  }
2185 
2191  int nmeasures = measures->size();
2192  if( nmeasures <= 0 )
2193  return;
2194 
2195  for( int i = 0; i < nmeasures; i++) {
2196  ControlMeasure* m = GetMeasure(i);
2197  if( !m )
2198  continue;
2199 
2200  m->SetRejected(false);
2201  }
2202 
2203  SetRejected(false);
2204  }
2205 
2206 
2207  ControlPointFileEntryV0002 ControlPoint::ToFileEntry() const {
2208  ControlPointFileEntryV0002 fileEntry;
2209 
2210  fileEntry.set_id(GetId().toLatin1().data());
2211  switch (GetType()) {
2212  case ControlPoint::Free:
2213  fileEntry.set_type(ControlPointFileEntryV0002::Free);
2214  break;
2216  fileEntry.set_type(ControlPointFileEntryV0002::Constrained);
2217  break;
2218  case ControlPoint::Fixed:
2219  fileEntry.set_type(ControlPointFileEntryV0002::Fixed);
2220  break;
2221  }
2222 
2223  if (!GetChooserName().isEmpty()) {
2224  fileEntry.set_choosername(GetChooserName().toLatin1().data());
2225  }
2226  if (!GetDateTime().isEmpty()) {
2227  fileEntry.set_datetime(GetDateTime().toLatin1().data());
2228  }
2229  if (IsEditLocked())
2230  fileEntry.set_editlock(true);
2231  if (IsIgnored())
2232  fileEntry.set_ignore(true);
2233  if (IsRejected())
2234  fileEntry.set_jigsawrejected(true);
2235 
2236  if (referenceMeasure && referenceExplicitlySet) {
2237  fileEntry.set_referenceindex(IndexOfRefMeasure());
2238  }
2239 
2240  switch (GetAprioriSurfacePointSource()) {
2241  case ControlPoint::SurfacePointSource::None:
2242  break;
2243  case ControlPoint::SurfacePointSource::User:
2244  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_User);
2245  break;
2246  case ControlPoint::SurfacePointSource::AverageOfMeasures:
2247  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures);
2248  break;
2249  case ControlPoint::SurfacePointSource::Reference:
2250  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_Reference);
2251  break;
2252  case ControlPoint::SurfacePointSource::Basemap:
2253  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_Basemap);
2254  break;
2255  case ControlPoint::SurfacePointSource::BundleSolution:
2256  fileEntry.set_apriorisurfpointsource(ControlPointFileEntryV0002_AprioriSource_BundleSolution);
2257  break;
2258  default:
2259  break;
2260  }
2261  if (!GetAprioriSurfacePointSourceFile().isEmpty()) {
2262  fileEntry.set_apriorisurfpointsourcefile(GetAprioriSurfacePointSourceFile().toLatin1().data());
2263  }
2264 
2265  switch (GetAprioriRadiusSource()) {
2266  case ControlPoint::RadiusSource::None:
2267  break;
2268  case ControlPoint::RadiusSource::User:
2269  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_User);
2270  break;
2271  case ControlPoint::RadiusSource::AverageOfMeasures:
2272  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_AverageOfMeasures);
2273  break;
2274  case ControlPoint::RadiusSource::Ellipsoid:
2275  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_Ellipsoid);
2276  break;
2277  case ControlPoint::RadiusSource::DEM:
2278  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_DEM);
2279  break;
2280  case ControlPoint::RadiusSource::BundleSolution:
2281  fileEntry.set_aprioriradiussource(ControlPointFileEntryV0002_AprioriSource_BundleSolution);
2282  break;
2283  default:
2284  break;
2285  }
2286 
2287  if (!GetAprioriRadiusSourceFile().isEmpty()) {
2288  fileEntry.set_aprioriradiussourcefile(GetAprioriRadiusSourceFile().toLatin1().data());
2289  }
2290 
2291  if (GetAprioriSurfacePoint().Valid()) {
2292  SurfacePoint apriori = GetAprioriSurfacePoint();
2293  fileEntry.set_apriorix(apriori.GetX().meters());
2294  fileEntry.set_aprioriy(apriori.GetY().meters());
2295  fileEntry.set_aprioriz(apriori.GetZ().meters());
2296 
2297  symmetric_matrix< double, upper > covar = apriori.GetRectangularMatrix();
2298  if (covar(0, 0) != 0. || covar(0, 1) != 0. ||
2299  covar(0, 2) != 0. || covar(1, 1) != 0. ||
2300  covar(1, 2) != 0. || covar(2, 2) != 0.) {
2301  fileEntry.add_aprioricovar(covar(0, 0));
2302  fileEntry.add_aprioricovar(covar(0, 1));
2303  fileEntry.add_aprioricovar(covar(0, 2));
2304  fileEntry.add_aprioricovar(covar(1, 1));
2305  fileEntry.add_aprioricovar(covar(1, 2));
2306  fileEntry.add_aprioricovar(covar(2, 2));
2307  }
2309 // if (!IsLatitudeConstrained())
2310  fileEntry.set_latitudeconstrained(true);
2311  if (constraintStatus.test(LongitudeConstrained))
2312 // if (!IsLongitudeConstrained())
2313  fileEntry.set_longitudeconstrained(true);
2314  if (constraintStatus.test(RadiusConstrained))
2315 // if (!IsRadiusConstrained())
2316  fileEntry.set_radiusconstrained(true);
2317  }
2318 
2319 
2320  if (GetAdjustedSurfacePoint().Valid()) {
2321  SurfacePoint adjusted = GetAdjustedSurfacePoint();
2322  fileEntry.set_adjustedx(adjusted.GetX().meters());
2323  fileEntry.set_adjustedy(adjusted.GetY().meters());
2324  fileEntry.set_adjustedz(adjusted.GetZ().meters());
2325 
2326  symmetric_matrix< double, upper > covar = adjusted.GetRectangularMatrix();
2327  if (covar(0, 0) != 0. || covar(0, 1) != 0. ||
2328  covar(0, 2) != 0. || covar(1, 1) != 0. ||
2329  covar(1, 2) != 0. || covar(2, 2) != 0.) {
2330  fileEntry.add_adjustedcovar(covar(0, 0));
2331  fileEntry.add_adjustedcovar(covar(0, 1));
2332  fileEntry.add_adjustedcovar(covar(0, 2));
2333  fileEntry.add_adjustedcovar(covar(1, 1));
2334  fileEntry.add_adjustedcovar(covar(1, 2));
2335  fileEntry.add_adjustedcovar(covar(2, 2));
2336  }
2337  }
2338 
2339  // Process all measures in the point
2340  for (int i = 0; i < cubeSerials->size(); i++) {
2341  *fileEntry.add_measures() =
2342  (*measures)[cubeSerials->at(i)]->ToProtocolBuffer();
2343  }
2344 
2345  return fileEntry;
2346  }
2347 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:86
double GetSampleResidualRms() const
Get rms of sample residuals.
bool isValid() const
Test if this displacement has been initialized or not.
Status SetAprioriSurfacePointSource(SurfacePointSource::Source source)
This updates the source of the surface point.
PointType GetType() const
virtual CameraType GetCameraType() const =0
Returns the type of camera that was created.
void UpdatePointReference(ControlPoint *point, QString oldId)
Updates the key reference (poind Id) from the old one to what the point id was changet to...
Definition: ControlNet.cpp:500
void ZeroNumberOfRejectedMeasures()
Initialize the number of rejected measures to 0.
The distance is being specified in kilometers.
Definition: Displacement.h:54
bool editLock
This stores the edit lock state.
Definition: ControlPoint.h:623
void SetNumberOfRejectedMeasures(int numRejected)
Set (update) the number of rejected measures for the control point.
std::vector< Distance > GetTargetRadii()
Get the target radii.
void Add(ControlMeasure *measure)
Add a measurement to the control point, taking ownership of the measure in the process.
SurfacePoint aprioriSurfacePoint
The apriori surface point.
Definition: ControlPoint.h:676
A Constrained point is a Control Point whose lat/lon/radius is somewhat established and should not be...
Definition: ControlPoint.h:361
A Fixed point is a Control Point whose lat/lon is well established and should not be changed...
Definition: ControlPoint.h:356
Status ComputeApriori()
This method computes the apriori lat/lon for a point.
QString id
This is the control point ID.
Definition: ControlPoint.h:588
CameraDistortionMap * DistortionMap()
Returns a pointer to the CameraDistortionMap object.
Definition: Camera.cpp:2886
Statistics GetStatistic(double(ControlMeasure::*statFunc)() const) const
This function will call a given method on every control measure that this point has.
Status SetAprioriRadiusSourceFile(QString sourceFile)
This updates the filename of the DEM that the apriori radius came from.
virtual bool SetFocalPlane(const double dx, const double dy)
Compute detector position (sample,line) from focal plane coordinates.
Status SetIgnored(bool newIgnoreStatus)
Set whether to ignore or use control point.
virtual bool GetXY(const SurfacePoint &spoint, double *cudx, double *cudy)
Compute undistorted focal plane coordinate from ground position using current Spice from SetImage cal...
void ClearJigsawRejected()
Set jigsaw rejected flag for all measures to false and set the jigsaw rejected flag for the point its...
ControlPoint * parentPoint
Pointer to parent ControlPoint, may be null.
bool jigsawRejected
This stores the jigsaw rejected state.
Definition: ControlPoint.h:629
double Rms() const
Computes and returns the rms.
Definition: Statistics.cpp:382
QString GetPointTypeString() const
Obtain a string representation of the PointType.
PointType
These are the valid &#39;types&#39; of point.
Definition: ControlPoint.h:349
Status ComputeResiduals_Millimeters()
This method computes the residuals for a point.
int GetNumValidMeasures() const
const ControlMeasure * operator[](QString serialNumber) const
Same as GetMeasure (provided for convenience)
ControlNet * parentNetwork
List of Control Measures.
Definition: ControlPoint.h:574
double UndistortedFocalPlaneY() const
Return undistorted focal plane y.
QString dateTime
This is the last modified date and time.
Definition: ControlPoint.h:604
double GetNumericalValue() const
Get the value associated with this log data.
Status SetChooserName(QString name)
Set the point&#39;s chooser name.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:154
static QString Name()
Returns the name of the application.
Status SetEditLock(bool editLock)
Set the EditLock state.
ControlPoint()
Construct a control point.
The distance is being specified in meters.
Definition: Displacement.h:52
void SetRectangularMatrix(const boost::numeric::ublas::symmetric_matrix< double, boost::numeric::ublas::upper > &covar)
Set rectangular covariance matrix.
const ControlMeasure * GetRefMeasure() const
Get the reference control measure.
Status SetRejected(bool rejected)
Set &quot;jigsaw&quot; rejected flag for a measure.
Distance measurement, usually in meters.
Definition: Distance.h:47
void measureDeleted(ControlMeasure *measure)
Updates the ControlCubeGraphNode for this measure&#39;s serial number to reflect the deletion.
Definition: ControlNet.cpp:514
QString GetReferenceSN() const
void measureAdded(ControlMeasure *measure)
Updates the ControlCubeGraphNode for the measure&#39;s serial number to reflect the addition.
Definition: ControlNet.cpp:377
Status SetAdjustedSurfacePoint(SurfacePoint newSurfacePoint)
Set or update the surface point relating to this control point.
void SetRadii(const Distance &majorRadius, const Distance &minorRadius, const Distance &polarRadius)
Reset the radii of the surface body of the surface point.
A Free point is a Control Point that identifies common measurements between two or more cubes...
Definition: ControlPoint.h:369
double DetectorLine() const
Return detector line.
Radar Camera.
Definition: Camera.h:363
static QString SurfacePointSourceToString(SurfacePointSource::Source source)
Obtain a string representation of a given SurfacePointSource.
bool HasSerialNumber(QString serialNumber) const
Return true if given serial number exists in point.
SurfacePoint adjustedSurfacePoint
This is the calculated, or aposterori, surface point.
Definition: ControlPoint.h:682
static QString RadiusSourceToString(RadiusSource::Source source)
Obtain a string representation of a given RadiusSource.
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:166
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:109
Status SetAprioriSurfacePointSourceFile(QString sourceFile)
This updates the filename of where the apriori surface point came from.
double DetectorSample() const
Return detector sample.
QString GetRadiusSourceString() const
Obtain a string representation of the RadiusSource.
Status SetResidual(double sampResidual, double lineResidual)
Set the BundleAdjust Residual of the coordinate.
QString GetId() const
Return the Id of the control point.
Convert between distorted focal plane and detector coordinates.
static RadiusSource::Source StringToRadiusSource(QString str)
Obtain a RadiusSource::Source from a string.
CameraGroundMap * GroundMap()
Returns a pointer to the CameraGroundMap object.
Definition: Camera.cpp:2916
virtual bool SetUndistortedFocalPlane(double ux, double uy)
Compute distorted focal plane x/y.
Status SetDateTime(QString newDateTime)
Set the point&#39;s last modified time.
static QString DateTime(time_t *curtime=0)
Returns the date and time as a QString.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
Status SetRefMeasure(ControlMeasure *cm)
Set the point&#39;s reference measure.
bool isValid() const
Test if this distance has been initialized or not.
Definition: Distance.cpp:204
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:134
Status SetAprioriSurfacePoint(SurfacePoint aprioriSP)
This updates the apriori surface point.
SurfacePoint GetBestSurfacePoint() const
Returns the adjusted surface point if it exists, otherwise returns the a priori surface point...
This is returned when an operation cannot be performed due to a problem such as the point is ignored ...
Definition: ControlPoint.h:384
A single control point.
Definition: ControlPoint.h:339
bool referenceExplicitlySet
This indicates if a program has explicitely set the reference in this point or the implicit reference...
Definition: ControlPoint.h:643
int IndexOf(ControlMeasure *, bool throws=true) const
SurfacePoint GetSurfacePoint() const
Returns the surface point (most efficient accessor).
Definition: Sensor.cpp:270
const ControlPoint & operator=(const ControlPoint &pPoint)
bool IsReferenceExplicit() const
bool ignore
True if we should preserve but ignore the entire control point and its measures.
Definition: ControlPoint.h:649
bool IsEditLocked() const
Return value for p_editLock or implicit lock on reference measure.
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
bool invalid
If we forced a build that we would normally have thrown an exception for then this is set to true...
Definition: ControlPoint.h:617
CameraFocalPlaneMap * FocalPlaneMap()
Returns a pointer to the CameraFocalPlaneMap object.
Definition: Camera.cpp:2896
~ControlPoint()
This destroys the current instance and cleans up any and all allocated memory.
Status SetRejected(bool rejected)
Set the jigsawRejected state.
Status SetType(PointType newType)
Updates the control point&#39;s type.
PointType type
What this control point is tying together.
Definition: ControlPoint.h:610
Status SetId(QString id)
Sets the Id of the control point.
void Coordinate(double p[3]) const
Returns the x,y,z of the surface intersection in BodyFixed km.
Definition: Sensor.cpp:211
static SurfacePointSource::Source StringToSurfacePointSource(QString str)
Obtain a SurfacePoint::Source from a string.
void ValidateMeasure(QString serialNumber) const
Throws an exception if none of the point&#39;s measures have the given serial number. ...
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Status
This is a return status for many of the mutating (setter) method calls.
Definition: ControlPoint.h:378
SurfacePointSource::Source aprioriSurfacePointSource
Where the apriori surface point originated from.
Definition: ControlPoint.h:652
void Load(PvlObject &p)
Loads the PvlObject into a ControlPoint.
void SetExplicitReference(ControlMeasure *measure)
Explicitly defines a new reference measure by pointer.
int numberOfRejectedMeasures
This parameter is used and maintained by BundleAdjust for the jigsaw application. ...
Definition: ControlPoint.h:689
QString chooserName
This is the user name of the person who last modified this control point.
Definition: ControlPoint.h:598
double GetResidualRms() const
Get rms of residuals.
double FocalPlaneY() const
Return distorted focal plane y.
Status SetFocalPlaneMeasured(double x, double y)
Set the focal plane x/y for the measured line/sample.
bool operator==(const ControlPoint &pPoint) const
Compare two Control Points for equality.
QString aprioriRadiusSourceFile
The name of the file that derives the apriori surface point&#39;s radius.
Definition: ControlPoint.h:666
QString aprioriSurfacePointSourceFile
FileName where the apriori surface point originated from.
Definition: ControlPoint.h:655
int GetNumberOfRejectedMeasures() const
Get the number of rejected measures on the control point.
QList< ControlMeasure * > getMeasures(bool excludeIgnored=false) const
Displacement is a signed length, usually in meters.
Definition: Displacement.h:43
Isis exception class.
Definition: IException.h:99
bool operator!=(const ControlPoint &pPoint) const
Compare two Control Points for inequality.
a control measurement
QString GetCubeSerialNumber() const
Return the serial number of the cube containing the coordinate.
Status ResetApriori()
Reset all the Apriori info to defaults.
int GetNumLockedMeasures() const
Returns the number of locked control measures.
int Delete(ControlMeasure *measure)
Remove a measurement from the control point, deleting reference measure is allowed.
void AddMeasure(ControlMeasure *measure)
Do the actual work of adding a measure to this point, without changing any extra data.
QString GetSurfacePointSourceString() const
Obtain a string representation of the SurfacePointSource.
double FocalPlaneX() const
Return distorted focal plane x.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:158
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
const ControlMeasure * GetMeasure(QString serialNumber) const
Get a control measure based on its cube&#39;s serial number.
QList< QString > getCubeSerialNumbers() const
double UndistortedFocalPlaneX() const
Return undistorted focal plane x.
static QString PointTypeToString(PointType type)
Obtain a string representation of a given PointType.
int IndexOfRefMeasure() const
std::bitset< 6 > constraintStatus
This stores the constraint status of the a priori SurfacePoint.
Definition: ControlPoint.h:635
Status SetAprioriRadiusSource(RadiusSource::Source source)
This updates the source of the radius of the apriori surface point.
Status ComputeResiduals()
This method computes the BundleAdjust residuals for a point.
Status SetFocalPlaneComputed(double x, double y)
Set the computed focal plane x/y for the apriori lat/lon.
void measureUnIgnored(ControlMeasure *measure)
Updates the connections for the ControlCubeGraphNode associated with the measure&#39;s serial number to r...
Definition: ControlNet.cpp:441
double GetLineResidualRms() const
Get rms of line residuals.
This is returned when the operation successfully took effect.
Definition: ControlPoint.h:388
This is the status of constrained coordinates in the SurfacePoint.
Definition: ControlPoint.h:407
static PointType StringToPointType(QString pointTypeString)
Obtain a PointType given a string representation of it.
void SetRectangular(const Displacement &x, const Displacement &y, const Displacement &z, const Distance &xSigma=Distance(), const Distance &ySigma=Distance(), const Distance &zSigma=Distance())
Set surface point in rectangular body-fixed coordinates wtih optional sigmas.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
This is returned when the operation requires Edit Lock to be false but it is currently true...
Definition: ControlPoint.h:393
RadiusSource::Source aprioriRadiusSource
Where the apriori surface point&#39;s radius originated from, most commonly used by jigsaw.
Definition: ControlPoint.h:661

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:16:39