PanoOperation.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00009 /*  This program is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU General Public
00011  *  License as published by the Free Software Foundation; either
00012  *  version 2 of the License, or (at your option) any later version.
00013  *
00014  *  This software is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  *  General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public
00020  *  License along with this software. If not, see
00021  *  <http://www.gnu.org/licenses/>.
00022  *
00023  */
00024 
00025 #include "hugin/PanoOperation.h"
00026 #include "hugin/config_defaults.h"
00027 #include "base_wx/PanoCommand.h"
00028 #include "base_wx/wxPanoCommand.h"
00029 #include "huginapp/ImageCache.h"
00030 #include "base_wx/MyProgressDialog.h"
00031 #include "base_wx/PTWXDlg.h"
00032 #include "algorithms/optimizer/ImageGraph.h"
00033 #include "algorithms/control_points/CleanCP.h"
00034 #include "celeste/Celeste.h"
00035 #include <exiv2/exif.hpp>
00036 #include <exiv2/image.hpp>
00037 #include "base_wx/LensTools.h"
00038 #include "base_wx/wxLensDB.h"
00039 #include "hugin/ResetDialog.h"
00040 #include "hugin/MainFrame.h"
00041 #include <vigra_ext/openmp_vigra.h>
00042 
00043 using namespace HuginBase;
00044 
00045 namespace PanoOperation
00046 {
00047 
00048 wxString PanoOperation::GetLabel()
00049 {
00050     return wxEmptyString;
00051 };
00052 
00053 bool PanoOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00054 {
00055     return true;
00056 };
00057 
00058 PanoCommand::PanoCommand* PanoOperation::GetCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00059 {
00060     //remember gui level, only used by some PanoOperation's
00061     m_guiLevel=guiLevel;
00062     if(IsEnabled(pano, images, m_guiLevel))
00063     {
00064         return GetInternalCommand(parent,pano,images);
00065     }
00066     else
00067     {
00068         return NULL;
00069     };
00070 };
00071 
00072 bool PanoSingleImageOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00073 {
00074     return images.size()==1;
00075 };
00076 
00077 bool PanoMultiImageOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00078 {
00079     return images.size()>0;
00080 };
00081 
00087 bool AddImageDialog(wxWindow* parent, std::vector<std::string>& files)
00088 {
00089     // get stored path
00090     wxConfigBase* config = wxConfigBase::Get();
00091     wxString path = config->Read(wxT("/actualPath"), wxT(""));
00092     wxFileDialog dlg(parent,_("Add images"),
00093                      path, wxT(""),
00094                      HUGIN_WX_FILE_IMG_FILTER,
00095                      wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST | wxFD_PREVIEW, wxDefaultPosition);
00096     dlg.SetDirectory(path);
00097 
00098     // remember the image extension
00099     wxString img_ext;
00100     if (config->HasEntry(wxT("lastImageType")))
00101     {
00102       img_ext = config->Read(wxT("lastImageType")).c_str();
00103     }
00104     if (img_ext == wxT("all images"))
00105       dlg.SetFilterIndex(0);
00106     else if (img_ext == wxT("jpg"))
00107       dlg.SetFilterIndex(1);
00108     else if (img_ext == wxT("tiff"))
00109       dlg.SetFilterIndex(2);
00110     else if (img_ext == wxT("png"))
00111       dlg.SetFilterIndex(3);
00112     else if (img_ext == wxT("hdr"))
00113       dlg.SetFilterIndex(4);
00114     else if (img_ext == wxT("exr"))
00115       dlg.SetFilterIndex(5);
00116     else if (img_ext == wxT("all files"))
00117       dlg.SetFilterIndex(6);
00118 
00119     // call the file dialog
00120     if (dlg.ShowModal() == wxID_OK)
00121     {
00122         // get the selections
00123         wxArrayString Pathnames;
00124         dlg.GetPaths(Pathnames);
00125 
00126         // remember path for later
00127 #ifdef __WXGTK__
00128         //workaround a bug in GTK, see https://bugzilla.redhat.com/show_bug.cgi?id=849692 and http://trac.wxwidgets.org/ticket/14525
00129         config->Write(wxT("/actualPath"), wxPathOnly(Pathnames[0]));
00130 #else
00131         config->Write(wxT("/actualPath"), dlg.GetDirectory());
00132 #endif
00133         // save the image extension
00134         switch (dlg.GetFilterIndex())
00135         {
00136             case 0: config->Write(wxT("lastImageType"), wxT("all images")); break;
00137             case 1: config->Write(wxT("lastImageType"), wxT("jpg")); break;
00138             case 2: config->Write(wxT("lastImageType"), wxT("tiff")); break;
00139             case 3: config->Write(wxT("lastImageType"), wxT("png")); break;
00140             case 4: config->Write(wxT("lastImageType"), wxT("hdr")); break;
00141             case 5: config->Write(wxT("lastImageType"), wxT("exr")); break;
00142             case 6: config->Write(wxT("lastImageType"), wxT("all files")); break;
00143         }
00144 
00145         //check for forbidden/non working chars
00146         wxArrayString invalidFiles;
00147         for(unsigned int i=0;i<Pathnames.GetCount(); i++)
00148         {
00149            if(containsInvalidCharacters(Pathnames[i]))
00150            {
00151                invalidFiles.Add(Pathnames[i]);
00152            };
00153         };
00154         if(invalidFiles.size()>0)
00155         {
00156             ShowFilenameWarning(parent, invalidFiles);
00157             return false;
00158         }
00159         for (unsigned int i=0; i<Pathnames.GetCount(); i++)
00160         {
00161             files.push_back((const char *)Pathnames[i].mb_str(HUGIN_CONV_FILENAME));
00162         };
00163         return true;
00164     };
00165     return false;
00166 };
00167 
00168 wxString AddImageOperation::GetLabel()
00169 {
00170     return _("Add individual images...");
00171 };
00172 
00173 PanoCommand::PanoCommand* AddImageOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00174 {
00175     std::vector<std::string> files;
00176     if(AddImageDialog(parent, files))
00177     {
00178         if(files.size()>0)
00179         {
00180             return new PanoCommand::wxAddImagesCmd(pano,files);
00181         };
00182     };
00183     return NULL;
00184 };
00185 
00186 WX_DECLARE_STRING_HASH_MAP(time_t, StringToPointerHash);
00187 WX_DECLARE_STRING_HASH_MAP(int, StringToFlagHash);
00188 
00189 time_t ReadExifTime(const char* filename)
00190 {
00191     Exiv2::Image::AutoPtr image;
00192     try
00193     {
00194         image = Exiv2::ImageFactory::open(filename);
00195     }
00196     catch(...)
00197     {
00198         return 0;
00199     }
00200     if (image.get() == 0)
00201     {
00202         return 0;
00203     }
00204 
00205     image->readMetadata();
00206     Exiv2::ExifData &exifData = image->exifData();
00207     if (exifData.empty())
00208     {
00209         return 0;
00210     }
00211 
00212     Exiv2::Exifdatum& tag = exifData["Exif.Image.DateTime"];
00213     const std::string date_time = tag.toString();
00214 
00215     // Remember the file and a shutter timestamp.
00216     struct tm when;
00217     memset(&when, 0, sizeof(when));
00218     when.tm_wday = -1;
00219 
00220     // parse into the tm_structure
00221     const int a = sscanf(date_time.c_str(), "%d:%d:%d %d:%d:%d",
00222             &when.tm_year, &when.tm_mon, &when.tm_mday,
00223             &when.tm_hour, &when.tm_min, &when.tm_sec);
00224 
00225     if (a == 6)
00226     {
00227         when.tm_isdst = -1;
00228         when.tm_mon -= 1;      // Adjust for unix zero-based months
00229         when.tm_year -= 1900;  // Adjust for year starting at 1900
00230     }
00231     else
00232     {
00233         // Not in EXIF format
00234         return 0;
00235     }
00236 
00237     time_t stamp;
00238     stamp = mktime(&when);
00239     if (stamp == (time_t)(-1))
00240         return 0;
00241 
00242     return stamp;
00243 }
00244 
00245 struct sortbytime
00246 {
00247     explicit sortbytime(map<string, time_t> & h) : m_time(h) {};
00248     bool operator()(const std::string & s1, const std::string & s2)
00249     {
00250         time_t t1 = m_time[s1];
00251         time_t t2 = m_time[s2];
00252         return t1 < t2;
00253     };
00254     map<string, time_t> & m_time;
00255 };
00256 
00257 wxString AddImagesSeriesOperation::GetLabel()
00258 {
00259     return _("Add time-series of images...");
00260 };
00261 
00262 PanoCommand::PanoCommand* AddImagesSeriesOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00263 {
00264     //load image if pano contains no images
00265     std::vector<std::string> files;
00266     if(pano.getNrOfImages()==0)
00267     {
00268         if(!AddImageDialog(parent,files))
00269         {
00270             return NULL;
00271         };
00272         //just in case
00273         if(files.size()==0)
00274         {
00275             return NULL;
00276         };
00277     }
00278     else
00279     {
00280         for(size_t i=0;i<pano.getNrOfImages();i++)
00281         {
00282             files.push_back(pano.getImage(i).getFilename());
00283         };
00284     };
00285 
00286     DEBUG_TRACE("seeking similarly timed images");
00287 
00288     // Collect potential image-mates.
00289     StringToPointerHash filenames;
00290     StringToFlagHash preloaded;
00291     for(size_t i=0;i<files.size();i++)
00292     {
00293         wxString file(files[i].c_str(), HUGIN_CONV_FILENAME);
00294         preloaded[file] = 1;
00295 
00296         // Glob for all files of same type in same directory.
00297         wxString path = ::wxPathOnly(file) + wxT("/*");
00298         file = ::wxFindFirstFile(path);
00299         while (!file.IsEmpty())
00300         {
00301             // Associated with a NULL dummy timestamp for now.
00302             if(vigra::isImage(files[i].c_str()))
00303             {
00304                 filenames[file] = 0;
00305             };
00306             file = ::wxFindNextFile();
00307         }
00308     }
00309 
00310     DEBUG_INFO("found " << filenames.size() << " candidate files to search.");
00311 
00312     // For each globbed or loaded file,
00313     StringToPointerHash::iterator found;
00314     std::map<std::string, time_t> timeMap;
00315     for (found = filenames.begin(); found != filenames.end(); ++found)
00316     {
00317         wxString file = found->first;
00318         // Check the time if it's got a camera EXIF timestamp.
00319         time_t stamp = ReadExifTime(file.mb_str(HUGIN_CONV_FILENAME));
00320         if (stamp)
00321         {
00322             filenames[file] = stamp;
00323             timeMap[(const char *)file.mb_str(HUGIN_CONV_FILENAME)] = stamp;
00324         }
00325     }
00326 
00327     //TODO: sorting the filenames keys by timestamp would be useful
00328     int maxtimediff = wxConfigBase::Get()->Read(wxT("CaptureTimeSpan"), HUGIN_CAPTURE_TIMESPAN);
00329     // For each timestamped file,
00330     for (found = filenames.begin(); found != filenames.end(); ++found)
00331     {
00332         wxString recruit = found->first;
00333         if (preloaded[recruit] == 1)
00334             continue;
00335         time_t pledge = filenames[recruit];
00336         if (!pledge)
00337             continue;
00338 
00339         // For each other image already loaded,
00340         for(size_t i=0;i<files.size();i++)
00341         {
00342             wxString file(files[i].c_str(), HUGIN_CONV_FILENAME);
00343             if (file == recruit)
00344                 continue;
00345 
00346             // If it is within threshold time,
00347             time_t stamp = filenames[file];
00348             if (abs((int)(pledge - stamp)) < maxtimediff)
00349             {
00350                 // Load this file, and remember it.
00351                 DEBUG_TRACE("Recruited " << recruit.mb_str(wxConvLocal));
00352                 std::string file = (const char *)recruit.mb_str(HUGIN_CONV_FILENAME);
00353                 files.push_back(file);
00354                 // Don't recruit it again.
00355                 filenames[recruit] = 0;
00356                 break;
00357             }
00358         }
00359     }
00360 
00361     if(files.size()>0)
00362     {
00363         // sort files by date
00364         sortbytime spred(timeMap);
00365         sort(files.begin(), files.end(), spred);
00366         // Load all of the named files.
00367         return new PanoCommand::wxAddImagesCmd(pano,files);
00368     }
00369     else
00370     {
00371         wxMessageBox(
00372             _("No matching images found."),
00373 #ifdef _WINDOWS
00374             _("Hugin"),
00375 #else
00376             wxT(""),
00377 #endif
00378             wxOK | wxICON_INFORMATION, parent);
00379         return NULL;
00380     };
00381 };
00382 
00383 wxString RemoveImageOperation::GetLabel()
00384 {
00385     return _("Remove selected image(s)");
00386 };
00387 
00388 PanoCommand::PanoCommand* RemoveImageOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00389 {
00390     //remove images from cache
00391     for (UIntSet::iterator it = images.begin(); it != images.end(); ++it)
00392     {
00393         ImageCache::getInstance().removeImage(pano.getImage(*it).getFilename());
00394     }
00395     return new PanoCommand::RemoveImagesCmd(pano, images);
00396 };
00397 
00398 wxString ChangeAnchorImageOperation::GetLabel()
00399 {
00400     return _("Anchor this image for position");
00401 };
00402 
00403 PanoCommand::PanoCommand* ChangeAnchorImageOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00404 {
00405     PanoramaOptions opt = pano.getOptions();
00406     opt.optimizeReferenceImage = *(images.begin());
00407     return new PanoCommand::SetPanoOptionsCmd(pano,opt);
00408 };
00409 
00410 wxString ChangeColorAnchorImageOperation::GetLabel()
00411 {
00412     return _("Anchor this image for exposure");
00413 };
00414 
00415 PanoCommand::PanoCommand* ChangeColorAnchorImageOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00416 {
00417     PanoramaOptions opt = pano.getOptions();
00418     opt.colorReferenceImage = *(images.begin());
00419     // Set the color correction mode so that the anchor image is persisted
00420     if (opt.colorCorrection == 0)
00421     {
00422         opt.colorCorrection = (PanoramaOptions::ColorCorrection) 1;
00423     }
00424     return new PanoCommand::SetPanoOptionsCmd(pano, opt);
00425 };
00426 
00427 bool NewLensOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00428 {
00429     if(pano.getNrOfImages()==0 || images.size()==0)
00430     {
00431         return false;
00432     }
00433     else
00434     {
00435         HuginBase::StandardImageVariableGroups variable_groups(pano);
00436         return variable_groups.getLenses().getNumberOfParts()<pano.getNrOfImages();
00437     };
00438 };
00439 
00440 wxString NewLensOperation::GetLabel()
00441 {
00442     return _("New lens");
00443 };
00444 
00445 PanoCommand::PanoCommand* NewLensOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00446 {
00447     return new PanoCommand::NewPartCmd(pano, images, HuginBase::StandardImageVariableGroups::getLensVariables());
00448 };
00449 
00450 bool ChangeLensOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00451 {
00452     if(pano.getNrOfImages()==0 || images.size()==0)
00453     {
00454         return false;
00455     }
00456     else
00457     {
00458         //project must have more than 1 lens before you can assign an other lens number
00459         HuginBase::StandardImageVariableGroups variableGroups(pano);
00460         return variableGroups.getLenses().getNumberOfParts() > 1;
00461     };
00462 };
00463 
00464 wxString ChangeLensOperation::GetLabel()
00465 {
00466     return _("Change lens...");
00467 };
00468 
00469 PanoCommand::PanoCommand* ChangeLensOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00470 {
00471     HuginBase::StandardImageVariableGroups variable_groups(pano);
00472     long nr = wxGetNumberFromUser(
00473                             _("Enter new lens number"),
00474                             _("Lens number"),
00475                             _("Change lens number"), 0, 0,
00476                             variable_groups.getLenses().getNumberOfParts()-1
00477                                  );
00478     if (nr >= 0)
00479     {
00480         // user accepted
00481         return new PanoCommand::ChangePartNumberCmd(pano, images, nr, HuginBase::StandardImageVariableGroups::getLensVariables());
00482     }
00483     else
00484     {
00485         return NULL;
00486     };
00487 };
00488 
00489 LoadLensOperation::LoadLensOperation(bool fromDatabase)
00490 {
00491     m_fromDatabase = fromDatabase;
00492 };
00493 
00494 wxString LoadLensOperation::GetLabel()
00495 {
00496     if (m_fromDatabase)
00497     {
00498         return _("Load lens from lens database");
00499     }
00500     else
00501     {
00502         return _("Load lens from ini file");
00503     };
00504 };
00505 
00506 PanoCommand::PanoCommand* LoadLensOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00507 {
00508     HuginBase::StandardImageVariableGroups variable_groups(pano);
00509     if(images.size()==1)
00510     {
00511         if(wxMessageBox(_("You selected only one image.\nShould the loaded parameters be applied to all images with the same lens?"),_("Question"), wxICON_QUESTION | wxYES_NO)==wxYES)
00512         {
00513             unsigned int lensNr = variable_groups.getLenses().getPartNumber(*images.begin());
00514             // get all images with the current lens.
00515             for (size_t i = 0; i < pano.getNrOfImages(); i++)
00516             {
00517                 if (variable_groups.getLenses().getPartNumber(i) == lensNr)
00518                 {
00519                     images.insert(i);
00520                 };
00521             };
00522         };
00523     };
00524     vigra::Size2D sizeImg0=pano.getImage(*(images.begin())).getSize();
00525     //check if all images have the same size
00526     bool differentImageSize=false;
00527     for(UIntSet::const_iterator it=images.begin();it!=images.end() && !differentImageSize;++it)
00528     {
00529         differentImageSize=(pano.getImage(*it).getSize()!=sizeImg0);
00530     };
00531     if(differentImageSize)
00532     {
00533         if(wxMessageBox(_("You selected images with different sizes.\nApply lens parameter file can result in unwanted results.\nApply settings anyway?"), _("Error"), wxICON_QUESTION |wxYES_NO)==wxID_NO)
00534         {
00535             return NULL;
00536         };
00537     };
00538     PanoCommand::PanoCommand* cmd=NULL;
00539     bool isLoaded=false;
00540     if (m_fromDatabase)
00541     {
00542         isLoaded=ApplyLensDBParameters(parent,&pano,images,cmd);
00543     }
00544     else
00545     {
00546         isLoaded=ApplyLensParameters(parent,&pano,images,cmd);
00547     };
00548     if(isLoaded)
00549     {
00550         return cmd;
00551     }
00552     else
00553     {
00554         return NULL;
00555     }
00556 };
00557 
00558 SaveLensOperation::SaveLensOperation(bool toDatabase)
00559 {
00560     m_database = toDatabase;
00561 };
00562 
00563 wxString SaveLensOperation::GetLabel()
00564 {
00565     if (m_database)
00566     {
00567         return _("Save lens parameters to lens database");
00568     }
00569     else
00570     {
00571         return _("Save lens to ini file");
00572     };
00573 };
00574 
00575 PanoCommand::PanoCommand* SaveLensOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00576 {
00577     unsigned int imgNr = *(images.begin());
00578     if (m_database)
00579     {
00580         SaveLensParameters(parent, pano.getImage(imgNr));
00581     }
00582     else
00583     {
00584         SaveLensParametersToIni(parent, &pano, images);
00585     };
00586     return NULL;
00587 };
00588 
00589 wxString RemoveControlPointsOperation::GetLabel()
00590 {
00591     return _("Remove control points");
00592 };
00593 
00594 bool RemoveControlPointsOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00595 {
00596     return pano.getNrOfImages()>0 && pano.getNrOfCtrlPoints()>0;
00597 };
00598 
00599 PanoCommand::PanoCommand* RemoveControlPointsOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00600 {
00601     UIntSet selImages;
00602     if(images.size()==0)
00603     {
00604         fill_set(selImages,0,pano.getNrOfCtrlPoints()-1);
00605     }
00606     else
00607     {
00608         selImages=images;
00609     };
00610     UIntSet cpsToDelete;
00611     const CPVector & cps = pano.getCtrlPoints();
00612     for (CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
00613     {
00614         if (set_contains(selImages, (*it).image1Nr) && set_contains(selImages, (*it).image2Nr) )
00615         {
00616             cpsToDelete.insert(it - cps.begin());
00617         }
00618     }
00619     if(cpsToDelete.size()==0)
00620     {
00621         wxMessageBox(_("Selected images have no control points."),
00622 #ifdef __WXMSW__
00623             wxT("Hugin"),
00624 #else
00625             wxT(""),
00626 #endif
00627             wxICON_EXCLAMATION | wxOK);
00628         return NULL;
00629     };
00630     int r =wxMessageBox(wxString::Format(_("Really delete %lu control points?"),
00631                                          (unsigned long int) cpsToDelete.size()),
00632                         _("Delete Control Points"),
00633                         wxICON_QUESTION | wxYES_NO);
00634     if (r == wxYES)
00635     {
00636         return new PanoCommand::RemoveCtrlPointsCmd(pano, cpsToDelete );
00637     }
00638     else
00639     {
00640         return NULL;
00641     };
00642 };
00643 
00644 wxString CleanControlPointsOperation::GetLabel()
00645 {
00646     return _("Clean control points");
00647 };
00648 
00649 bool CleanControlPointsOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00650 {
00651     return pano.getNrOfCtrlPoints()>2;
00652 };
00653 
00654 PanoCommand::PanoCommand* CleanControlPointsOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00655 {
00656     deregisterPTWXDlgFcn();
00657     ProgressReporterDialog progress(0, _("Cleaning Control points"), _("Checking pairwise"), parent);
00658 
00659     UIntSet removedCPs=getCPoutsideLimit_pair(pano, progress, 2.0);
00660 
00661     //create a copy to work with
00662     //we copy remaining control points to new pano object for running second step
00663     HuginBase::Panorama newPano=pano.duplicate();
00664     std::map<size_t,size_t> cpMap;
00665     CPVector allCPs=newPano.getCtrlPoints();
00666     CPVector firstCleanedCP;
00667     size_t j=0;
00668     for(size_t i=0;i<allCPs.size();i++)
00669     {
00670         ControlPoint cp=allCPs[i];
00671         if(cp.mode==ControlPoint::X_Y && !set_contains(removedCPs,i))
00672         {
00673             firstCleanedCP.push_back(cp);
00674             cpMap[j++]=i;
00675         };
00676     };
00677     newPano.setCtrlPoints(firstCleanedCP);
00678 
00679     //check for unconnected images
00680     CPGraph graph;
00681     createCPGraph(newPano, graph);
00682     CPComponents comps;
00683     const size_t n=findCPComponents(graph, comps);
00684     if (!progress.updateDisplayValue(_("Checking whole project")))
00685     {
00686         return NULL;
00687     }
00688     if (n <= 1)
00689     {
00690         //now run the second step
00691         UIntSet removedCP2=getCPoutsideLimit(newPano, 2.0);
00692         if(removedCP2.size()>0)
00693         {
00694             for(UIntSet::const_iterator it=removedCP2.begin();it!=removedCP2.end();++it)
00695             {
00696                 removedCPs.insert(cpMap[*it]);
00697             };
00698         };
00699     }
00700     registerPTWXDlgFcn();
00701     if (!progress.updateDisplay(_("Finished cleaning")))
00702     {
00703         return NULL;
00704     }
00705     if (removedCPs.size()>0)
00706     {
00707         wxMessageBox(wxString::Format(_("Removed %lu control points"), (unsigned long int)removedCPs.size()), _("Cleaning"), wxOK | wxICON_INFORMATION, parent);
00708         return new PanoCommand::RemoveCtrlPointsCmd(pano,removedCPs);
00709     };
00710     return NULL;
00711 };
00712 
00713 wxString CelesteOperation::GetLabel()
00714 {
00715     return _("Remove control points on clouds");
00716 };
00717 
00718 PanoCommand::PanoCommand* CelesteOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00719 {
00720     ProgressReporterDialog progress(images.size() + 2, _("Running Celeste"), _("Running Celeste"), parent);
00721     progress.updateDisplay(_("Loading model file"));
00722 
00723     struct celeste::svm_model* model=MainFrame::Get()->GetSVMModel();
00724     if (model == NULL || !progress.updateDisplay(_("Loading images")))
00725     {
00726         return NULL;
00727     };
00728 
00729     // Get Celeste parameters
00730     wxConfigBase *cfg = wxConfigBase::Get();
00731     // SVM threshold
00732     double threshold = HUGIN_CELESTE_THRESHOLD;
00733     cfg->Read(wxT("/Celeste/Threshold"), &threshold, HUGIN_CELESTE_THRESHOLD);
00734 
00735     // Mask resolution - 1 sets it to fine
00736     bool t = (cfg->Read(wxT("/Celeste/Filter"), HUGIN_CELESTE_FILTER) == 0);
00737     int radius=(t)?10:20;
00738     DEBUG_TRACE("Running Celeste");
00739 
00740     UIntSet cpsToRemove;
00741     for (UIntSet::const_iterator it=images.begin(); it!=images.end(); ++it)
00742     {
00743         // Image to analyse
00744         HuginBase::CPointVector cps=pano.getCtrlPointsVectorForImage(*it);
00745         if(cps.size()==0)
00746         {
00747             if (!progress.updateDisplayValue())
00748             {
00749                 return NULL;
00750             };
00751             continue;
00752         };
00753         ImageCache::EntryPtr img=ImageCache::getInstance().getImage(pano.getImage(*it).getFilename());
00754         vigra::UInt16RGBImage in;
00755         if(img->image16->width()>0)
00756         {
00757             in.resize(img->image16->size());
00758             vigra::omp::copyImage(srcImageRange(*(img->image16)),destImage(in));
00759         }
00760         else
00761         {
00762             ImageCache::ImageCacheRGB8Ptr im8=img->get8BitImage();
00763             in.resize(im8->size());
00764             vigra::omp::transformImage(srcImageRange(*im8),destImage(in),vigra::functor::Arg1()*vigra::functor::Param(65535/255));
00765         };
00766         if (!progress.updateDisplay(_("Running Celeste")))
00767         {
00768             return NULL;
00769         };
00770         UIntSet cloudCP=celeste::getCelesteControlPoints(model,in,cps,radius,threshold,800);
00771         in.resize(0,0);
00772         if (!progress.updateDisplay())
00773         {
00774             return NULL;
00775         };
00776         if(cloudCP.size()>0)
00777         {
00778             for(UIntSet::const_iterator it2=cloudCP.begin();it2!=cloudCP.end(); ++it2)
00779             {
00780                 cpsToRemove.insert(*it2);
00781             };
00782         };
00783         if (!progress.updateDisplayValue(_("Loading images")))
00784         {
00785             return NULL;
00786         };
00787     };
00788 
00789     if (!progress.updateDisplayValue())
00790     {
00791         return NULL;
00792     }
00793     if (cpsToRemove.size()>0)
00794     {
00795         wxMessageBox(wxString::Format(_("Removed %lu control points"), (unsigned long int) cpsToRemove.size()), _("Celeste result"),wxOK|wxICON_INFORMATION);
00796         return new PanoCommand::RemoveCtrlPointsCmd(pano,cpsToRemove);
00797     }
00798     else
00799     {
00800         return NULL;
00801     };
00802 };
00803 
00804 ResetOperation::ResetOperation(ResetMode newResetMode)
00805 {
00806     m_resetMode=newResetMode;
00807     m_resetPos=(m_resetMode==RESET_POSITION);
00808     m_resetTranslation=(m_resetMode==RESET_TRANSLATION);
00809     m_resetHFOV=(m_resetMode==RESET_LENS);
00810     m_resetLens=(m_resetMode==RESET_LENS);
00811     m_resetExposure=0;
00812     if(m_resetMode==RESET_PHOTOMETRICS)
00813     {
00814         m_resetExposure=1;
00815     };
00816     m_resetVignetting=(m_resetMode==RESET_PHOTOMETRICS);
00817     if(m_resetMode==RESET_PHOTOMETRICS)
00818     {
00819         m_resetColor=1;
00820     };
00821     m_resetCameraResponse=(m_resetMode==RESET_PHOTOMETRICS);
00822 };
00823 
00824 wxString ResetOperation::GetLabel()
00825 {
00826     switch(m_resetMode)
00827     {
00828         case RESET_DIALOG:
00829         case RESET_DIALOG_LENS:
00830         case RESET_DIALOG_PHOTOMETRICS:
00831             return _("Reset user defined...");
00832             break;
00833         case RESET_POSITION:
00834             return _("Reset positions");
00835             break;
00836         case RESET_TRANSLATION:
00837             return _("Reset translation parameters");
00838             break;
00839         case RESET_LENS:
00840             return _("Reset lens parameters");
00841             break;
00842         case RESET_PHOTOMETRICS:
00843             return _("Reset photometric parameters");
00844     };
00845     return wxEmptyString;
00846 };
00847 
00848 bool ResetOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00849 {
00850     switch(m_resetMode)
00851     {
00852         case RESET_TRANSLATION:
00853             return guiLevel>=GUI_EXPERT && pano.getNrOfImages()>0;
00854             break;
00855         default:
00856             return pano.getNrOfImages()>0;
00857     };
00858 };
00859 
00860 PanoCommand::PanoCommand* ResetOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00861 {
00862     if(m_resetMode==RESET_DIALOG || m_resetMode==RESET_DIALOG_LENS || m_resetMode==RESET_DIALOG_PHOTOMETRICS)
00863     {
00864         if(!ShowDialog(parent))
00865         {
00866             return NULL;
00867         };
00868     };
00869     if(images.size()==0)
00870     {
00871         fill_set(images,0,pano.getNrOfImages()-1);
00872     };
00873     // If we should unlink exposure value (to load it from EXIF)
00874     bool needs_unlink_exposure = false;
00875     bool needs_unlink_redbal = false;
00876     bool needs_unlink_bluebal = false;
00877     double redBalanceAnchor = pano.getImage(pano.getOptions().colorReferenceImage).getExifRedBalance();
00878     double blueBalanceAnchor = pano.getImage(pano.getOptions().colorReferenceImage).getExifBlueBalance();
00879     if(fabs(redBalanceAnchor)<1e-2)
00880     {
00881         redBalanceAnchor=1;
00882     };
00883     if(fabs(blueBalanceAnchor)<1e-2)
00884     {
00885         blueBalanceAnchor=1;
00886     };
00887 
00888     VariableMapVector vars;
00889     for(UIntSet::const_iterator it = images.begin(); it != images.end(); ++it)
00890     {
00891         unsigned int imgNr = *it;
00892         VariableMap ImgVars=pano.getImageVariables(imgNr);
00893         if(m_resetPos)
00894         {
00895             map_get(ImgVars,"y").setValue(0);
00896             map_get(ImgVars,"p").setValue(0);
00897             map_get(ImgVars,"r").setValue(pano.getSrcImage(imgNr).getExifOrientation());
00898             map_get(ImgVars,"TrX").setValue(0);
00899             map_get(ImgVars,"TrY").setValue(0);
00900             map_get(ImgVars,"TrZ").setValue(0);
00901             map_get(ImgVars,"Tpy").setValue(0);
00902             map_get(ImgVars,"Tpp").setValue(0);
00903         };
00904         if(m_resetTranslation)
00905         {
00906             map_get(ImgVars,"TrX").setValue(0);
00907             map_get(ImgVars,"TrY").setValue(0);
00908             map_get(ImgVars,"TrZ").setValue(0);
00909             map_get(ImgVars,"Tpy").setValue(0);
00910             map_get(ImgVars,"Tpp").setValue(0);
00911         };
00912         SrcPanoImage srcImg = pano.getSrcImage(imgNr);
00913         if(m_resetHFOV)
00914         {
00915             double focalLength=srcImg.getExifFocalLength();
00916             double cropFactor=srcImg.getExifCropFactor();
00917             if(focalLength!=0 && cropFactor!=0)
00918             {
00919                 double newHFOV=HuginBase::SrcPanoImage::calcHFOV(srcImg.getProjection(), focalLength, cropFactor, srcImg.getSize());
00920                 if(newHFOV!=0)
00921                 {
00922                     map_get(ImgVars,"v").setValue(newHFOV);
00923                 };
00924             };
00925         };
00926         if(m_resetLens)
00927         {
00928             map_get(ImgVars,"a").setValue(0);
00929             map_get(ImgVars,"b").setValue(0);
00930             map_get(ImgVars,"c").setValue(0);
00931             map_get(ImgVars,"d").setValue(0);
00932             map_get(ImgVars,"e").setValue(0);
00933             map_get(ImgVars,"g").setValue(0);
00934             map_get(ImgVars,"t").setValue(0);
00935         };
00936         if(m_resetExposure>0)
00937         {
00938             if(m_resetExposure==1)
00939             {
00940                 if (pano.getImage(imgNr).ExposureValueisLinked())
00941                 {
00942                     /* Unlink exposure value variable so the EXIF values can be
00943                      * independant. */
00944                     needs_unlink_exposure = true;
00945                 }
00946                 //reset to exif value
00947                 double eV=srcImg.calcExifExposureValue();
00948                 if(eV!=0)
00949                 {
00950                     map_get(ImgVars,"Eev").setValue(eV);
00951                 }
00952             }
00953             else
00954             {
00955                 //reset to zero
00956                 map_get(ImgVars,"Eev").setValue(0);
00957             };
00958         };
00959         if(m_resetColor>0)
00960         {
00961             if(m_resetColor==1)
00962             {
00963                 if (pano.getImage(imgNr).WhiteBalanceRedisLinked())
00964                 {
00965                     /* Unlink red balance variable so the EXIF values can be
00966                      * independant. */
00967                     needs_unlink_redbal = true;
00968                 }
00969                 if (pano.getImage(imgNr).WhiteBalanceBlueisLinked())
00970                 {
00971                     /* Unlink red balance variable so the EXIF values can be
00972                      * independant. */
00973                     needs_unlink_bluebal = true;
00974                 }
00975                 double redBal=1;
00976                 double blueBal=1;
00977                 const SrcPanoImage& img=pano.getImage(imgNr);
00978                 const SrcPanoImage& anchor=pano.getImage(pano.getOptions().colorReferenceImage);
00979                 // use EXIF Red/BlueBalance data only if image and anchor image are from the same camera
00980                 if(img.getExifMake() == anchor.getExifMake() &&
00981                     img.getExifModel() == anchor.getExifModel())
00982                 {
00983                     redBal=fabs(img.getExifRedBalance()/redBalanceAnchor);
00984                     if(redBal<1e-2)
00985                     {
00986                         redBal=1;
00987                     };
00988                     blueBal=fabs(img.getExifBlueBalance()/blueBalanceAnchor);
00989                     if(blueBal<1e-2)
00990                     {
00991                         blueBal=1;
00992                     };
00993                 };
00994                 map_get(ImgVars,"Er").setValue(redBal);
00995                 map_get(ImgVars,"Eb").setValue(blueBal);
00996             }
00997             else
00998             {
00999                 map_get(ImgVars,"Er").setValue(1);
01000                 map_get(ImgVars,"Eb").setValue(1);
01001             };
01002         };
01003         if(m_resetVignetting)
01004         {
01005             map_get(ImgVars,"Vb").setValue(0);
01006             map_get(ImgVars,"Vc").setValue(0);
01007             map_get(ImgVars,"Vd").setValue(0);
01008             map_get(ImgVars,"Vx").setValue(0);
01009             map_get(ImgVars,"Vy").setValue(0);
01010 
01011         };
01012         if(m_resetCameraResponse)
01013         {
01014             map_get(ImgVars,"Ra").setValue(0);
01015             map_get(ImgVars,"Rb").setValue(0);
01016             map_get(ImgVars,"Rc").setValue(0);
01017             map_get(ImgVars,"Rd").setValue(0);
01018             map_get(ImgVars,"Re").setValue(0);
01019         };
01020         vars.push_back(ImgVars);
01021     };
01022     std::vector<PanoCommand::PanoCommand *> reset_commands;
01023     if (needs_unlink_exposure)
01024     {
01025         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01026         variables.insert(HuginBase::ImageVariableGroup::IVE_ExposureValue);
01027         
01028         reset_commands.push_back(
01029                 new PanoCommand::ChangePartImagesLinkingCmd(
01030                             pano,
01031                             images,
01032                             variables,
01033                             false,
01034                             HuginBase::StandardImageVariableGroups::getLensVariables())
01035                 );
01036     }
01037     if (needs_unlink_redbal)
01038     {
01039         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01040         variables.insert(HuginBase::ImageVariableGroup::IVE_WhiteBalanceRed);
01041         
01042         reset_commands.push_back(
01043                 new PanoCommand::ChangePartImagesLinkingCmd(
01044                             pano,
01045                             images,
01046                             variables,
01047                             false,
01048                             HuginBase::StandardImageVariableGroups::getLensVariables())
01049                 );
01050     }
01051     if (needs_unlink_bluebal)
01052     {
01053         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01054         variables.insert(HuginBase::ImageVariableGroup::IVE_WhiteBalanceBlue);
01055         
01056         reset_commands.push_back(
01057                 new PanoCommand::ChangePartImagesLinkingCmd(
01058                             pano,
01059                             images,
01060                             variables,
01061                             false,
01062                             HuginBase::StandardImageVariableGroups::getLensVariables())
01063                 );
01064     }
01065     reset_commands.push_back(
01066                             new PanoCommand::UpdateImagesVariablesCmd(pano, images, vars)
01067                                            );
01068     if(m_resetExposure>0)
01069     {
01070         //reset panorama output exposure value
01071         reset_commands.push_back(new PanoCommand::ResetToMeanExposure(pano));
01072     };
01073     return new PanoCommand::CombinedPanoCommand(pano, reset_commands);
01074 };
01075 
01076 bool ResetOperation::ShowDialog(wxWindow* parent)
01077 {
01078     ResetDialog reset_dlg(parent, m_guiLevel);
01079     bool checkGeometric;
01080     bool checkPhotometric;
01081     switch(m_resetMode)
01082     {
01083         case RESET_DIALOG:
01084             checkGeometric=true;
01085             checkPhotometric=true;
01086             break;
01087         case RESET_DIALOG_LENS:
01088             reset_dlg.LimitToGeometric();
01089             checkGeometric=true;
01090             checkPhotometric=false;
01091             break;
01092         case RESET_DIALOG_PHOTOMETRICS:
01093             reset_dlg.LimitToPhotometric();
01094             checkGeometric=false;
01095             checkPhotometric=true;
01096     };
01097     if(reset_dlg.ShowModal()==wxID_OK)
01098     {
01099         if(checkGeometric)
01100         {
01101             m_resetPos=reset_dlg.GetResetPos();
01102             m_resetTranslation=reset_dlg.GetResetTranslation();
01103             m_resetHFOV=reset_dlg.GetResetFOV();
01104             m_resetLens=reset_dlg.GetResetLens();
01105         };
01106         if(checkPhotometric)
01107         {
01108             if(reset_dlg.GetResetExposure())
01109             {
01110                 if(reset_dlg.GetResetExposureToExif())
01111                 {
01112                     m_resetExposure=1;
01113                 }
01114                 else
01115                 {
01116                     m_resetExposure=2;
01117                 };
01118             }
01119             else
01120             {
01121                 m_resetExposure=0;
01122             };
01123             m_resetVignetting=reset_dlg.GetResetVignetting();
01124             if(reset_dlg.GetResetColor())
01125             {
01126                 if(reset_dlg.GetResetColorToExif())
01127                 {
01128                     m_resetColor=1;
01129                 }
01130                 else
01131                 {
01132                     m_resetColor=2;
01133                 };
01134             }
01135             else
01136             {
01137                 m_resetColor=0;
01138             };
01139             m_resetCameraResponse=reset_dlg.GetResetResponse();
01140         };
01141         return true;
01142     }
01143     else
01144     {
01145         return false;
01146     };
01147 };
01148 
01149 bool NewStackOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
01150 {
01151     if(pano.getNrOfImages()==0 || images.size()==0)
01152     {
01153         return false;
01154     }
01155     else
01156     {
01157         HuginBase::StandardImageVariableGroups variable_groups(pano);
01158         return variable_groups.getStacks().getNumberOfParts()<pano.getNrOfImages();
01159     };
01160 };
01161 
01162 wxString NewStackOperation::GetLabel()
01163 {
01164     return _("New stack");
01165 };
01166 
01167 PanoCommand::PanoCommand* NewStackOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
01168 {
01169     return new PanoCommand::NewPartCmd(pano, images, HuginBase::StandardImageVariableGroups::getStackVariables());
01170 };
01171 
01172 bool ChangeStackOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
01173 {
01174     if(pano.getNrOfImages()==0 || images.size()==0)
01175     {
01176         return false;
01177     }
01178     else
01179     {
01180         //project must have more than 1 stack before you can assign an other stack number
01181         HuginBase::StandardImageVariableGroups variableGroups(pano);
01182         return variableGroups.getStacks().getNumberOfParts() > 1;
01183     };
01184 };
01185 
01186 wxString ChangeStackOperation::GetLabel()
01187 {
01188     return _("Change stack...");
01189 };
01190 
01191 PanoCommand::PanoCommand* ChangeStackOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
01192 {
01193     HuginBase::StandardImageVariableGroups variable_groups(pano);
01194     long nr = wxGetNumberFromUser(
01195                             _("Enter new stack number"),
01196                             _("stack number"),
01197                             _("Change stack number"), 0, 0,
01198                             variable_groups.getStacks().getNumberOfParts()-1
01199                                  );
01200     if (nr >= 0)
01201     {
01202         // user accepted
01203         return new PanoCommand::ChangePartNumberCmd(pano, images, nr, HuginBase::StandardImageVariableGroups::getStackVariables());
01204     }
01205     else
01206     {
01207         return NULL;
01208     };
01209 };
01210 
01211 bool AssignStacksOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
01212 {
01213     return pano.getNrOfImages()>1;
01214 };
01215 
01216 wxString AssignStacksOperation::GetLabel()
01217 {
01218     return _("Set stack size...");
01219 };
01220 
01221 PanoCommand::PanoCommand* AssignStacksOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
01222 {
01223     wxConfigBase* cfg = wxConfigBase::Get();
01224     wxDialog dlg;
01225     wxXmlResource::Get()->LoadDialog(&dlg, parent, wxT("stack_size_dialog"));
01226     wxSpinCtrl* stackSpin = XRCCTRL(dlg, "stack_size_spinctrl", wxSpinCtrl);
01227     stackSpin->SetRange(1, pano.getNrOfImages());
01228     size_t oldStackSize = cfg->Read(wxT("/StackDialog/StackSize"), 3);
01229     oldStackSize = std::min(oldStackSize, pano.getNrOfImages());
01230     stackSpin->SetValue(oldStackSize);
01231     wxCheckBox* linkCheckBox = XRCCTRL(dlg, "stack_size_link_checkbox", wxCheckBox);
01232     linkCheckBox->SetValue(cfg->Read(wxT("/StackDialog/LinkPosition"), true) != 0l);
01233     if (dlg.ShowModal() != wxID_OK)
01234     {
01235         // user has canceled dialog
01236         return NULL;
01237     };
01238     long stackSize = stackSpin->GetValue();
01239     bool linkPosition = linkCheckBox->IsChecked();
01240     cfg->Write(wxT("/StackDialog/StackSize"), stackSize);
01241     cfg->Write(wxT("/StackDialog/LinkPosition"), linkPosition);
01242     if(stackSize<0)
01243     {
01244         return NULL;
01245     };
01246     std::vector<PanoCommand::PanoCommand *> commands;
01247     HuginBase::StandardImageVariableGroups variable_groups(pano);
01248     if(variable_groups.getStacks().getNumberOfParts()<pano.getNrOfImages())
01249     {
01250         // first remove all existing stacks
01251         for(size_t i=1; i<pano.getNrOfImages(); i++)
01252         {
01253             UIntSet imgs;
01254             imgs.insert(i);
01255             commands.push_back(new PanoCommand::NewPartCmd(pano, imgs, HuginBase::StandardImageVariableGroups::getStackVariables()));
01256         };
01257     };
01258 
01259     if (stackSize > 1)
01260     {
01261         size_t stackNr=0;
01262         size_t imgNr=0;
01263         while(imgNr<pano.getNrOfImages())
01264         {
01265             UIntSet imgs;
01266             for(size_t i=0; i<stackSize && imgNr<pano.getNrOfImages(); i++)
01267             {
01268                 imgs.insert(imgNr);
01269                 imgNr++;
01270             };
01271             commands.push_back(new PanoCommand::ChangePartNumberCmd(pano, imgs, stackNr, HuginBase::StandardImageVariableGroups::getStackVariables()));
01272             stackNr++;
01273         };
01274     };
01275 
01276     if (!linkPosition && stackSize > 1)
01277     {
01278         // unlink image position
01279         UIntSet imgs;
01280         fill_set(imgs, 0, pano.getNrOfImages() - 1);
01281         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01282         variables.insert(HuginBase::ImageVariableGroup::IVE_Yaw);
01283         variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
01284         variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
01285         variables.insert(HuginBase::ImageVariableGroup::IVE_X);
01286         variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
01287         variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
01288         variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
01289         variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
01290         commands.push_back(new PanoCommand::ChangePartImagesLinkingCmd(pano, imgs, variables, false, HuginBase::StandardImageVariableGroups::getStackVariables()));
01291     };
01292     return new PanoCommand::CombinedPanoCommand(pano, commands);
01293 };
01294 
01295 static PanoOperationVector PanoOpImages;
01296 static PanoOperationVector PanoOpLens;
01297 static PanoOperationVector PanoOpStacks;
01298 static PanoOperationVector PanoOpControlPoints;
01299 static PanoOperationVector PanoOpReset;
01300 
01301 PanoOperationVector* GetImagesOperationVector()
01302 {
01303     return &PanoOpImages;
01304 };
01305 
01306 PanoOperationVector* GetLensesOperationVector()
01307 {
01308     return &PanoOpLens;
01309 };
01310 
01311 PanoOperationVector* GetStacksOperationVector()
01312 {
01313     return &PanoOpStacks;
01314 };
01315 
01316 PanoOperationVector* GetControlPointsOperationVector()
01317 {
01318     return &PanoOpControlPoints;
01319 };
01320 
01321 PanoOperationVector* GetResetOperationVector()
01322 {
01323     return &PanoOpReset;
01324 };
01325 
01326 void GeneratePanoOperationVector()
01327 {
01328     PanoOpImages.push_back(new AddImageOperation());
01329     PanoOpImages.push_back(new AddImagesSeriesOperation());
01330     PanoOpImages.push_back(new RemoveImageOperation());
01331     PanoOpImages.push_back(new ChangeAnchorImageOperation());
01332     PanoOpImages.push_back(new ChangeColorAnchorImageOperation());
01333 
01334     PanoOpLens.push_back(new NewLensOperation());
01335     PanoOpLens.push_back(new ChangeLensOperation());
01336     PanoOpLens.push_back(new LoadLensOperation(false));
01337     PanoOpLens.push_back(new LoadLensOperation(true));
01338     PanoOpLens.push_back(new SaveLensOperation(false));
01339     PanoOpLens.push_back(new SaveLensOperation(true));
01340 
01341     PanoOpStacks.push_back(new NewStackOperation());
01342     PanoOpStacks.push_back(new ChangeStackOperation());
01343     PanoOpStacks.push_back(new AssignStacksOperation());
01344 
01345     PanoOpControlPoints.push_back(new RemoveControlPointsOperation());
01346     PanoOpControlPoints.push_back(new CelesteOperation());
01347     PanoOpControlPoints.push_back(new CleanControlPointsOperation());
01348 
01349     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_POSITION));
01350     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_TRANSLATION));
01351     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_LENS));
01352     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_PHOTOMETRICS));
01353     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_DIALOG));
01354 
01355 };
01356 
01357 
01358 void _CleanPanoOperationVector(PanoOperationVector& vec)
01359 {
01360     for(size_t i=0; i<vec.size(); i++)
01361     {
01362         delete vec[i];
01363     }
01364     vec.clear();
01365 };
01366 
01367 void CleanPanoOperationVector()
01368 {
01369     _CleanPanoOperationVector(PanoOpImages);
01370     _CleanPanoOperationVector(PanoOpLens);
01371     _CleanPanoOperationVector(PanoOpStacks);
01372     _CleanPanoOperationVector(PanoOpControlPoints);
01373     _CleanPanoOperationVector(PanoOpReset);
01374 };
01375 
01376 } //namespace

Generated on 1 Aug 2015 for Hugintrunk by  doxygen 1.4.7