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 an other 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     if(images.size()==1)
00509     {
00510         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)
00511         {
00512             unsigned int lensNr = variable_groups.getLenses().getPartNumber(*images.begin());
00513             // get all images with the current lens.
00514             for (size_t i = 0; i < pano.getNrOfImages(); i++)
00515             {
00516                 if (variable_groups.getLenses().getPartNumber(i) == lensNr)
00517                 {
00518                     images.insert(i);
00519                 };
00520             };
00521         };
00522     };
00523     vigra::Size2D sizeImg0=pano.getImage(*(images.begin())).getSize();
00524     //check if all images have the same size
00525     bool differentImageSize=false;
00526     for(HuginBase::UIntSet::const_iterator it=images.begin();it!=images.end() && !differentImageSize;++it)
00527     {
00528         differentImageSize=(pano.getImage(*it).getSize()!=sizeImg0);
00529     };
00530     if(differentImageSize)
00531     {
00532         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)
00533         {
00534             return NULL;
00535         };
00536     };
00537     PanoCommand::PanoCommand* cmd=NULL;
00538     bool isLoaded=false;
00539     if (m_fromDatabase)
00540     {
00541         isLoaded=ApplyLensDBParameters(parent,&pano,images,cmd);
00542     }
00543     else
00544     {
00545         isLoaded=ApplyLensParameters(parent,&pano,images,cmd);
00546     };
00547     if(isLoaded)
00548     {
00549         return cmd;
00550     }
00551     else
00552     {
00553         return NULL;
00554     }
00555 };
00556 
00557 SaveLensOperation::SaveLensOperation(bool toDatabase)
00558 {
00559     m_database = toDatabase;
00560 };
00561 
00562 wxString SaveLensOperation::GetLabel()
00563 {
00564     if (m_database)
00565     {
00566         return _("Save lens parameters to lens database");
00567     }
00568     else
00569     {
00570         return _("Save lens to ini file");
00571     };
00572 };
00573 
00574 PanoCommand::PanoCommand* SaveLensOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00575 {
00576     unsigned int imgNr = *(images.begin());
00577     if (m_database)
00578     {
00579         SaveLensParameters(parent, pano.getImage(imgNr));
00580     }
00581     else
00582     {
00583         SaveLensParametersToIni(parent, &pano, images);
00584     };
00585     return NULL;
00586 };
00587 
00588 wxString RemoveControlPointsOperation::GetLabel()
00589 {
00590     return _("Remove control points");
00591 };
00592 
00593 bool RemoveControlPointsOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00594 {
00595     return pano.getNrOfImages()>0 && pano.getNrOfCtrlPoints()>0;
00596 };
00597 
00598 PanoCommand::PanoCommand* RemoveControlPointsOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00599 {
00600     HuginBase::UIntSet selImages;
00601     if(images.size()==0)
00602     {
00603         fill_set(selImages,0,pano.getNrOfCtrlPoints()-1);
00604     }
00605     else
00606     {
00607         selImages=images;
00608     };
00609     HuginBase::UIntSet cpsToDelete;
00610     const HuginBase::CPVector & cps = pano.getCtrlPoints();
00611     for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
00612     {
00613         if (set_contains(selImages, (*it).image1Nr) && set_contains(selImages, (*it).image2Nr) )
00614         {
00615             cpsToDelete.insert(it - cps.begin());
00616         }
00617     }
00618     if(cpsToDelete.size()==0)
00619     {
00620         wxMessageBox(_("Selected images have no control points."),
00621 #ifdef __WXMSW__
00622             wxT("Hugin"),
00623 #else
00624             wxT(""),
00625 #endif
00626             wxICON_EXCLAMATION | wxOK);
00627         return NULL;
00628     };
00629     int r =wxMessageBox(wxString::Format(_("Really delete %lu control points?"),
00630                                          (unsigned long int) cpsToDelete.size()),
00631                         _("Delete Control Points"),
00632                         wxICON_QUESTION | wxYES_NO);
00633     if (r == wxYES)
00634     {
00635         return new PanoCommand::RemoveCtrlPointsCmd(pano, cpsToDelete );
00636     }
00637     else
00638     {
00639         return NULL;
00640     };
00641 };
00642 
00643 wxString CleanControlPointsOperation::GetLabel()
00644 {
00645     return _("Clean control points");
00646 };
00647 
00648 bool CleanControlPointsOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
00649 {
00650     return pano.getNrOfCtrlPoints()>2;
00651 };
00652 
00653 PanoCommand::PanoCommand* CleanControlPointsOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00654 {
00655     deregisterPTWXDlgFcn();
00656     ProgressReporterDialog progress(0, _("Cleaning Control points"), _("Checking pairwise"), parent);
00657 
00658     HuginBase::UIntSet removedCPs=getCPoutsideLimit_pair(pano, progress, 2.0);
00659 
00660     //create a copy to work with
00661     //we copy remaining control points to new pano object for running second step
00662     HuginBase::Panorama newPano=pano.duplicate();
00663     std::map<size_t,size_t> cpMap;
00664     HuginBase::CPVector allCPs=newPano.getCtrlPoints();
00665     HuginBase::CPVector firstCleanedCP;
00666     size_t j=0;
00667     for(size_t i=0;i<allCPs.size();i++)
00668     {
00669         HuginBase::ControlPoint cp = allCPs[i];
00670         if (cp.mode == HuginBase::ControlPoint::X_Y && !set_contains(removedCPs, i))
00671         {
00672             firstCleanedCP.push_back(cp);
00673             cpMap[j++]=i;
00674         };
00675     };
00676     newPano.setCtrlPoints(firstCleanedCP);
00677 
00678     //check for unconnected images
00679     HuginGraph::ImageGraph graph(newPano);
00680     if (!progress.updateDisplayValue(_("Checking whole project")))
00681     {
00682         return NULL;
00683     }
00684     if (graph.IsConnected())
00685     {
00686         //now run the second step
00687         HuginBase::UIntSet removedCP2=getCPoutsideLimit(newPano, 2.0);
00688         if(removedCP2.size()>0)
00689         {
00690             for(HuginBase::UIntSet::const_iterator it=removedCP2.begin();it!=removedCP2.end();++it)
00691             {
00692                 removedCPs.insert(cpMap[*it]);
00693             };
00694         };
00695     }
00696     registerPTWXDlgFcn();
00697     if (!progress.updateDisplay(_("Finished cleaning")))
00698     {
00699         return NULL;
00700     }
00701     if (removedCPs.size()>0)
00702     {
00703         wxMessageBox(wxString::Format(_("Removed %lu control points"), (unsigned long int)removedCPs.size()), _("Cleaning"), wxOK | wxICON_INFORMATION, parent);
00704         return new PanoCommand::RemoveCtrlPointsCmd(pano,removedCPs);
00705     };
00706     return NULL;
00707 };
00708 
00709 wxString CelesteOperation::GetLabel()
00710 {
00711     return _("Remove control points on clouds");
00712 };
00713 
00714 PanoCommand::PanoCommand* CelesteOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
00715 {
00716     ProgressReporterDialog progress(images.size() + 2, _("Running Celeste"), _("Running Celeste"), parent);
00717     progress.updateDisplay(_("Loading model file"));
00718 
00719     struct celeste::svm_model* model=MainFrame::Get()->GetSVMModel();
00720     if (model == NULL || !progress.updateDisplay(_("Loading images")))
00721     {
00722         return NULL;
00723     };
00724 
00725     // Get Celeste parameters
00726     wxConfigBase *cfg = wxConfigBase::Get();
00727     // SVM threshold
00728     double threshold = HUGIN_CELESTE_THRESHOLD;
00729     cfg->Read(wxT("/Celeste/Threshold"), &threshold, HUGIN_CELESTE_THRESHOLD);
00730 
00731     // Mask resolution - 1 sets it to fine
00732     bool t = (cfg->Read(wxT("/Celeste/Filter"), HUGIN_CELESTE_FILTER) == 0);
00733     int radius=(t)?10:20;
00734     DEBUG_TRACE("Running Celeste");
00735 
00736     HuginBase::UIntSet cpsToRemove;
00737     for (HuginBase::UIntSet::const_iterator it=images.begin(); it!=images.end(); ++it)
00738     {
00739         // Image to analyse
00740         HuginBase::CPointVector cps=pano.getCtrlPointsVectorForImage(*it);
00741         if(cps.size()==0)
00742         {
00743             if (!progress.updateDisplayValue())
00744             {
00745                 return NULL;
00746             };
00747             continue;
00748         };
00749         HuginBase::ImageCache::EntryPtr img = HuginBase::ImageCache::getInstance().getImage(pano.getImage(*it).getFilename());
00750         vigra::UInt16RGBImage in;
00751         if(img->image16->width()>0)
00752         {
00753             in.resize(img->image16->size());
00754             vigra::omp::copyImage(srcImageRange(*(img->image16)),destImage(in));
00755         }
00756         else
00757         {
00758             HuginBase::ImageCache::ImageCacheRGB8Ptr im8 = img->get8BitImage();
00759             in.resize(im8->size());
00760             vigra::omp::transformImage(srcImageRange(*im8),destImage(in),vigra::functor::Arg1()*vigra::functor::Param(65535/255));
00761         };
00762         if (!img->iccProfile->empty())
00763         {
00764             HuginBase::Color::ApplyICCProfile(in, *(img->iccProfile), TYPE_RGB_16);
00765         };
00766         if (!progress.updateDisplay(_("Running Celeste")))
00767         {
00768             return NULL;
00769         };
00770         HuginBase::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(HuginBase::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     HuginBase::VariableMapVector vars;
00889     for(HuginBase::UIntSet::const_iterator it = images.begin(); it != images.end(); ++it)
00890     {
00891         unsigned int imgNr = *it;
00892         HuginBase::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         HuginBase::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 HuginBase::SrcPanoImage& img=pano.getImage(imgNr);
00978                 const HuginBase::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_LENS:
01084             reset_dlg.LimitToGeometric();
01085             checkGeometric=true;
01086             checkPhotometric=false;
01087             break;
01088         case RESET_DIALOG_PHOTOMETRICS:
01089             reset_dlg.LimitToPhotometric();
01090             checkGeometric=false;
01091             checkPhotometric=true;
01092         case RESET_DIALOG:
01093         default:
01094             checkGeometric=true;
01095             checkPhotometric=true;
01096             break;
01097     };
01098     if(reset_dlg.ShowModal()==wxID_OK)
01099     {
01100         if(checkGeometric)
01101         {
01102             m_resetPos=reset_dlg.GetResetPos();
01103             m_resetTranslation=reset_dlg.GetResetTranslation();
01104             m_resetHFOV=reset_dlg.GetResetFOV();
01105             m_resetLens=reset_dlg.GetResetLens();
01106         };
01107         if(checkPhotometric)
01108         {
01109             if(reset_dlg.GetResetExposure())
01110             {
01111                 if(reset_dlg.GetResetExposureToExif())
01112                 {
01113                     m_resetExposure=1;
01114                 }
01115                 else
01116                 {
01117                     m_resetExposure=2;
01118                 };
01119             }
01120             else
01121             {
01122                 m_resetExposure=0;
01123             };
01124             m_resetVignetting=reset_dlg.GetResetVignetting();
01125             if(reset_dlg.GetResetColor())
01126             {
01127                 if(reset_dlg.GetResetColorToExif())
01128                 {
01129                     m_resetColor=1;
01130                 }
01131                 else
01132                 {
01133                     m_resetColor=2;
01134                 };
01135             }
01136             else
01137             {
01138                 m_resetColor=0;
01139             };
01140             m_resetCameraResponse=reset_dlg.GetResetResponse();
01141         };
01142         return true;
01143     }
01144     else
01145     {
01146         return false;
01147     };
01148 };
01149 
01150 bool NewStackOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
01151 {
01152     if(pano.getNrOfImages()==0 || images.size()==0)
01153     {
01154         return false;
01155     }
01156     else
01157     {
01158         HuginBase::StandardImageVariableGroups variable_groups(pano);
01159         return variable_groups.getStacks().getNumberOfParts()<pano.getNrOfImages();
01160     };
01161 };
01162 
01163 wxString NewStackOperation::GetLabel()
01164 {
01165     return _("New stack");
01166 };
01167 
01168 PanoCommand::PanoCommand* NewStackOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
01169 {
01170     return new PanoCommand::NewPartCmd(pano, images, HuginBase::StandardImageVariableGroups::getStackVariables());
01171 };
01172 
01173 bool ChangeStackOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
01174 {
01175     if(pano.getNrOfImages()==0 || images.size()==0)
01176     {
01177         return false;
01178     }
01179     else
01180     {
01181         //project must have more than 1 stack before you can assign an other stack number
01182         HuginBase::StandardImageVariableGroups variableGroups(pano);
01183         return variableGroups.getStacks().getNumberOfParts() > 1;
01184     };
01185 };
01186 
01187 wxString ChangeStackOperation::GetLabel()
01188 {
01189     return _("Change stack...");
01190 };
01191 
01192 PanoCommand::PanoCommand* ChangeStackOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
01193 {
01194     HuginBase::StandardImageVariableGroups variable_groups(pano);
01195     long nr = wxGetNumberFromUser(
01196                             _("Enter new stack number"),
01197                             _("stack number"),
01198                             _("Change stack number"), 0, 0,
01199                             variable_groups.getStacks().getNumberOfParts()-1
01200                                  );
01201     if (nr >= 0)
01202     {
01203         // user accepted
01204         return new PanoCommand::ChangePartNumberCmd(pano, images, nr, HuginBase::StandardImageVariableGroups::getStackVariables());
01205     }
01206     else
01207     {
01208         return NULL;
01209     };
01210 };
01211 
01212 bool AssignStacksOperation::IsEnabled(HuginBase::Panorama& pano, HuginBase::UIntSet images, GuiLevel guiLevel)
01213 {
01214     return pano.getNrOfImages()>1;
01215 };
01216 
01217 wxString AssignStacksOperation::GetLabel()
01218 {
01219     return _("Set stack size...");
01220 };
01221 
01222 PanoCommand::PanoCommand* AssignStacksOperation::GetInternalCommand(wxWindow* parent, HuginBase::Panorama& pano, HuginBase::UIntSet images)
01223 {
01224     wxConfigBase* cfg = wxConfigBase::Get();
01225     wxDialog dlg;
01226     wxXmlResource::Get()->LoadDialog(&dlg, parent, wxT("stack_size_dialog"));
01227     wxSpinCtrl* stackSpin = XRCCTRL(dlg, "stack_size_spinctrl", wxSpinCtrl);
01228     stackSpin->SetRange(1, pano.getNrOfImages());
01229     size_t oldStackSize = cfg->Read(wxT("/StackDialog/StackSize"), 3);
01230     oldStackSize = std::min(oldStackSize, pano.getNrOfImages());
01231     stackSpin->SetValue(oldStackSize);
01232     wxCheckBox* linkCheckBox = XRCCTRL(dlg, "stack_size_link_checkbox", wxCheckBox);
01233     linkCheckBox->SetValue(cfg->Read(wxT("/StackDialog/LinkPosition"), true) != 0l);
01234     if (dlg.ShowModal() != wxID_OK)
01235     {
01236         // user has canceled dialog
01237         return NULL;
01238     };
01239     long stackSize = stackSpin->GetValue();
01240     bool linkPosition = linkCheckBox->IsChecked();
01241     cfg->Write(wxT("/StackDialog/StackSize"), stackSize);
01242     cfg->Write(wxT("/StackDialog/LinkPosition"), linkPosition);
01243     if(stackSize<0)
01244     {
01245         return NULL;
01246     };
01247     std::vector<PanoCommand::PanoCommand *> commands;
01248     HuginBase::StandardImageVariableGroups variable_groups(pano);
01249     if(variable_groups.getStacks().getNumberOfParts()<pano.getNrOfImages())
01250     {
01251         // first remove all existing stacks
01252         for(size_t i=1; i<pano.getNrOfImages(); i++)
01253         {
01254             HuginBase::UIntSet imgs;
01255             imgs.insert(i);
01256             commands.push_back(new PanoCommand::NewPartCmd(pano, imgs, HuginBase::StandardImageVariableGroups::getStackVariables()));
01257         };
01258     };
01259 
01260     if (stackSize > 1)
01261     {
01262         size_t stackNr=0;
01263         size_t imgNr=0;
01264         while(imgNr<pano.getNrOfImages())
01265         {
01266             HuginBase::UIntSet imgs;
01267             for(size_t i=0; i<stackSize && imgNr<pano.getNrOfImages(); i++)
01268             {
01269                 imgs.insert(imgNr);
01270                 imgNr++;
01271             };
01272             commands.push_back(new PanoCommand::ChangePartNumberCmd(pano, imgs, stackNr, HuginBase::StandardImageVariableGroups::getStackVariables()));
01273             stackNr++;
01274         };
01275     };
01276 
01277     if (!linkPosition && stackSize > 1)
01278     {
01279         // unlink image position
01280         HuginBase::UIntSet imgs;
01281         fill_set(imgs, 0, pano.getNrOfImages() - 1);
01282         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01283         variables.insert(HuginBase::ImageVariableGroup::IVE_Yaw);
01284         variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
01285         variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
01286         variables.insert(HuginBase::ImageVariableGroup::IVE_X);
01287         variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
01288         variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
01289         variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
01290         variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
01291         commands.push_back(new PanoCommand::ChangePartImagesLinkingCmd(pano, imgs, variables, false, HuginBase::StandardImageVariableGroups::getStackVariables()));
01292     };
01293     return new PanoCommand::CombinedPanoCommand(pano, commands);
01294 };
01295 
01296 static PanoOperationVector PanoOpImages;
01297 static PanoOperationVector PanoOpLens;
01298 static PanoOperationVector PanoOpStacks;
01299 static PanoOperationVector PanoOpControlPoints;
01300 static PanoOperationVector PanoOpReset;
01301 
01302 PanoOperationVector* GetImagesOperationVector()
01303 {
01304     return &PanoOpImages;
01305 };
01306 
01307 PanoOperationVector* GetLensesOperationVector()
01308 {
01309     return &PanoOpLens;
01310 };
01311 
01312 PanoOperationVector* GetStacksOperationVector()
01313 {
01314     return &PanoOpStacks;
01315 };
01316 
01317 PanoOperationVector* GetControlPointsOperationVector()
01318 {
01319     return &PanoOpControlPoints;
01320 };
01321 
01322 PanoOperationVector* GetResetOperationVector()
01323 {
01324     return &PanoOpReset;
01325 };
01326 
01327 void GeneratePanoOperationVector()
01328 {
01329     PanoOpImages.push_back(new AddImageOperation());
01330     PanoOpImages.push_back(new AddImagesSeriesOperation());
01331     PanoOpImages.push_back(new RemoveImageOperation());
01332     PanoOpImages.push_back(new ChangeAnchorImageOperation());
01333     PanoOpImages.push_back(new ChangeColorAnchorImageOperation());
01334 
01335     PanoOpLens.push_back(new NewLensOperation());
01336     PanoOpLens.push_back(new ChangeLensOperation());
01337     PanoOpLens.push_back(new LoadLensOperation(false));
01338     PanoOpLens.push_back(new LoadLensOperation(true));
01339     PanoOpLens.push_back(new SaveLensOperation(false));
01340     PanoOpLens.push_back(new SaveLensOperation(true));
01341 
01342     PanoOpStacks.push_back(new NewStackOperation());
01343     PanoOpStacks.push_back(new ChangeStackOperation());
01344     PanoOpStacks.push_back(new AssignStacksOperation());
01345 
01346     PanoOpControlPoints.push_back(new RemoveControlPointsOperation());
01347     PanoOpControlPoints.push_back(new CelesteOperation());
01348     PanoOpControlPoints.push_back(new CleanControlPointsOperation());
01349 
01350     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_POSITION));
01351     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_TRANSLATION));
01352     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_LENS));
01353     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_PHOTOMETRICS));
01354     PanoOpReset.push_back(new ResetOperation(ResetOperation::RESET_DIALOG));
01355 
01356 };
01357 
01358 
01359 void _CleanPanoOperationVector(PanoOperationVector& vec)
01360 {
01361     for(size_t i=0; i<vec.size(); i++)
01362     {
01363         delete vec[i];
01364     }
01365     vec.clear();
01366 };
01367 
01368 void CleanPanoOperationVector()
01369 {
01370     _CleanPanoOperationVector(PanoOpImages);
01371     _CleanPanoOperationVector(PanoOpLens);
01372     _CleanPanoOperationVector(PanoOpStacks);
01373     _CleanPanoOperationVector(PanoOpControlPoints);
01374     _CleanPanoOperationVector(PanoOpReset);
01375 };
01376 
01377 } //namespace

Generated on 26 May 2016 for Hugintrunk by  doxygen 1.4.7