USGS

Isis 3.0 Application Source Code Reference

Home

cam2map.cpp

Go to the documentation of this file.
00001 #define GUIHELPERS
00002 
00003 #include "Isis.h"
00004 #include "Camera.h"
00005 #include "ProjectionFactory.h"
00006 #include "ProcessRubberSheet.h"
00007 #include "iException.h"
00008 #include "cam2map.h"
00009 
00010 using namespace std;
00011 using namespace Isis;
00012 
00013 void PrintMap ();
00014 void LoadMapRes ();
00015 void LoadCameraRes ();
00016 void LoadMapRange ();
00017 void LoadCameraRange ();
00018 
00019 map <string,void*> GuiHelpers(){
00020   map <string,void*> helper;
00021   helper ["PrintMap"] = (void*) PrintMap;
00022   helper ["LoadMapRes"] = (void*) LoadMapRes;
00023   helper ["LoadCameraRes"] = (void*) LoadCameraRes;
00024   helper ["LoadMapRange"] = (void*) LoadMapRange;
00025   helper ["LoadCameraRange"] = (void*) LoadCameraRange;
00026   return helper;
00027 }
00028 
00029 
00030 // Global variables
00031 void BandChange (const int band);
00032 Cube *icube;
00033 Camera *incam;
00034 
00035 void IsisMain() {
00036   // We will be warping a cube
00037   ProcessRubberSheet p;
00038 
00039   // Get the map projection file provided by the user
00040   UserInterface &ui = Application::GetUserInterface();
00041   Pvl userMap;
00042   userMap.Read(ui.GetFilename("MAP"));
00043   PvlGroup &userGrp = userMap.FindGroup("Mapping",Pvl::Traverse);
00044 
00045   // Open the input cube and get the camera
00046   icube = p.SetInputCube ("FROM");
00047   incam = icube->Camera();
00048 
00049   // Make sure it is not the sky
00050   if (incam->IsSky()) {
00051     string msg = "The image [" + ui.GetFilename("FROM") +
00052                  "] is targeting the sky, use skymap instead.";
00053     throw Isis::iException::Message(Isis::iException::User,msg,_FILEINFO_);
00054   }
00055 
00056   // Get the mapping grop
00057   Pvl camMap;
00058   incam->BasicMapping(camMap);
00059   PvlGroup &camGrp = camMap.FindGroup("Mapping");
00060 
00061 
00062   // Make the target info match the user mapfile
00063   double minlat,maxlat,minlon,maxlon;
00064   incam->GroundRange(minlat,maxlat,minlon,maxlon,userMap);
00065   camGrp.AddKeyword(PvlKeyword("MinimumLatitude",minlat),Pvl::Replace);
00066   camGrp.AddKeyword(PvlKeyword("MaximumLatitude",maxlat),Pvl::Replace);
00067   camGrp.AddKeyword(PvlKeyword("MinimumLongitude",minlon),Pvl::Replace);
00068   camGrp.AddKeyword(PvlKeyword("MaximumLongitude",maxlon),Pvl::Replace);
00069 
00070 
00071   // We want to delete the keywords we just added if the user wants the range
00072   // out of the mapfile, otherwise they will replace any keywords not in the
00073   // mapfile
00074   if (ui.GetString("DEFAULTRANGE") == "MAP" || ui.GetBoolean("MATCHMAP")) {
00075     camGrp.DeleteKeyword("MinimumLatitude");
00076     camGrp.DeleteKeyword("MaximumLatitude");
00077     camGrp.DeleteKeyword("MinimumLongitude");
00078     camGrp.DeleteKeyword("MaximumLongitude");
00079   }
00080   // Otherwise, remove the keywords from the map file so the camera keywords
00081   // will be propogated correctly
00082   else {
00083     while (userGrp.HasKeyword("MinimumLatitude")) {
00084       userGrp.DeleteKeyword("MinimumLatitude");
00085     }
00086     while (userGrp.HasKeyword("MinimumLongitude")) {
00087       userGrp.DeleteKeyword("MinimumLongitude");
00088     }
00089     while (userGrp.HasKeyword("MaximumLatitude")) {
00090       userGrp.DeleteKeyword("MaximumLatitude");
00091     }
00092     while (userGrp.HasKeyword("MaximumLongitude")) {
00093       userGrp.DeleteKeyword("MaximumLongitude");
00094     }
00095   }
00096 
00097   // If the user decided to enter a ground range then override
00098   if (ui.WasEntered("MINLON") && !ui.GetBoolean("MATCHMAP")) {
00099     userGrp.AddKeyword(PvlKeyword("MinimumLongitude",
00100                                       ui.GetDouble("MINLON")),Pvl::Replace);
00101   }
00102 
00103   if (ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) {
00104     userGrp.AddKeyword(PvlKeyword("MaximumLongitude",
00105                                       ui.GetDouble("MAXLON")),Pvl::Replace);
00106   }
00107 
00108   if (ui.WasEntered("MINLAT") && !ui.GetBoolean("MATCHMAP")) {
00109     userGrp.AddKeyword(PvlKeyword("MinimumLatitude",
00110                                       ui.GetDouble("MINLAT")),Pvl::Replace);
00111   }
00112 
00113   if (ui.WasEntered("MAXLAT") && !ui.GetBoolean("MATCHMAP")) {
00114     userGrp.AddKeyword(PvlKeyword("MaximumLatitude",
00115                                       ui.GetDouble("MAXLAT")),Pvl::Replace);
00116   }
00117 
00118   // If they want the res. from the mapfile, delete it from the camera so
00119   // nothing gets overriden
00120   if (ui.GetString("PIXRES") == "MAP" || ui.GetBoolean("MATCHMAP")) {
00121     camGrp.DeleteKeyword("PixelResolution");
00122   }
00123   // Otherwise, delete any resolution keywords from the mapfile so the camera
00124   // info is propogated over
00125   else if (ui.GetString("PIXRES") == "CAMERA") {
00126     if (userGrp.HasKeyword("Scale")) {
00127       userGrp.DeleteKeyword("Scale");
00128     }
00129     if (userGrp.HasKeyword("PixelResolution")) {
00130       userGrp.DeleteKeyword("PixelResolution");
00131     }
00132   }
00133 
00134   // Copy any defaults that are not in the user map from the camera map file
00135   for (int k=0; k<camGrp.Keywords(); k++) {
00136     if (!userGrp.HasKeyword(camGrp[k].Name())) {
00137       userGrp += camGrp[k];
00138     }
00139   }
00140 
00141   // If the user decided to enter a resolution then override
00142   if (ui.GetString("PIXRES") == "MPP" && !ui.GetBoolean("MATCHMAP")) {
00143     userGrp.AddKeyword(PvlKeyword("PixelResolution",
00144                                       ui.GetDouble("RESOLUTION")),
00145                                       Pvl::Replace);
00146     if (userGrp.HasKeyword("Scale")) {
00147       userGrp.DeleteKeyword("Scale");
00148     }
00149   }
00150   else if (ui.GetString("PIXRES") == "PPD" && !ui.GetBoolean("MATCHMAP")) {
00151     userGrp.AddKeyword(PvlKeyword("Scale",
00152                                       ui.GetDouble("RESOLUTION")),
00153                                       Pvl::Replace);
00154     if (userGrp.HasKeyword("PixelResolution")) {
00155       userGrp.DeleteKeyword("PixelResolution");
00156     }
00157   }
00158 
00159   // See if the user want us to handle the longitude seam
00160   if ((ui.GetString("DEFAULTRANGE") == "CAMERA" || ui.GetString("DEFAULTRANGE") == "MINIMIZE") && 
00161       !ui.GetBoolean("MATCHMAP")) {
00162     if (incam->IntersectsLongitudeDomain(userMap)) {
00163       if (ui.GetString("LONSEAM") == "AUTO") {
00164         if ((int) userGrp["LongitudeDomain"] == 360) {
00165           userGrp.AddKeyword(PvlKeyword("LongitudeDomain",180),
00166                                             Pvl::Replace);
00167           if (incam->IntersectsLongitudeDomain(userMap)) {
00168             // Its looks like a global image so switch back to the
00169             // users preference
00170             userGrp.AddKeyword(PvlKeyword("LongitudeDomain",360),
00171                                             Pvl::Replace);
00172           }
00173         }
00174         else {
00175           userGrp.AddKeyword(PvlKeyword("LongitudeDomain",360),
00176                                             Pvl::Replace);
00177           if (incam->IntersectsLongitudeDomain(userMap)) {
00178             // Its looks like a global image so switch back to the
00179             // users preference
00180             userGrp.AddKeyword(PvlKeyword("LongitudeDomain",180),
00181                                               Pvl::Replace);
00182           }
00183         }
00184         // Make the target info match the new longitude domain
00185         double minlat,maxlat,minlon,maxlon;
00186         incam->GroundRange(minlat,maxlat,minlon,maxlon,userMap);
00187         if( !ui.WasEntered("MINLAT") ) {
00188           userGrp.AddKeyword(PvlKeyword("MinimumLatitude",minlat),Pvl::Replace);
00189         }
00190         if( !ui.WasEntered("MAXLAT") ) {
00191           userGrp.AddKeyword(PvlKeyword("MaximumLatitude",maxlat),Pvl::Replace);
00192         }
00193         if( !ui.WasEntered("MINLON") ) {
00194           userGrp.AddKeyword(PvlKeyword("MinimumLongitude",minlon),Pvl::Replace);
00195         }
00196         if( !ui.WasEntered("MAXLON") ) {
00197           userGrp.AddKeyword(PvlKeyword("MaximumLongitude",maxlon),Pvl::Replace);
00198         }
00199       }
00200 
00201       else if (ui.GetString("LONSEAM") == "ERROR") {
00202         string msg = "The image [" + ui.GetFilename("FROM") + "] crosses the " +
00203                                                               "longitude seam";
00204         throw Isis::iException::Message(Isis::iException::User,msg,_FILEINFO_);
00205       }
00206     }
00207   }
00208 
00209   // Use the updated label to create the output projection
00210   int samples,lines;
00211   Projection *outmap;
00212   bool trim;
00213 
00214   // Determine the image size
00215   if (ui.GetString("DEFAULTRANGE") == "MINIMIZE" && !ui.GetBoolean("MATCHMAP")) {
00216     outmap = ProjectionFactory::CreateForCube(userMap,samples,lines,*incam);
00217     trim = false;
00218   }
00219   else if (ui.GetString("DEFAULTRANGE") == "CAMERA" && !ui.GetBoolean("MATCHMAP")) {
00220     outmap = ProjectionFactory::CreateForCube(userMap,samples,lines,false);
00221     trim = ui.GetBoolean("TRIM");
00222   }
00223   else { // DEFAULTRANGE = MAP
00224     outmap = ProjectionFactory::CreateForCube(userMap,samples,lines,
00225                                               ui.GetBoolean("MATCHMAP"));
00226     trim = ui.GetBoolean("TRIM");
00227   }
00228 
00229   int tileStart, tileEnd;
00230   incam->GetGeometricTilingHint(tileStart, tileEnd);
00231   p.SetTiling(tileStart, tileEnd);
00232 
00233   // Output the mapping group used to the Gui session log
00234   Application::GuiLog(userMap);
00235 
00236   // Set up the transform object which will simply map
00237   // output line/samps -> output lat/lons -> input line/samps
00238   Transform *transform = new cam2map (icube->Samples(),
00239                                           icube->Lines(),
00240                                           incam,
00241                                           samples,
00242                                           lines,
00243                                           outmap,
00244                                           trim);
00245 
00246   // Allocate the output cube and add the mapping labels
00247   Cube *ocube = p.SetOutputCube ("TO", transform->OutputSamples(),
00248                                             transform->OutputLines(),
00249                                             icube->Bands());
00250   ocube->PutGroup(userGrp);
00251 
00252   // Set up the interpolator
00253   Interpolator *interp = NULL;
00254   if (ui.GetString("INTERP") == "NEARESTNEIGHBOR") {
00255     interp = new Interpolator(Interpolator::NearestNeighborType);
00256   }
00257   else if (ui.GetString("INTERP") == "BILINEAR") {
00258     interp = new Interpolator(Interpolator::BiLinearType);
00259   }
00260   else if (ui.GetString("INTERP") == "CUBICCONVOLUTION") {
00261     interp = new Interpolator(Interpolator::CubicConvolutionType);
00262   }
00263 
00264   // See if we need to deal with band dependent camera models
00265   if (!incam->IsBandIndependent()) {
00266     p.BandChange(BandChange);
00267   }
00268 
00269   //  See if center of input image projects.  If it does, force tile
00270   //  containing this center to be processed in ProcessRubberSheet.
00271   double centerSamp = icube->Samples () / 2.;
00272   double centerLine = icube->Lines () / 2.;
00273   if (incam->SetImage(centerSamp,centerLine)) {
00274     if (outmap->SetUniversalGround(incam->UniversalLatitude(),
00275                                 incam->UniversalLongitude())) {
00276       p.ForceTile (outmap->WorldX(),outmap->WorldY ());
00277     }
00278   }
00279   // Create an alpha cube group for the output cube
00280   if (!ocube->HasGroup("AlphaCube")) {
00281     PvlGroup alpha("AlphaCube");
00282     alpha += PvlKeyword("AlphaSamples",icube->Samples());
00283     alpha += PvlKeyword("AlphaLines",icube->Lines());
00284     alpha += PvlKeyword("AlphaStartingSample",0.5);
00285     alpha += PvlKeyword("AlphaStartingLine",0.5);
00286     alpha += PvlKeyword("AlphaEndingSample",icube->Samples()+0.5);
00287     alpha += PvlKeyword("AlphaEndingLine",icube->Lines()+0.5);
00288     alpha += PvlKeyword("BetaSamples",icube->Samples());
00289     alpha += PvlKeyword("BetaLines",icube->Lines());
00290     ocube->PutGroup(alpha);
00291   }
00292 
00293   // Warp the cube
00294   p.StartProcess(*transform, *interp);
00295   p.EndProcess();
00296 
00297   // add mapping to print.prt
00298   PvlGroup mapping = outmap->Mapping(); 
00299   Application::Log(mapping); 
00300 
00301   // Cleanup
00302   delete outmap;
00303   delete transform;
00304   delete interp;
00305 }
00306 
00307 // Transform object constructor
00308 cam2map::cam2map (const int inputSamples, const int inputLines,
00309                   Camera *incam, const int outputSamples,
00310                   const int outputLines, Projection *outmap,
00311                   bool trim) {
00312   p_inputSamples = inputSamples;
00313   p_inputLines = inputLines;
00314   p_incam = incam;
00315 
00316   p_outputSamples = outputSamples;
00317   p_outputLines = outputLines;
00318   p_outmap = outmap;
00319 
00320   p_trim = trim;
00321 }
00322 
00323 // Transform method mapping output line/samps to lat/lons to input line/samps
00324 bool cam2map::Xform (double &inSample, double &inLine,
00325                          const double outSample, const double outLine) {
00326   // See if the output image coordinate converts to lat/lon
00327   if (!p_outmap->SetWorld(outSample,outLine)) return false;
00328 
00329   // See if we should trim
00330   if ((p_trim) && (p_outmap->HasGroundRange())) {
00331     if (p_outmap->Latitude() < p_outmap->MinimumLatitude()) return false;
00332     if (p_outmap->Latitude() > p_outmap->MaximumLatitude()) return false;
00333     if (p_outmap->Longitude() < p_outmap->MinimumLongitude()) return false;
00334     if (p_outmap->Longitude() > p_outmap->MaximumLongitude()) return false;
00335   }
00336 
00337   // Get the universal lat/lon and see if it can be converted to input line/samp
00338   double lat = p_outmap->UniversalLatitude();
00339   double lon = p_outmap->UniversalLongitude();
00340 
00341   if (!p_incam->SetUniversalGround(lat,lon)) return false;
00342 
00343   // Make sure the point is inside the input image
00344   if (p_incam->Sample() < 0.5) return false;
00345   if (p_incam->Line() < 0.5) return false;
00346   if (p_incam->Sample() > p_inputSamples + 0.5) return false;
00347   if (p_incam->Line() > p_inputLines + 0.5) return false;
00348 
00349   // Everything is good
00350   inSample = p_incam->Sample();
00351   inLine = p_incam->Line();
00352 
00353   return true;
00354 }
00355 
00356 int cam2map::OutputSamples () const {
00357   return p_outputSamples;
00358 }
00359 
00360 int cam2map::OutputLines () const {
00361   return p_outputLines;
00362 }
00363 
00364 void BandChange (const int band) {
00365   incam->SetBand(band);
00366 }
00367 
00368 // Helper function to print out mapfile to session log
00369 void PrintMap() {
00370   UserInterface &ui = Application::GetUserInterface();
00371 
00372   // Get mapping group from map file
00373   Pvl userMap;
00374   userMap.Read(ui.GetFilename("MAP"));
00375   PvlGroup &userGrp = userMap.FindGroup("Mapping",Pvl::Traverse);
00376 
00377   //Write map file out to the log
00378   Isis::Application::GuiLog(userGrp);
00379 }
00380 
00381 // Helper function to get mapping resolution.
00382 void LoadMapRes () {
00383   UserInterface &ui = Application::GetUserInterface();
00384 
00385   // Get mapping group from map file
00386   Pvl userMap;
00387   userMap.Read(ui.GetFilename("MAP"));
00388   PvlGroup &userGrp = userMap.FindGroup("Mapping",Pvl::Traverse);
00389 
00390   // Set resolution
00391   if (userGrp.HasKeyword("Scale")) {
00392     ui.Clear("RESOLUTION");
00393     ui.PutDouble("RESOLUTION",userGrp["Scale"]);
00394     ui.Clear("PIXRES");
00395     ui.PutAsString("PIXRES","PPD");
00396   }
00397   else if (userGrp.HasKeyword("PixelResolution")) {
00398     ui.Clear("RESOLUTION");
00399     ui.PutDouble("RESOLUTION",userGrp["PixelResolution"]);
00400     ui.Clear("PIXRES");
00401     ui.PutAsString("PIXRES","MPP");
00402   }
00403   else {
00404     string msg = "No resolution value found in [" + ui.GetFilename("MAP") + "]";
00405     throw Isis::iException::Message(Isis::iException::User,msg,_FILEINFO_);
00406   }
00407 }
00408 
00409 //Helper function to get camera resolution.
00410 void LoadCameraRes () {
00411   UserInterface &ui = Application::GetUserInterface();
00412   string file = ui.GetFilename("FROM");
00413 
00414   // Open the input cube, get the camera object, and the cam map projection
00415   Cube c;
00416   c.Open(file);
00417   Camera *cam = c.Camera();
00418   Pvl camMap;
00419   cam->BasicMapping(camMap);
00420   PvlGroup &camGrp = camMap.FindGroup("Mapping");
00421 
00422   ui.Clear("RESOLUTION");
00423   ui.PutDouble("RESOLUTION",camGrp["PixelResolution"]);
00424 
00425   ui.Clear("PIXRES");
00426   ui.PutAsString("PIXRES","MPP");
00427 }
00428 
00429 //Helper function to get ground range from map file.
00430 void LoadMapRange() {
00431   UserInterface &ui = Application::GetUserInterface();
00432 
00433   // Get map file
00434   Pvl userMap;
00435   userMap.Read(ui.GetFilename("MAP"));
00436   PvlGroup &userGrp = userMap.FindGroup("Mapping",Pvl::Traverse);
00437 
00438   // Set ground range keywords that are found in mapfile
00439   int count = 0;
00440   ui.Clear("MINLAT");
00441   ui.Clear("MAXLAT");
00442   ui.Clear("MINLON");
00443   ui.Clear("MAXLON");
00444   if (userGrp.HasKeyword("MinimumLatitude")) {
00445     ui.PutDouble("MINLAT",userGrp["MinimumLatitude"]);
00446     count++;
00447   }
00448   if (userGrp.HasKeyword("MaximumLatitude")) {
00449     ui.PutDouble("MAXLAT",userGrp["MaximumLatitude"]);
00450     count++;
00451   }
00452   if (userGrp.HasKeyword("MinimumLongitude")) {
00453     ui.PutDouble("MINLON",userGrp["MinimumLongitude"]);
00454     count++;
00455   }
00456   if (userGrp.HasKeyword("MaximumLongitude")) {
00457     ui.PutDouble("MAXLON",userGrp["MaximumLongitude"]);
00458     count++;
00459   }
00460 
00461   // Set default ground range param to map
00462   ui.Clear("DEFAULTRANGE");
00463   ui.PutAsString("DEFAULTRANGE","MAP");
00464 
00465   if (count < 4) {
00466     string msg = "One or more of the values for the ground range was not found";
00467     msg += " in [" + ui.GetFilename("MAP") + "]";
00468     throw Isis::iException::Message(Isis::iException::User,msg,_FILEINFO_);
00469   }
00470 }
00471 
00472 //Helper function to load camera range.
00473 void LoadCameraRange () {
00474   UserInterface &ui = Application::GetUserInterface();
00475   string file = ui.GetFilename("FROM");
00476 
00477   // Get the map projection file provided by the user
00478   Pvl userMap;
00479   userMap.Read(ui.GetFilename("MAP"));
00480 
00481   // Open the input cube, get the camera object, and the cam map projection
00482   Cube c;
00483   c.Open(file);
00484   Camera *cam = c.Camera();
00485 
00486   // Make the target info match the user mapfile
00487   double minlat,maxlat,minlon,maxlon;
00488   cam->GroundRange(minlat,maxlat,minlon,maxlon,userMap);
00489 
00490   // Set ground range parameters in UI
00491   ui.Clear("MINLAT");
00492   ui.PutDouble("MINLAT",minlat);
00493   ui.Clear("MAXLAT");
00494   ui.PutDouble("MAXLAT",maxlat);
00495   ui.Clear("MINLON");
00496   ui.PutDouble("MINLON",minlon);
00497   ui.Clear("MAXLON");
00498   ui.PutDouble("MAXLON",maxlon);
00499 
00500   // Set default ground range param to camera
00501   ui.Clear("DEFAULTRANGE");
00502   ui.PutAsString("DEFAULTRANGE","CAMERA");
00503 }
00504