USGS

Isis 3.0 Object Programmers' Reference

Home

ControlNetVersioner.cpp
1 #include "ControlNetVersioner.h"
2 
3 #include <string>
4 
5 #include <QDebug>
6 
7 #include "ControlNetFile.h"
8 #include "ControlNetFileV0001.h"
9 #include "ControlNetFileV0002.h"
10 #include "ControlNetFileV0002.pb.h"
11 #include "ControlMeasureLogData.h"
12 #include "Distance.h"
13 #include "FileName.h"
14 #include "IException.h"
15 #include "IString.h"
16 #include "Latitude.h"
17 #include "Longitude.h"
18 #include "NaifStatus.h"
19 #include "Progress.h"
20 #include "TProjection.h"
21 #include "Pvl.h"
22 #include "PvlGroup.h"
23 #include "PvlKeyword.h"
24 #include "PvlObject.h"
25 #include "SurfacePoint.h"
26 
27 using namespace std;
28 
29 namespace Isis {
39  LatestControlNetFile *ControlNetVersioner::Read(
40  const FileName &networkFileName) {
41  try {
42  Pvl network(networkFileName.expanded());
43 
44  if(network.hasObject("ProtoBuffer")) {
45  return ReadBinaryNetwork(network, networkFileName);
46  }
47  else if(network.hasObject("ControlNetwork")) {
48  return ReadPvlNetwork(network);
49  }
50  else {
51  IString msg = "Could not determine the control network file type";
52  throw IException(IException::Io, msg, _FILEINFO_);
53  }
54  }
55  catch(IException &e) {
56  IString msg = "Reading the control network [" + networkFileName.name()
57  + "] failed";
58  throw IException(e, IException::Io, msg, _FILEINFO_);
59  }
60  }
61 
62 
71  void ControlNetVersioner::Write(const FileName &file,
72  const LatestControlNetFile &fileData, bool pvl) {
73  if(pvl) {
74  fileData.toPvl().write(file.expanded());
75  }
76  else {
77  fileData.Write(file);
78  }
79  }
80 
81 
98  LatestControlNetFile *ControlNetVersioner::ReadPvlNetwork(Pvl pvl) {
99  PvlObject &network = pvl.findObject("ControlNetwork");
100 
101  if(!network.hasKeyword("Version"))
102  network += PvlKeyword("Version", "1");
103 
104  int version = toInt(network["Version"][0]);
105 
106  while(version != LATEST_PVL_VERSION) {
107  int previousVersion = version;
108 
109  switch(version) {
110  case 1:
111  ConvertVersion1ToVersion2(network);
112  break;
113 
114  case 2:
115  ConvertVersion2ToVersion3(network);
116  break;
117 
118  case 3:
119  ConvertVersion3ToVersion4(network);
120  break;
121 
122  default:
123  IString msg = "The Pvl file version [" + IString(version) + "] is not"
124  " supported";
125  throw IException(IException::Unknown, msg, _FILEINFO_);
126  }
127 
128  version = toInt(network["Version"][0]);
129 
130  if(version == previousVersion) {
131  IString msg = "Cannot update from version [" + IString(version) + "] "
132  "to any other version";
133  throw IException(IException::Programmer, msg, _FILEINFO_);
134  }
135  }
136 
137  return LatestPvlToBinary(network);
138  }
139 
140 
153  LatestControlNetFile *ControlNetVersioner::LatestPvlToBinary(
154  PvlObject &network) {
156 
157  ControlNetFileHeaderV0002 &header = latest->GetNetworkHeader();
158 
159  header.set_networkid(network.findKeyword("NetworkId")[0].toAscii().data());
160  header.set_targetname(network.findKeyword("TargetName")[0].toAscii().data());
161  header.set_created(network.findKeyword("Created")[0].toAscii().data());
162  header.set_lastmodified(network.findKeyword("LastModified")[0].toAscii().data());
163  header.set_description(network.findKeyword("Description")[0].toAscii().data());
164  header.set_username(network.findKeyword("UserName")[0].toAscii().data());
165  header.add_pointmessagesizes(0); // Just to pass the "IsInitialized" test
166 
167  if(!header.IsInitialized()) {
168  IString msg = "There is missing required information in the network "
169  "header";
170  throw IException(IException::Io, msg, _FILEINFO_);
171  }
172 
174 
175  for(int objectIndex = 0; objectIndex < network.objects(); objectIndex ++) {
177  PvlObject &object = network.object(objectIndex);
178 
179  Copy(object, "PointId",
180  point, &ControlPointFileEntryV0002::set_id);
181  Copy(object, "ChooserName",
182  point, &ControlPointFileEntryV0002::set_choosername);
183  Copy(object, "DateTime",
184  point, &ControlPointFileEntryV0002::set_datetime);
185  Copy(object, "AprioriXYZSourceFile",
186  point, &ControlPointFileEntryV0002::set_apriorisurfpointsourcefile);
187  Copy(object, "AprioriRadiusSourceFile",
188  point, &ControlPointFileEntryV0002::set_aprioriradiussourcefile);
189  Copy(object, "JigsawRejected",
190  point, &ControlPointFileEntryV0002::set_jigsawrejected);
191  Copy(object, "EditLock",
192  point, &ControlPointFileEntryV0002::set_editlock);
193  Copy(object, "Ignore",
194  point, &ControlPointFileEntryV0002::set_ignore);
195  Copy(object, "AprioriX",
196  point, &ControlPointFileEntryV0002::set_apriorix);
197  Copy(object, "AprioriY",
198  point, &ControlPointFileEntryV0002::set_aprioriy);
199  Copy(object, "AprioriZ",
200  point, &ControlPointFileEntryV0002::set_aprioriz);
201  Copy(object, "AdjustedX",
202  point, &ControlPointFileEntryV0002::set_adjustedx);
203  Copy(object, "AdjustedY",
204  point, &ControlPointFileEntryV0002::set_adjustedy);
205  Copy(object, "AdjustedZ",
206  point, &ControlPointFileEntryV0002::set_adjustedz);
207  Copy(object, "LatitudeConstrained",
208  point, &ControlPointFileEntryV0002::set_latitudeconstrained);
209  Copy(object, "LongitudeConstrained",
210  point, &ControlPointFileEntryV0002::set_longitudeconstrained);
211  Copy(object, "RadiusConstrained",
212  point, &ControlPointFileEntryV0002::set_radiusconstrained);
213 
214  if (object["PointType"][0] == "Fixed")
215  point.set_type(ControlPointFileEntryV0002::Fixed);
216  else if (object["PointType"][0] == "Constrained")
217  point.set_type(ControlPointFileEntryV0002::Constrained);
218  else
219  point.set_type(ControlPointFileEntryV0002::Free);
220 
221  if (object.hasKeyword("AprioriXYZSource")) {
222  IString source = object["AprioriXYZSource"][0];
223 
224  if (source == "None") {
225  point.set_apriorisurfpointsource(ControlPointFileEntryV0002::None);
226  }
227  else if (source == "User") {
228  point.set_apriorisurfpointsource(ControlPointFileEntryV0002::User);
229  }
230  else if (source == "AverageOfMeasures") {
231  point.set_apriorisurfpointsource(
232  ControlPointFileEntryV0002::AverageOfMeasures);
233  }
234  else if (source == "Reference") {
235  point.set_apriorisurfpointsource(
236  ControlPointFileEntryV0002::Reference);
237  }
238  else if (source == "Basemap") {
239  point.set_apriorisurfpointsource(
240  ControlPointFileEntryV0002::Basemap);
241  }
242  else if (source == "BundleSolution") {
243  point.set_apriorisurfpointsource(
244  ControlPointFileEntryV0002::BundleSolution);
245  }
246  else {
247  IString msg = "Invalid AprioriXYZSource [" + source + "]";
248  throw IException(IException::User, msg, _FILEINFO_);
249  }
250  }
251 
252  if (object.hasKeyword("AprioriRadiusSource")) {
253  IString source = object["AprioriRadiusSource"][0];
254 
255  if (source == "None") {
256  point.set_aprioriradiussource(ControlPointFileEntryV0002::None);
257  }
258  else if (source == "User") {
259  point.set_aprioriradiussource(ControlPointFileEntryV0002::User);
260  }
261  else if (source == "AverageOfMeasures") {
262  point.set_aprioriradiussource(
263  ControlPointFileEntryV0002::AverageOfMeasures);
264  }
265  else if (source == "Ellipsoid") {
266  point.set_aprioriradiussource(ControlPointFileEntryV0002::Ellipsoid);
267  }
268  else if (source == "DEM") {
269  point.set_aprioriradiussource(ControlPointFileEntryV0002::DEM);
270  }
271  else if (source == "BundleSolution") {
272  point.set_aprioriradiussource(
273  ControlPointFileEntryV0002::BundleSolution);
274  }
275  else {
276  std::string msg = "Invalid AprioriRadiusSource, [" + source + "]";
277  throw IException(IException::User, msg, _FILEINFO_);
278  }
279  }
280 
281  if (object.hasKeyword("AprioriCovarianceMatrix")) {
282  PvlKeyword &matrix = object["AprioriCovarianceMatrix"];
283 
284  point.add_aprioricovar(toDouble(matrix[0]));
285  point.add_aprioricovar(toDouble(matrix[1]));
286  point.add_aprioricovar(toDouble(matrix[2]));
287  point.add_aprioricovar(toDouble(matrix[3]));
288  point.add_aprioricovar(toDouble(matrix[4]));
289  point.add_aprioricovar(toDouble(matrix[5]));
290  }
291 
292  if(object.hasKeyword("AdjustedCovarianceMatrix")) {
293  PvlKeyword &matrix = object["AdjustedCovarianceMatrix"];
294 
295  point.add_adjustedcovar(toDouble(matrix[0]));
296  point.add_adjustedcovar(toDouble(matrix[1]));
297  point.add_adjustedcovar(toDouble(matrix[2]));
298  point.add_adjustedcovar(toDouble(matrix[3]));
299  point.add_adjustedcovar(toDouble(matrix[4]));
300  point.add_adjustedcovar(toDouble(matrix[5]));
301  }
302 
303  // Process Measures
304  for (int groupIndex = 0; groupIndex < object.groups(); groupIndex ++) {
305  PvlGroup &group = object.group(groupIndex);
307 
308  Copy(group, "SerialNumber",
309  measure, &ControlPointFileEntryV0002::Measure::set_serialnumber);
310  Copy(group, "ChooserName",
311  measure, &ControlPointFileEntryV0002::Measure::set_choosername);
312  Copy(group, "Sample",
313  measure, &ControlPointFileEntryV0002::Measure::set_sample);
314  Copy(group, "Line",
315  measure, &ControlPointFileEntryV0002::Measure::set_line);
316  Copy(group, "SampleResidual",
317  measure, &ControlPointFileEntryV0002::Measure::set_sampleresidual);
318  Copy(group, "LineResidual",
319  measure, &ControlPointFileEntryV0002::Measure::set_lineresidual);
320  Copy(group, "DateTime",
321  measure, &ControlPointFileEntryV0002::Measure::set_datetime);
322  Copy(group, "Diameter",
323  measure, &ControlPointFileEntryV0002::Measure::set_diameter);
324  Copy(group, "EditLock",
325  measure, &ControlPointFileEntryV0002::Measure::set_editlock);
326  Copy(group, "Ignore",
327  measure, &ControlPointFileEntryV0002::Measure::set_ignore);
328  Copy(group, "JigsawRejected",
329  measure, &ControlPointFileEntryV0002::Measure::set_jigsawrejected);
330  Copy(group, "AprioriSample",
331  measure, &ControlPointFileEntryV0002::Measure::set_apriorisample);
332  Copy(group, "AprioriLine",
333  measure, &ControlPointFileEntryV0002::Measure::set_aprioriline);
334  Copy(group, "SampleSigma",
335  measure, &ControlPointFileEntryV0002::Measure::set_samplesigma);
336  Copy(group, "LineSigma",
337  measure, &ControlPointFileEntryV0002::Measure::set_linesigma);
338 
339  if(group.hasKeyword("Reference")) {
340  if(group["Reference"][0].toLower() == "true")
341  point.set_referenceindex(groupIndex);
342 
343  group.deleteKeyword("Reference");
344  }
345 
346  QString type = group["MeasureType"][0].toLower();
347  if(type == "candidate")
348  measure.set_type(ControlPointFileEntryV0002::Measure::Candidate);
349  else if(type == "manual")
350  measure.set_type(ControlPointFileEntryV0002::Measure::Manual);
351  else if(type == "registeredpixel")
352  measure.set_type(
353  ControlPointFileEntryV0002::Measure::RegisteredPixel);
354  else if(type == "registeredsubpixel")
355  measure.set_type(
356  ControlPointFileEntryV0002::Measure::RegisteredSubPixel);
357  else
358  throw IException(IException::Io,
359  "Unknown measure type [" + type + "]",
360  _FILEINFO_);
361  group.deleteKeyword("MeasureType");
362 
363  for(int key = 0; key < group.keywords(); key++) {
364  ControlMeasureLogData interpreter(group[key]);
365  if(!interpreter.IsValid()) {
366  IString msg = "Unhandled or duplicate keywords in control measure ["
367  + group[key].name() + "]";
368  throw IException(IException::Programmer, msg, _FILEINFO_);
369  }
370  else {
371  *measure.add_log() = interpreter.ToProtocolBuffer();
372  }
373  }
374 
375  *point.add_measures() = measure;
376  }
377 
378  if(!point.IsInitialized()) {
379  IString msg = "There is missing required information in the control "
380  "points or measures";
381  throw IException(IException::Io, msg, _FILEINFO_);
382  }
383 
384  points.append(point);
385  }
386 
387  return latest;
388  }
389 
390 
399  LatestControlNetFile *ControlNetVersioner::ReadBinaryNetwork(
400  const Pvl &header, const FileName &filename) {
401  // Find the binary cnet version by any means necessary
402  int version = 1;
403 
404  const PvlObject &protoBuf = header.findObject("ProtoBuffer");
405  const PvlGroup &netInfo = protoBuf.findGroup("ControlNetworkInfo");
406 
407  if(netInfo.hasKeyword("Version"))
408  version = toInt(netInfo["Version"][0]);
409 
410  // Okay, let's instantiate the correct ControlNetFile for this version
411  ControlNetFile *cnetFile;
412  switch(version) {
413  case 1:
414  cnetFile = new ControlNetFileV0001;
415  break;
416 
417  case 2:
418  cnetFile = new ControlNetFileV0002;
419  break;
420 
421  default:
422  IString msg = "The binary file version [" + IString(version) + "] is "
423  "not supported";
424  throw IException(IException::Io, msg, _FILEINFO_);
425  }
426 
427  // Now read and update as necessary
428  cnetFile->Read(header, filename);
429 
430  if(version != LATEST_BINARY_VERSION) {
431  Pvl pvl(cnetFile->toPvl());
432 
433  delete cnetFile;
434  cnetFile = NULL;
435 
436  return ReadPvlNetwork(pvl);
437  }
438  else {
439  return (LatestControlNetFile *)cnetFile;
440  }
441  }
442 
443 
461  void ControlNetVersioner::ConvertVersion1ToVersion2(
462  PvlObject &network) {
463  network["Version"] = "2";
464 
465  // Really... Projection::TargetRadii should be making this call
466  NaifStatus::CheckErrors();
467 
468  if (QString(network["TargetName"]).startsWith("MRO/")) {
469  network["TargetName"] = "Mars";
470  }
471 
472  PvlGroup radii;
473  try {
474  radii = TProjection::TargetRadii(network["TargetName"]);
475  }
476  catch(IException &e) {
477  try {
478  NaifStatus::CheckErrors();
479  }
480  catch (IException &) {
481  }
482 
483  QString msg = "The target name is not recognized";
484  throw IException(e, IException::Io, msg, _FILEINFO_);
485  }
486 
487  Distance equatorialRadius(radii["EquatorialRadius"], Distance::Meters);
488  Distance polarRadius(radii["PolarRadius"], Distance::Meters);
489 
490  for(int cpIndex = 0; cpIndex < network.objects(); cpIndex ++) {
491  PvlObject &cp = network.object(cpIndex);
492 
493  if(cp.hasKeyword("Held") && cp["Held"][0] == "True")
494  cp["PointType"] = "Ground";
495 
496  if(cp.hasKeyword("AprioriLatLonSource"))
497  cp["AprioriLatLonSource"].setName("AprioriXYZSource");
498 
499  if(cp.hasKeyword("AprioriLatLonSourceFile"))
500  cp["AprioriLatLonSourceFile"].setName("AprioriXYZSourceFile");
501 
502  if(cp.hasKeyword("AprioriLatitude")) {
503  SurfacePoint apriori(
504  Latitude(toDouble(cp["AprioriLatitude"][0]), Angle::Degrees),
505  Longitude(toDouble(cp["AprioriLongitude"][0]), Angle::Degrees),
506  Distance(toDouble(cp["AprioriRadius"][0]), Distance::Meters));
507 
508  cp += PvlKeyword("AprioriX", toString(apriori.GetX().meters()), "meters");
509  cp += PvlKeyword("AprioriY", toString(apriori.GetY().meters()), "meters");
510  cp += PvlKeyword("AprioriZ", toString(apriori.GetZ().meters()), "meters");
511  }
512 
513  if(cp.hasKeyword("Latitude")) {
514  SurfacePoint adjusted(
515  Latitude(toDouble(cp["Latitude"][0]), Angle::Degrees),
516  Longitude(toDouble(cp["Longitude"][0]), Angle::Degrees),
517  Distance(toDouble(cp["Radius"][0]), Distance::Meters));
518 
519  cp += PvlKeyword("AdjustedX", toString(adjusted.GetX().meters()), "meters");
520  cp += PvlKeyword("AdjustedY", toString(adjusted.GetY().meters()), "meters");
521  cp += PvlKeyword("AdjustedZ", toString(adjusted.GetZ().meters()), "meters");
522 
523  if(!cp.hasKeyword("AprioriLatitude")) {
524  cp += PvlKeyword("AprioriX", toString(adjusted.GetX().meters()), "meters");
525  cp += PvlKeyword("AprioriY", toString(adjusted.GetY().meters()), "meters");
526  cp += PvlKeyword("AprioriZ", toString(adjusted.GetZ().meters()), "meters");
527  }
528  }
529 
530  if(cp.hasKeyword("X"))
531  cp["X"].setName("AdjustedX");
532 
533  if(cp.hasKeyword("Y"))
534  cp["Y"].setName("AdjustedY");
535 
536  if(cp.hasKeyword("Z"))
537  cp["Z"].setName("AdjustedZ");
538 
539  if(cp.hasKeyword("AprioriSigmaLatitude") ||
540  cp.hasKeyword("AprioriSigmaLongitude") ||
541  cp.hasKeyword("AprioriSigmaRadius")) {
542  double sigmaLat = 10000.0;
543  double sigmaLon = 10000.0;
544  double sigmaRad = 10000.0;
545 
546  if(cp.hasKeyword("AprioriSigmaLatitude")) {
547  if(toDouble(cp["AprioriSigmaLatitude"][0]) > 0 &&
548  toDouble(cp["AprioriSigmaLatitude"][0]) < sigmaLat)
549  sigmaLat = cp["AprioriSigmaLatitude"];
550 
551  cp += PvlKeyword("LatitudeConstrained", "True");
552  }
553 
554  if(cp.hasKeyword("AprioriSigmaLongitude")) {
555  if(toDouble(cp["AprioriSigmaLongitude"][0]) > 0 &&
556  toDouble(cp["AprioriSigmaLongitude"][0]) < sigmaLon)
557  sigmaLon = cp["AprioriSigmaLongitude"];
558 
559  cp += PvlKeyword("LongitudeConstrained", "True");
560  }
561 
562  if(cp.hasKeyword("AprioriSigmaRadius")) {
563  if(toDouble(cp["AprioriSigmaRadius"][0]) > 0 &&
564  toDouble(cp["AprioriSigmaRadius"][0]) < sigmaRad)
565  sigmaRad = cp["AprioriSigmaRadius"];
566 
567  cp += PvlKeyword("RadiusConstrained", "True");
568  }
569 
570  SurfacePoint tmp;
571  tmp.SetRadii(equatorialRadius, equatorialRadius, polarRadius);
572  tmp.SetRectangular(
573  Displacement(cp["AprioriX"], Displacement::Meters),
574  Displacement(cp["AprioriY"], Displacement::Meters),
575  Displacement(cp["AprioriZ"], Displacement::Meters));
577  Distance(sigmaLat, Distance::Meters),
578  Distance(sigmaLon, Distance::Meters),
579  Distance(sigmaRad, Distance::Meters));
580 
581  PvlKeyword aprioriCovarMatrix("AprioriCovarianceMatrix");
582  aprioriCovarMatrix += toString(tmp.GetRectangularMatrix()(0, 0));
583  aprioriCovarMatrix += toString(tmp.GetRectangularMatrix()(0, 1));
584  aprioriCovarMatrix += toString(tmp.GetRectangularMatrix()(0, 2));
585  aprioriCovarMatrix += toString(tmp.GetRectangularMatrix()(1, 1));
586  aprioriCovarMatrix += toString(tmp.GetRectangularMatrix()(1, 2));
587  aprioriCovarMatrix += toString(tmp.GetRectangularMatrix()(2, 2));
588 
589  cp += aprioriCovarMatrix;
590  }
591 
592  if(cp.hasKeyword("AdjustedSigmaLatitude") ||
593  cp.hasKeyword("AdjustedSigmaLongitude") ||
594  cp.hasKeyword("AdjustedSigmaRadius")) {
595  double sigmaLat = 10000.0;
596  double sigmaLon = 10000.0;
597  double sigmaRad = 10000.0;
598 
599  if(cp.hasKeyword("AdjustedSigmaLatitude")) {
600  if(toDouble(cp["AdjustedSigmaLatitude"][0]) > 0 &&
601  toDouble(cp["AdjustedSigmaLatitude"][0]) < sigmaLat)
602  sigmaLat = cp["AdjustedSigmaLatitude"];
603  }
604 
605  if(cp.hasKeyword("AdjustedSigmaLongitude")) {
606  if(toDouble(cp["AdjustedSigmaLongitude"][0]) > 0 &&
607  toDouble(cp["AdjustedSigmaLongitude"][0]) < sigmaLon)
608  sigmaLon = cp["AdjustedSigmaLongitude"];
609  }
610 
611  if(cp.hasKeyword("AdjustedSigmaRadius")) {
612  if(toDouble(cp["AdjustedSigmaRadius"][0]) > 0 &&
613  toDouble(cp["AdjustedSigmaRadius"][0]) < sigmaRad)
614  sigmaRad = cp["AdjustedSigmaRadius"];
615  }
616 
617  SurfacePoint tmp;
618  tmp.SetRadii(equatorialRadius, equatorialRadius, polarRadius);
619  tmp.SetRectangular(
620  Displacement(cp["AdjustedX"], Displacement::Meters),
621  Displacement(cp["AdjustedY"], Displacement::Meters),
622  Displacement(cp["AdjustedZ"], Displacement::Meters));
624  Distance(sigmaLat, Distance::Meters),
625  Distance(sigmaLon, Distance::Meters),
626  Distance(sigmaRad, Distance::Meters));
627 
628  PvlKeyword adjustedCovarMatrix("AdjustedCovarianceMatrix");
629  adjustedCovarMatrix += toString(tmp.GetRectangularMatrix()(0, 0));
630  adjustedCovarMatrix += toString(tmp.GetRectangularMatrix()(0, 1));
631  adjustedCovarMatrix += toString(tmp.GetRectangularMatrix()(0, 2));
632  adjustedCovarMatrix += toString(tmp.GetRectangularMatrix()(1, 1));
633  adjustedCovarMatrix += toString(tmp.GetRectangularMatrix()(1, 2));
634  adjustedCovarMatrix += toString(tmp.GetRectangularMatrix()(2, 2));
635 
636  cp += adjustedCovarMatrix;
637  }
638 
639  if(cp.hasKeyword("ApostCovarianceMatrix"))
640  cp["ApostCovarianceMatrix"].setName("AdjustedCovarianceMatrix");
641 
642  if(!cp.hasKeyword("LatitudeConstrained")) {
643  if(cp.hasKeyword("AprioriCovarianceMatrix"))
644  cp += PvlKeyword("LatitudeConstrained", "True");
645  else
646  cp += PvlKeyword("LatitudeConstrained", "False");
647  }
648 
649  if(!cp.hasKeyword("LongitudeConstrained")) {
650  if(cp.hasKeyword("AprioriCovarianceMatrix"))
651  cp += PvlKeyword("LongitudeConstrained", "True");
652  else
653  cp += PvlKeyword("LongitudeConstrained", "False");
654  }
655 
656  if(!cp.hasKeyword("RadiusConstrained")) {
657  if(cp.hasKeyword("AprioriCovarianceMatrix"))
658  cp += PvlKeyword("RadiusConstrained", "True");
659  else
660  cp += PvlKeyword("RadiusConstrained", "False");
661  }
662 
663  // Delete anything that has no value...
664  for(int cpKeyIndex = 0; cpKeyIndex < cp.keywords(); cpKeyIndex ++) {
665  if(cp[cpKeyIndex][0] == "") {
666  cp.deleteKeyword(cpKeyIndex);
667  }
668  }
669 
670  for(int cmIndex = 0; cmIndex < cp.groups(); cmIndex ++) {
671  PvlGroup &cm = cp.group(cmIndex);
672 
673  // Estimated => Candidate
674  if(cm.hasKeyword("MeasureType")) {
675  QString type = cm["MeasureType"][0].toLower();
676 
677  if(type == "estimated" || type == "unmeasured") {
678  if (type == "unmeasured") {
679  bool hasSampleLine = false;
680 
681  try {
682  toDouble(cm["Sample"][0]);
683  toDouble(cm["Line"][0]);
684  hasSampleLine = true;
685  }
686  catch (...) {
687  }
688 
689  if (!hasSampleLine) {
690  cm.addKeyword(PvlKeyword("Sample", "0.0"), PvlContainer::Replace);
691  cm.addKeyword(PvlKeyword("Line", "0.0"), PvlContainer::Replace);
692  cm.addKeyword(PvlKeyword("Ignore", toString(true)), PvlContainer::Replace);
693  }
694  }
695 
696  cm["MeasureType"] = "Candidate";
697  }
698  else if(type == "automatic" || type == "validatedmanual" ||
699  type == "automaticpixel") {
700  cm["MeasureType"] = "RegisteredPixel";
701  }
702  else if(type == "validatedautomatic" ||
703  type == "automaticsubpixel") {
704  cm["MeasureType"] = "RegisteredSubPixel";
705  }
706  }
707 
708  if(cm.hasKeyword("ErrorSample"))
709  cm["ErrorSample"].setName("SampleResidual");
710 
711  if(cm.hasKeyword("ErrorLine"))
712  cm["ErrorLine"].setName("LineResidual");
713 
714  // Delete some extraneous values we once printed
715  if(cm.hasKeyword("SampleResidual") &&
716  toDouble(cm["SampleResidual"][0]) == 0.0)
717  cm.deleteKeyword("SampleResidual");
718 
719  if(cm.hasKeyword("LineResidual") &&
720  toDouble(cm["LineResidual"][0]) == 0.0)
721  cm.deleteKeyword("LineResidual");
722 
723  if(cm.hasKeyword("Diameter") &&
724  toDouble(cm["Diameter"][0]) == 0.0)
725  cm.deleteKeyword("Diameter");
726 
727  if(cm.hasKeyword("ErrorMagnitude"))
728  cm.deleteKeyword("ErrorMagnitude");
729 
730  if(cm.hasKeyword("ZScore"))
731  cm.deleteKeyword("ZScore");
732 
733  // Delete anything that has no value...
734  for(int cmKeyIndex = 0; cmKeyIndex < cm.keywords(); cmKeyIndex ++) {
735  if(cm[cmKeyIndex][0] == "") {
736  cm.deleteKeyword(cmKeyIndex);
737  }
738  }
739  }
740  }
741  }
742 
743 
744 
752  void ControlNetVersioner::ConvertVersion2ToVersion3(
753  PvlObject &network) {
754  network["Version"] = "3";
755 
756  for(int cpIndex = 0; cpIndex < network.objects(); cpIndex ++) {
757  PvlObject &cp = network.object(cpIndex);
758 
759  if(cp.hasKeyword("AprioriCovarianceMatrix") ||
760  cp.hasKeyword("AdjustedCovarianceMatrix"))
761  cp["PointType"] = "Constrained";
762  }
763  }
764 
765 
773  void ControlNetVersioner::ConvertVersion3ToVersion4(
774  PvlObject &network) {
775  network["Version"] = "4";
776 
777  for (int cpIndex = 0; cpIndex < network.objects(); cpIndex ++) {
778  PvlObject &cp = network.object(cpIndex);
779 
780  if (cp["PointType"][0] == "Ground") cp["PointType"] = "Fixed";
781  if (cp["PointType"][0] == "Tie") cp["PointType"] = "Free";
782  }
783  }
784 
785 
799  void ControlNetVersioner::Copy(PvlContainer &container,
800  QString keyName, ControlPointFileEntryV0002 &point,
801  void (ControlPointFileEntryV0002::*setter)(bool)) {
802  if(!container.hasKeyword(keyName))
803  return;
804 
805  QString value = container[keyName][0];
806  container.deleteKeyword(keyName);
807  value = value.toLower();
808  if(value == "true" || value == "yes")
809  (point.*setter)(true);
810  }
811 
812 
826  void ControlNetVersioner::Copy(PvlContainer &container,
827  QString keyName, ControlPointFileEntryV0002 &point,
828  void (ControlPointFileEntryV0002::*setter)(double)) {
829  if(!container.hasKeyword(keyName))
830  return;
831 
832  double value = toDouble(container[keyName][0]);
833  container.deleteKeyword(keyName);
834  (point.*setter)(value);
835  }
836 
837 
851  void ControlNetVersioner::Copy(PvlContainer &container,
852  QString keyName, ControlPointFileEntryV0002 &point,
853  void (ControlPointFileEntryV0002::*setter)(const std::string&)) {
854  if(!container.hasKeyword(keyName))
855  return;
856 
857  IString value = container[keyName][0];
858  container.deleteKeyword(keyName);
859  (point.*setter)(value);
860  }
861 
862 
876  void ControlNetVersioner::Copy(PvlContainer &container, QString keyName,
878  void (ControlPointFileEntryV0002::Measure::*setter)(bool)) {
879  if(!container.hasKeyword(keyName))
880  return;
881 
882  QString value = container[keyName][0];
883  container.deleteKeyword(keyName);
884  value = value.toLower();
885  if(value == "true" || value == "yes")
886  (measure.*setter)(true);
887  }
888 
889 
903  void ControlNetVersioner::Copy(PvlContainer &container, QString keyName,
905  void (ControlPointFileEntryV0002::Measure::*setter)(double)) {
906  if(!container.hasKeyword(keyName))
907  return;
908 
909  double value = toDouble(container[keyName][0]);
910  container.deleteKeyword(keyName);
911  (measure.*setter)(value);
912  }
913 
914 
928  void ControlNetVersioner::Copy(PvlContainer &container, QString keyName,
930  void (ControlPointFileEntryV0002::Measure::*set)(const std::string &)) {
931  if(!container.hasKeyword(keyName))
932  return;
933 
934  IString value = container[keyName][0];
935  container.deleteKeyword(keyName);
936  (measure.*set)(value);
937  }
938 }