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

Generated on 17 Nov 2017 for Hugintrunk by  doxygen 1.4.7