Пример #1
0
void IsisMain() {
  // Open the input cube
  Process p;
  UserInterface &ui = Application::GetUserInterface();
  CubeAttributeInput cai;
  Cube *icube = p.SetInputCube(ui.GetFilename("FROM"), cai, ReadWrite);

  // Make sure at least one CK & SPK quality was selected
  if (!ui.GetBoolean("CKPREDICTED") && !ui.GetBoolean("CKRECON") && !ui.GetBoolean("CKSMITHED") && !ui.GetBoolean("CKNADIR")) {
    string msg = "At least one CK quality must be selected";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }
  if (!ui.GetBoolean("SPKPREDICTED") && !ui.GetBoolean("SPKRECON") && !ui.GetBoolean("SPKSMITHED")) {
    string msg = "At least one SPK quality must be selected";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  // Make sure it is not projected
  Projection *proj = NULL;
  try {
    proj = icube->Projection();
  } catch (iException &e) {
    proj = NULL;
    e.Clear();
  }

  if (proj != NULL) {
    string msg = "Can not initialize SPICE for a map projected cube";
    throw iException::Message(iException::User,msg,_FILEINFO_);
  }

  Pvl lab = *icube->Label();

  // if cube has existing polygon delete it
  if (icube->Label()->HasObject("Polygon")) {
    icube->Label()->DeleteObject("Polygon");
  }

  // Set up for getting the mission name
  // Get the directory where the system missions translation table is.
  string transFile = p.MissionData("base", "translations/MissionName2DataDir.trn");

  // Get the mission translation manager ready
  PvlTranslationManager missionXlater (lab, transFile);

  // Get the mission name so we can search the correct DB's for kernels
  string mission = missionXlater.Translate ("MissionName");

  // Get system base kernels
  unsigned int allowed = 0;
  unsigned int allowedCK = 0;
  unsigned int allowedSPK = 0;
  if (ui.GetBoolean("CKPREDICTED"))  allowedCK |= spiceInit::kernelTypeEnum("PREDICTED");
  if (ui.GetBoolean("CKRECON"))      allowedCK |= spiceInit::kernelTypeEnum("RECONSTRUCTED");
  if (ui.GetBoolean("CKSMITHED"))    allowedCK |= spiceInit::kernelTypeEnum("SMITHED");
  if (ui.GetBoolean("CKNADIR"))      allowedCK |= spiceInit::kernelTypeEnum("NADIR");
  if (ui.GetBoolean("SPKPREDICTED")) allowedSPK |= spiceInit::kernelTypeEnum("PREDICTED");
  if (ui.GetBoolean("SPKRECON"))     allowedSPK |= spiceInit::kernelTypeEnum("RECONSTRUCTED");
  if (ui.GetBoolean("SPKSMITHED"))   allowedSPK |= spiceInit::kernelTypeEnum("SMITHED");
  KernelDb baseKernels (allowed);
  KernelDb ckKernels (allowedCK);
  KernelDb spkKernels (allowedSPK);

  baseKernels.LoadSystemDb(mission);
  ckKernels.LoadSystemDb(mission);
  spkKernels.LoadSystemDb(mission);

  Kernel lk, pck, targetSpk, fk, ik, sclk, spk, iak, dem, exk;
  std::priority_queue< Kernel > ck;
  lk        = baseKernels.LeapSecond(lab);
  pck       = baseKernels.TargetAttitudeShape(lab);
  targetSpk = baseKernels.TargetPosition(lab);
  ik        = baseKernels.Instrument(lab);
  sclk      = baseKernels.SpacecraftClock(lab);
  iak       = baseKernels.InstrumentAddendum(lab);
  fk        = ckKernels.Frame(lab);
  ck        = ckKernels.SpacecraftPointing(lab);
  spk       = spkKernels.SpacecraftPosition(lab);

  if (ui.GetBoolean("CKNADIR")) {
    // Only add nadir if no spacecraft pointing found
    std::vector<std::string> kernels;
    kernels.push_back("Nadir");
    ck.push(Kernel((spiceInit::kernelTypes)0, kernels));
  }

  // Get user defined kernels and override ones already found
  GetUserEnteredKernel("LS", lk);
  GetUserEnteredKernel("PCK", pck);
  GetUserEnteredKernel("TSPK", targetSpk);
  GetUserEnteredKernel("FK", fk);
  GetUserEnteredKernel("IK", ik);
  GetUserEnteredKernel("SCLK", sclk);
  GetUserEnteredKernel("SPK", spk);
  GetUserEnteredKernel("IAK", iak);
  GetUserEnteredKernel("EXTRA", exk);

  // Get shape kernel
  if (ui.GetString ("SHAPE") == "USER") {
    GetUserEnteredKernel("MODEL", dem);
  } else if (ui.GetString("SHAPE") == "SYSTEM") {
    dem = baseKernels.Dem(lab);
  }

  bool kernelSuccess = false;

  if (ck.size() == 0 && !ui.WasEntered("CK")) {
    throw iException::Message(iException::Camera, 
                              "No Camera Kernel found for the image ["+ui.GetFilename("FROM")
                              +"]", 
                              _FILEINFO_);
  }
  else if(ui.WasEntered("CK")) {
    // ck needs to be array size 1 and empty kernel objects
    while(ck.size()) ck.pop();
    ck.push(Kernel());
  }

  while(ck.size() != 0 && !kernelSuccess) {
    Kernel realCkKernel = ck.top();
    ck.pop();

    if (ui.WasEntered("CK")) {
      ui.GetAsString("CK", realCkKernel.kernels);
    }

    // Merge SpacecraftPointing and Frame into ck
    for (int i = 0; i < fk.size(); i++) {
      realCkKernel.push_back(fk[i]);
    }

    kernelSuccess = TryKernels(icube, p, lk, pck, targetSpk,
                   realCkKernel, fk, ik, sclk, spk, iak, dem, exk);
  }

  if(!kernelSuccess) {
    throw iException::Message(iException::Camera, 
                              "Unable to initialize camera model", 
                              _FILEINFO_);
  }

  p.EndProcess();
}
Пример #2
0
void IsisMain() {
  // We will be warping a cube
  ProcessRubberSheet p;

  // Get the map projection file provided by the user
  UserInterface &ui = Application::GetUserInterface();
  Pvl userPvl(ui.GetFilename("MAP"));
  PvlGroup &userMappingGrp = userPvl.FindGroup("Mapping",Pvl::Traverse);

  // Open the input cube and get the projection
  Cube *icube = p.SetInputCube ("FROM");

  // Get the mapping group
  PvlGroup fromMappingGrp = icube->GetGroup("Mapping");
  Projection *inproj = icube->Projection();
  PvlGroup outMappingGrp = fromMappingGrp;

  // If the default range is FROM, then wipe out any range data in user mapping file
  if(ui.GetString("DEFAULTRANGE").compare("FROM") == 0 && !ui.GetBoolean("MATCHMAP")) {
    if(userMappingGrp.HasKeyword("MinimumLatitude")) {
      userMappingGrp.DeleteKeyword("MinimumLatitude");
    }

    if(userMappingGrp.HasKeyword("MaximumLatitude")) {
      userMappingGrp.DeleteKeyword("MaximumLatitude");
    }

    if(userMappingGrp.HasKeyword("MinimumLongitude")) {
      userMappingGrp.DeleteKeyword("MinimumLongitude");
    }

    if(userMappingGrp.HasKeyword("MaximumLongitude")) {
      userMappingGrp.DeleteKeyword("MaximumLongitude");
    }
  }

  // Deal with user overrides entered in the GUI. Do this by changing the user's mapping group, which
  // will then overlay anything in the output mapping group.
  if(ui.WasEntered("MINLAT") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MinimumLatitude", ui.GetDouble("MINLAT")), Pvl::Replace );
  }

  if(ui.WasEntered("MAXLAT") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MaximumLatitude", ui.GetDouble("MAXLAT")), Pvl::Replace );
  }

  if(ui.WasEntered("MINLON") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MinimumLongitude", ui.GetDouble("MINLON")), Pvl::Replace );
  }

  if(ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.AddKeyword( PvlKeyword("MaximumLongitude", ui.GetDouble("MAXLON")), Pvl::Replace );
  }

  /**
   * If the user is changing from positive east to positive west, or vice-versa, the output minimum is really
   * the input maximum. However, the user mapping group must be left unaffected (an input minimum must be the
   * output minimum). To accomplish this, we swap the minimums/maximums in the output group ahead of time. This
   * causes the minimums and maximums to correlate to the output minimums and maximums. That way when we copy
   * the user mapping group into the output group a mimimum overrides a minimum and a maximum overrides a maximum.
   */
  bool sameDirection = true;
  if(userMappingGrp.HasKeyword("LongitudeDirection")) {
    if(((string)userMappingGrp["LongitudeDirection"]).compare(fromMappingGrp["LongitudeDirection"]) != 0) {
      sameDirection = false;
    }
  }

  // Since the out mapping group came from the from mapping group, which came from a valid cube,
  // we can assume both min/max lon exists if min longitude exists.
  if(!sameDirection && outMappingGrp.HasKeyword("MinimumLongitude")) {
    double minLon = outMappingGrp["MinimumLongitude"];
    double maxLon = outMappingGrp["MaximumLongitude"];

    outMappingGrp["MaximumLongitude"] = minLon;
    outMappingGrp["MinimumLongitude"] = maxLon;
  }

  if(ui.GetString("PIXRES").compare("FROM") == 0 && !ui.GetBoolean("MATCHMAP")) {
    // Resolution will be in fromMappingGrp and outMappingGrp at this time
    //   delete from user mapping grp
    if(userMappingGrp.HasKeyword("Scale")) {
      userMappingGrp.DeleteKeyword("Scale");
    }

    if(userMappingGrp.HasKeyword("PixelResolution")) {
      userMappingGrp.DeleteKeyword("PixelResolution");
    }
  }
  else if(ui.GetString("PIXRES").compare("MAP") == 0 || ui.GetBoolean("MATCHMAP")) {
    // Resolution will be in userMappingGrp - delete all others
    if(outMappingGrp.HasKeyword("Scale")) {
      outMappingGrp.DeleteKeyword("Scale");
    }

    if(outMappingGrp.HasKeyword("PixelResolution")) {
      outMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(fromMappingGrp.HasKeyword("Scale")); {
      fromMappingGrp.DeleteKeyword("Scale");
    }

    if(fromMappingGrp.HasKeyword("PixelResolution")) {
      fromMappingGrp.DeleteKeyword("PixelResolution");
    }
  }
  else if(ui.GetString("PIXRES").compare("MPP") == 0) {
    // Resolution specified - delete all and add to outMappingGrp
    if(outMappingGrp.HasKeyword("Scale")) {
      outMappingGrp.DeleteKeyword("Scale");
    }

    if(outMappingGrp.HasKeyword("PixelResolution")) {
      outMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(fromMappingGrp.HasKeyword("Scale")) {
      fromMappingGrp.DeleteKeyword("Scale");
    }

    if(fromMappingGrp.HasKeyword("PixelResolution")) {
      fromMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(userMappingGrp.HasKeyword("Scale")) {
      userMappingGrp.DeleteKeyword("Scale");
    }

    if(userMappingGrp.HasKeyword("PixelResolution")) {
      userMappingGrp.DeleteKeyword("PixelResolution");
    }

    outMappingGrp.AddKeyword(PvlKeyword("PixelResolution", ui.GetDouble("RESOLUTION"), "meters/pixel"), Pvl::Replace);
  }
  else if(ui.GetString("PIXRES").compare("PPD") == 0) {
    // Resolution specified - delete all and add to outMappingGrp
    if(outMappingGrp.HasKeyword("Scale")) {
      outMappingGrp.DeleteKeyword("Scale");
    }

    if(outMappingGrp.HasKeyword("PixelResolution")) {
      outMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(fromMappingGrp.HasKeyword("Scale")) {
      fromMappingGrp.DeleteKeyword("Scale");
    }

    if(fromMappingGrp.HasKeyword("PixelResolution")) {
      fromMappingGrp.DeleteKeyword("PixelResolution");
    }

    if(userMappingGrp.HasKeyword("Scale")) {
      userMappingGrp.DeleteKeyword("Scale");
    }

    if(userMappingGrp.HasKeyword("PixelResolution")) {
      userMappingGrp.DeleteKeyword("PixelResolution");
    }

    outMappingGrp.AddKeyword(PvlKeyword("Scale", ui.GetDouble("RESOLUTION"), "pixels/degree"), Pvl::Replace);
  }

  // Rotation will NOT Propagate
  if(outMappingGrp.HasKeyword("Rotation")) {
    outMappingGrp.DeleteKeyword("Rotation");
  }


  /**
   * The user specified map template file overrides what ever is in the
   * cube's mapping group.
   */
  for(int keyword = 0; keyword < userMappingGrp.Keywords(); keyword ++) {
    outMappingGrp.AddKeyword(userMappingGrp[keyword], Pvl::Replace);
  }

  /**
   * Now, we have to deal with unit conversions. We convert only if the following are true:
   *   1) We used values from the input cube
   *   2) The values are longitudes or latitudes
   *   3) The map file or user-specified information uses a different measurement system than
   *        the input cube for said values.
   *
   * The data is corrected for:
   *   1) Positive east/positive west
   *   2) Longitude domain
   *   3) planetographic/planetocentric.
   */

  // First, the longitude direction
  if(!sameDirection) {
    PvlGroup longitudes = inproj->MappingLongitudes();

    for(int index = 0; index < longitudes.Keywords(); index ++) {
      if(!userMappingGrp.HasKeyword(longitudes[index].Name())) {
        // use the from domain because that's where our values are coming from
        if(((string)userMappingGrp["LongitudeDirection"]).compare("PositiveEast") == 0) {
          outMappingGrp[longitudes[index].Name()] =
            Projection::ToPositiveEast(outMappingGrp[longitudes[index].Name()], outMappingGrp["LongitudeDomain"]);
        }
        else {
          outMappingGrp[longitudes[index].Name()] =
            Projection::ToPositiveWest(outMappingGrp[longitudes[index].Name()], outMappingGrp["LongitudeDomain"]);
        }
      }
    }
  }

  // The minimum/maximum longitudes should be in order now. However, if the user entered a
  // maximum that was lower than the minimum, or a minimum that was higher than the maximum this
  // may still fail. Let it throw an error when we instantiate the projection.

  // Second, longitude domain
  if(userMappingGrp.HasKeyword("LongitudeDomain")) { // user set a new domain?
    if((int)userMappingGrp["LongitudeDomain"] != (int)fromMappingGrp["LongitudeDomain"]) { // new domain different?

      PvlGroup longitudes = inproj->MappingLongitudes();

      for(int index = 0; index < longitudes.Keywords(); index ++) {
        if(!userMappingGrp.HasKeyword(longitudes[index].Name())) {
          if((int)userMappingGrp["LongitudeDomain"] == 180) {
            outMappingGrp[longitudes[index].Name()] = Projection::To180Domain(outMappingGrp[longitudes[index].Name()]);
          }
          else {
            outMappingGrp[longitudes[index].Name()] = Projection::To360Domain(outMappingGrp[longitudes[index].Name()]);
          }
        }
      }

    }
  }

  // Third, planetographic/planetocentric
  if(userMappingGrp.HasKeyword("LatitudeType")) { // user set a new domain?
    if(((string)userMappingGrp["LatitudeType"]).compare(fromMappingGrp["LatitudeType"]) != 0) { // new lat type different?

      PvlGroup latitudes = inproj->MappingLatitudes();

      for(int index = 0; index < latitudes.Keywords(); index ++) {
        if(!userMappingGrp.HasKeyword(latitudes[index].Name())) {
          if(((string)userMappingGrp["LatitudeType"]).compare("Planetographic") == 0) {
            outMappingGrp[latitudes[index].Name()] = Projection::ToPlanetographic(
                                                      (double)fromMappingGrp[latitudes[index].Name()],
                                                      (double)fromMappingGrp["EquatorialRadius"],
                                                      (double)fromMappingGrp["PolarRadius"]);
          }
          else {
            outMappingGrp[latitudes[index].Name()] = Projection::ToPlanetocentric(
                                                      (double)fromMappingGrp[latitudes[index].Name()],
                                                      (double)fromMappingGrp["EquatorialRadius"],
                                                      (double)fromMappingGrp["PolarRadius"]);
          }
        }
      }

    }
  }

  // If MinLon/MaxLon out of order, we weren't able to calculate the correct values
  if((double)outMappingGrp["MinimumLongitude"] >= (double)outMappingGrp["MaximumLongitude"]) {
    if(!ui.WasEntered("MINLON") || !ui.WasEntered("MAXLON")) {
      string msg = "Unable to determine the correct [MinimumLongitude,MaximumLongitude].";
      msg += " Please specify these values in the [MINLON,MAXLON] parameters";
      throw iException::Message(iException::Pvl,msg,_FILEINFO_);
    }
  }

  int samples,lines;
  Pvl mapData;
  // Copy to preserve cube labels so we can match cube size
  if (userPvl.HasObject("IsisCube")) {
    mapData = userPvl;
    mapData.FindObject("IsisCube").DeleteGroup("Mapping");
    mapData.FindObject("IsisCube").AddGroup(outMappingGrp);
  }
  else {
    mapData.AddGroup(outMappingGrp);
  }

  // *NOTE: The UpperLeftX,UpperLeftY keywords will not be used in the CreateForCube
  //   method, and they will instead be recalculated. This is correct.
  Projection *outproj = ProjectionFactory::CreateForCube(mapData,samples,lines,
                                                         ui.GetBoolean("MATCHMAP"));

  // Set up the transform object which will simply map
  // output line/samps -> output lat/lons -> input line/samps
  Transform *transform = new map2map (icube->Samples(),
                                       icube->Lines(),
                                       icube->Projection(),
                                       samples,
                                       lines,
                                       outproj,
                                       ui.GetBoolean("TRIM"));

  // Allocate the output cube and add the mapping labels
  Cube *ocube = p.SetOutputCube ("TO", transform->OutputSamples(),
                                            transform->OutputLines(),
                                            icube->Bands());

  PvlGroup cleanOutGrp = outproj->Mapping();

  // ProjectionFactory::CreateForCube updated mapData to have the correct
  //   upperleftcornerx, upperleftcornery, scale and resolution. Use these
  //   updated numbers.
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["UpperLeftCornerX"], Pvl::Replace);
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["UpperLeftCornerY"], Pvl::Replace);
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["Scale"], Pvl::Replace);
  cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["PixelResolution"], Pvl::Replace);

  ocube->PutGroup(cleanOutGrp);

  // Set up the interpolator
  Interpolator *interp;
  if (ui.GetString("INTERP") == "NEARESTNEIGHBOR") {
    interp = new Interpolator(Interpolator::NearestNeighborType);
  }
  else if (ui.GetString("INTERP") == "BILINEAR") {
    interp = new Interpolator(Interpolator::BiLinearType);
  }
  else if (ui.GetString("INTERP") == "CUBICCONVOLUTION") {
    interp = new Interpolator(Interpolator::CubicConvolutionType);
  }
  else {
    string msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]";
    throw iException::Message(iException::Programmer,msg,_FILEINFO_);
  }

  // Warp the cube
  p.StartProcess(*transform, *interp);
  p.EndProcess();

  Application::Log(cleanOutGrp);

  // Cleanup
  delete transform;
  delete interp;
}