Esempio n. 1
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->group("Mapping");
  TProjection *inproj = (TProjection *) 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", toString(ui.GetDouble("MINLAT"))), Pvl::Replace);
  }

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

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

  if(ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) {
    userMappingGrp.addKeyword(PvlKeyword("MaximumLongitude", toString(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(((QString)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"] = toString(minLon);
    outMappingGrp["MinimumLongitude"] = toString(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", toString(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", toString(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(((QString)userMappingGrp["LongitudeDirection"]).compare("PositiveEast") == 0) {
          outMappingGrp[longitudes[index].name()] = toString(
            TProjection::ToPositiveEast(outMappingGrp[longitudes[index].name()],
                                        outMappingGrp["LongitudeDomain"]));
        }
        else {
          outMappingGrp[longitudes[index].name()] = toString(
              TProjection::ToPositiveWest(outMappingGrp[longitudes[index].name()],
                                          outMappingGrp["LongitudeDomain"]));
        }
      }
    }
  }

  // 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()] = toString(
                TProjection::To180Domain(outMappingGrp[longitudes[index].name()]));
          }
          else {
            outMappingGrp[longitudes[index].name()] = toString(
                TProjection::To360Domain(outMappingGrp[longitudes[index].name()]));
          }
        }
      }

    }
  }

  // Third, planetographic/planetocentric
  if(userMappingGrp.hasKeyword("LatitudeType")) { // user set a new domain?
    if(((QString)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(((QString)userMappingGrp["LatitudeType"]).compare("Planetographic") == 0) {
            outMappingGrp[latitudes[index].name()] = toString(TProjection::ToPlanetographic(
                  (double)fromMappingGrp[latitudes[index].name()],
                  (double)fromMappingGrp["EquatorialRadius"],
                  (double)fromMappingGrp["PolarRadius"]));
          }
          else {
            outMappingGrp[latitudes[index].name()] = toString(TProjection::ToPlanetocentric(
                  (double)fromMappingGrp[latitudes[index].name()],
                  (double)fromMappingGrp["EquatorialRadius"],
                  (double)fromMappingGrp["PolarRadius"]));
          }
        }
      }

    }
  }

  // Try a couple equivalent longitudes to fix the ordering of min,max for border cases
  if ((double)outMappingGrp["MinimumLongitude"] >=
      (double)outMappingGrp["MaximumLongitude"]) {

    if ((QString)outMappingGrp["MinimumLongitude"] == "180.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 180)
      outMappingGrp["MinimumLongitude"] = "-180";

    if ((QString)outMappingGrp["MaximumLongitude"] == "-180.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 180)
      outMappingGrp["MaximumLongitude"] = "180";

    if ((QString)outMappingGrp["MinimumLongitude"] == "360.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 360)
      outMappingGrp["MinimumLongitude"] = "0";

    if ((QString)outMappingGrp["MaximumLongitude"] == "0.0" &&
        (int)userMappingGrp["LongitudeDomain"] == 360)
      outMappingGrp["MaximumLongitude"] = "360";
  }

  // 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")) {
      QString msg = "Unable to determine the correct [MinimumLongitude,MaximumLongitude].";
      msg += " Please specify these values in the [MINLON,MAXLON] parameters";
      throw IException(IException::Unknown, 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.
  TProjection *outproj = (TProjection *) 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->sampleCount(),
                                     icube->lineCount(),
                                     (TProjection *) 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->bandCount());

  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 {
    QString msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]";
    throw IException(IException::Programmer, msg, _FILEINFO_);
  }

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

  Application::Log(cleanOutGrp);

  // Cleanup
  delete transform;
  delete interp;
}
Esempio n. 2
0
  /**
   * Set the output cube to specified file name and specified input images
   * and output attributes and lat,lons
   */
  Isis::Cube *ProcessMapMosaic::SetOutputCube(FileList &propagationCubes,
      double slat, double elat, double slon, double elon,
      CubeAttributeOutput &oAtt, const QString &mosaicFile) {
    if (propagationCubes.size() < 1) {
      QString msg = "The list does not contain any data";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    int samples, lines, bands = 0;
    Pvl label;
    label.read(propagationCubes[0].toString());
    PvlGroup mGroup = label.findGroup("Mapping", Pvl::Traverse);
    mGroup.addKeyword(PvlKeyword("MinimumLatitude", toString(slat)), Pvl::Replace);
    mGroup.addKeyword(PvlKeyword("MaximumLatitude", toString(elat)), Pvl::Replace);
    mGroup.addKeyword(PvlKeyword("MinimumLongitude", toString(slon)), Pvl::Replace);
    mGroup.addKeyword(PvlKeyword("MaximumLongitude", toString(elon)), Pvl::Replace);

    if (mGroup.hasKeyword("UpperLeftCornerX"))
      mGroup.deleteKeyword("UpperLeftCornerX");

    if (mGroup.hasKeyword("UpperLeftCornerY"))
      mGroup.deleteKeyword("UpperLeftCornerY");

    Pvl mapPvl;
    mapPvl += mGroup;

    // Use CreateForCube because our range differs from any of the cubes (manually specified)
    Projection *proj = Isis::ProjectionFactory::CreateForCube(mapPvl, samples, lines, false);

    double xmin, xmax, ymin, ymax;
    proj->XYRange(xmin, xmax, ymin, ymax);

    // The xmin/ymax should be rounded for the labels
    xmin = mapPvl.findGroup("Mapping")["UpperLeftCornerX"];
    ymax = mapPvl.findGroup("Mapping")["UpperLeftCornerY"];

    for (int i = 0; i < propagationCubes.size(); i++) {
      Cube cube;
      cube.open(propagationCubes[i].toString());
      bands = max(cube.bandCount(), bands);

      // See if the cube has a projection and make sure it matches
      // previous input cubes
      Projection *projNew =
          Isis::ProjectionFactory::CreateFromCube(*(cube.label()));

      if (proj == NULL) {
      }
      else if (*proj != *projNew) {
        QString msg = "Mapping groups do not match between cube [" + propagationCubes[i].toString() +
                     "] and [" + propagationCubes[0].toString() + "]";
        throw IException(IException::User, msg, _FILEINFO_);
      }

      if (proj) delete proj;
      proj = projNew;
    }

    if (proj) delete proj;

    return SetOutputCube(propagationCubes[0].toString(), xmin, xmax, ymin, ymax,
                         slat, elat, slon, elon, bands, oAtt, mosaicFile);
  }