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

Generated on 25 Jul 2017 for Hugintrunk by  doxygen 1.4.7