PapywizardImport.cpp

Go to the documentation of this file.
00001 
00009 /*  This 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 *  Lesser 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 "PapywizardImport.h"
00026 
00027 #include "panoinc_WX.h"
00028 #include "hugin_utils/utils.h"
00029 #include <wx/xml/xml.h>
00030 #include <wx/msgdlg.h>
00031 #include <wx/stdpaths.h>
00032 #include "hugin/huginApp.h"
00033 #include "base_wx/CommandHistory.h"
00034 #include "base_wx/PanoCommand.h"
00035 #include "base_wx/platform.h"
00036 #include "base_wx/MyExternalCmdExecDialog.h"
00037 #include "base_wx/wxPanoCommand.h"
00038 #include "icpfind/AutoCtrlPointCreator.h"
00039 #include "hugin/config_defaults.h"
00040 
00041 namespace Papywizard
00042 {
00043 
00045 class PapywizardSettings
00046 {
00047 public:
00048     // read from header
00049     double focallength;
00050     double cropfactor;
00051     HuginBase::SrcPanoImage::Projection projection;
00052     // read from shoot section
00053     struct PapywizardImage
00054     {
00055         size_t id;
00056         size_t bracket;
00057         double yaw, pitch, roll;
00058     };
00059 
00060     std::vector<PapywizardImage> images;
00062     PapywizardSettings()
00063     {
00064         focallength = 0;
00065         cropfactor = 1;
00066         projection = HuginBase::SrcPanoImage::RECTILINEAR;
00067     };
00068 
00069     bool HasBracketImages() const
00070     {
00071         for (size_t i = 0; i < images.size(); ++i)
00072         {
00073             if (images[i].bracket > 1)
00074             {
00075                 return true;
00076             };
00077         };
00078         return false;
00079     };
00080 };
00081 
00083 bool ParseHeader(wxXmlNode* root, PapywizardSettings& images)
00084 {
00085     wxXmlNode* child = root->GetChildren();
00086     while (child)
00087     {
00088         // section <camera>
00089         if (child->GetName().CmpNoCase(wxT("camera")) == 0)
00090         {
00091             wxXmlNode* camChild = child->GetChildren();
00092             while (camChild)
00093             {
00094                 // crop factor is saved as attribute in <sensor>
00095                 if (camChild->GetName().CmpNoCase(wxT("sensor")) == 0)
00096                 {
00097                     wxString number;
00098                     if (camChild->GetAttribute(wxT("coef"), &number))
00099                     {
00100                         if (!hugin_utils::stringToDouble(std::string(number.mb_str(wxConvLocal)), images.cropfactor))
00101                         {
00102                             return false;
00103                         };
00104                     };
00105                 }
00106                 camChild = camChild->GetNext();
00107             }
00108         }
00109         // section <lens>
00110         if (child->GetName().CmpNoCase(wxT("lens")) == 0)
00111         {
00112             // projection as type attribute
00113             wxString projection = child->GetAttribute(wxT("type"), wxEmptyString).Trim().Trim(false);
00114             if (!projection.empty())
00115             {
00116                 if (projection.CmpNoCase(wxT("rectilinear")) == 0)
00117                 {
00118                     images.projection = HuginBase::SrcPanoImage::RECTILINEAR;
00119                 }
00120                 else
00121                 {
00122                     if (projection.CmpNoCase(wxT("fisheye")) == 0)
00123                     {
00124                         images.projection = HuginBase::SrcPanoImage::CIRCULAR_FISHEYE;
00125                     }
00126                     else
00127                     {
00128                         return false;
00129                     };
00130                 };
00131             };
00132             // focal length as own element
00133             wxXmlNode* lensChild = child->GetChildren();
00134             while (lensChild)
00135             {
00136                 if (lensChild->GetName().CmpNoCase(wxT("focal")) == 0)
00137                 {
00138                     wxString focallength = lensChild->GetNodeContent().Trim().Trim(false);
00139                     if(!hugin_utils::stringToDouble(std::string(focallength.mb_str(wxConvLocal)), images.focallength))
00140                     {
00141                         return false;
00142                     };
00143                 }
00144                 lensChild = lensChild->GetNext();
00145             }
00146         };
00147         child = child->GetNext();
00148     };
00149     return true;
00150 };
00151 
00153 bool ParseShoot(wxXmlNode* root, PapywizardSettings& images)
00154 {
00155     wxXmlNode* child = root->GetChildren();
00156     size_t id = 1;
00157     while (child)
00158     {
00159         if (child->GetName().CmpNoCase(wxT("pict")) == 0)
00160         {
00161             PapywizardSettings::PapywizardImage image;
00162             long longVal;
00163             wxString s;
00164             // check id
00165             if (!child->GetAttribute(wxT("id"), &s))
00166             {
00167                 return false;
00168             };
00169             if (!s.ToLong(&longVal))
00170             {
00171                 return false;
00172             };
00173             if (longVal < id)
00174             {
00175                 return false;
00176             };
00177             image.id = longVal;
00178             ++id;
00179             // read bracket attribute
00180             if(!child->GetAttribute(wxT("bracket"), &s))
00181             {
00182                 return false;
00183             };
00184             if (!s.ToLong(&longVal))
00185             {
00186                 return false;
00187             };
00188             image.bracket = longVal;
00189             // now parse all position entries
00190             wxXmlNode* posChild = child->GetChildren();
00191             while (posChild)
00192             {
00193                 if (posChild->GetName().CmpNoCase(wxT("position")) == 0)
00194                 {
00195                     if (!posChild->GetAttribute(wxT("yaw"), &s))
00196                     {
00197                         return false;
00198                     };
00199                     if (!hugin_utils::stringToDouble(std::string(s.mb_str(wxConvLocal)), image.yaw))
00200                     {
00201                         return false;
00202                     };
00203                     if (!posChild->GetAttribute(wxT("pitch"), &s))
00204                     {
00205                         return false;
00206                     }
00207                     if (!hugin_utils::stringToDouble(std::string(s.mb_str(wxConvLocal)), image.pitch))
00208                     {
00209                         return false;
00210                     };
00211                     if (!posChild->GetAttribute(wxT("roll"), &s))
00212                     {
00213                         return false;
00214                     };
00215                     if (!hugin_utils::stringToDouble(std::string(s.mb_str(wxConvLocal)), image.roll))
00216                     {
00217                         return false;
00218                     };
00219                     images.images.push_back(image);
00220                     // we are ignoring all further entries
00221                     break;
00222                 };
00223                 posChild = posChild->GetNext();
00224             };
00225         };
00226         child = child->GetNext();
00227     };
00228     return true;
00229 };
00230 
00231 bool ParsePapywizardFile(const wxString& filename, PapywizardSettings& images)
00232 {
00233     wxXmlDocument xmlFile;
00234     if (!xmlFile.Load(filename))
00235     {
00236         return false;
00237     }
00238     if (xmlFile.GetRoot()->GetName().CmpNoCase(wxT("papywizard")) != 0)
00239     {
00240         // not a papywizard file
00241         return false;
00242     };
00243     // iterate all children
00244     wxXmlNode* child = xmlFile.GetRoot()->GetChildren();
00245     while (child)
00246     {
00247         if (child->GetName().CmpNoCase(wxT("header")) == 0)
00248         {
00249             if (!ParseHeader(child, images))
00250             {
00251                 return false;
00252             };
00253         };
00254         if (child->GetName().CmpNoCase(wxT("shoot")) == 0)
00255         {
00256             if (!ParseShoot(child, images))
00257             {
00258                 return false;
00259             };
00260         }
00261         child = child->GetNext();
00262     }
00263     return true;
00264 };
00265 
00266 class PapywizardImportDialog: public wxDialog
00267 {
00268 public:
00270     PapywizardImportDialog(wxWindow *parent)
00271     {
00272         wxXmlResource::Get()->LoadDialog(this, parent, wxT("papywizard_import_dialog"));
00273 #ifdef __WXMSW__
00274         wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"), wxBITMAP_TYPE_ICO);
00275 #else
00276         wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"), wxBITMAP_TYPE_PNG);
00277 #endif
00278         SetIcon(myIcon);
00279         m_linkPos = XRCCTRL(*this, "papywizard_link_positions", wxCheckBox);
00280         m_cpfind = XRCCTRL(*this, "papywizard_cpfind", wxCheckBox);
00281         m_cpfindParams = XRCCTRL(*this, "papywizard_cpfind_parameters", wxTextCtrl);
00282         m_geocpset = XRCCTRL(*this, "papywizard_geocpset", wxCheckBox);
00283         const wxString cpfindParams = wxConfig::Get()->Read(wxT("/PapywizardImportCpfind"), wxEmptyString);
00284         m_cpfindParams->SetValue(cpfindParams);
00285         RestoreFramePosition(this, wxT("PapywizardImportDialog"));
00286     };
00288     ~PapywizardImportDialog()
00289     {
00290         StoreFramePosition(this, wxT("PapywizardImportDialog"));
00291         if (m_cpfind->IsChecked())
00292         {
00293             wxConfig::Get()->Write(wxT("/PapywizardImportCpfind"), m_cpfindParams->GetValue());
00294         };
00295     };
00296     void EnableStack(const bool hasStacks)
00297     {
00298         m_linkPos->Enable(hasStacks);
00299         m_linkPos->SetValue(hasStacks);
00300     };
00301     const bool LinkStacks() const
00302     {
00303         return m_linkPos->IsEnabled() && m_linkPos->IsChecked();
00304     };
00305     const bool RunCpfind() const
00306     {
00307         return m_cpfind->IsChecked();
00308     };
00309     const wxString GetCPFindParam() const
00310     {
00311         return m_cpfindParams->GetValue();
00312     };
00313     const bool RunGeocpset() const
00314     {
00315         return m_geocpset->IsEnabled() && m_geocpset->IsChecked();
00316     };
00317 protected:
00318     void OnCpfindCheck(wxCommandEvent& e)
00319     {
00320         const bool cpfindActive = m_cpfind->IsChecked();
00321         m_cpfindParams->Enable(cpfindActive);
00322         m_geocpset->Enable(cpfindActive);
00323     };
00324 private:
00325     wxCheckBox* m_linkPos;
00326     wxCheckBox* m_cpfind;
00327     wxTextCtrl* m_cpfindParams;
00328     wxCheckBox* m_geocpset;
00329     DECLARE_EVENT_TABLE()
00330 };
00331 
00332 BEGIN_EVENT_TABLE(PapywizardImportDialog, wxDialog)
00333     EVT_CHECKBOX(XRCID("papywizard_cpfind"), PapywizardImportDialog::OnCpfindCheck)
00334 END_EVENT_TABLE()
00335 
00336 bool ImportPapywizardFile(const wxString& filename, HuginBase::Panorama& pano)
00337 {
00338     PapywizardSettings papyImages;
00339     if (!ParsePapywizardFile(filename, papyImages))
00340     {
00341         wxMessageBox(wxString::Format(_("Could not parse file %s as Papywizard XML file."), filename.c_str()),
00342 #ifdef __WXMSW__
00343             _("Hugin"),
00344 #else
00345             wxT(""),
00346 #endif
00347             wxOK);
00348         return false;
00349     };
00350     // check if number of images matches
00351     if(papyImages.images.size()!=pano.getNrOfImages())
00352     {
00353         wxMessageBox(wxString::Format(_("The current project does not match with the Papywizard xml file.\nThe Papywizard file \"%s\" contains %lu images, but the Hugin project contains %lu images."), filename.c_str(), static_cast<unsigned long>(papyImages.images.size()), static_cast<unsigned long>(pano.getNrOfImages())),
00354 #ifdef __WXMSW__
00355             _("Hugin"),
00356 #else
00357             wxT(""),
00358 #endif
00359             wxOK);
00360         return false;
00361     };
00362     PapywizardImportDialog dialog(wxGetActiveWindow());
00363     dialog.EnableStack(papyImages.HasBracketImages());
00364     if(dialog.ShowModal()!=wxID_OK)
00365     { 
00366         return false;
00367     };
00368     // now we can build all commands
00369     std::vector<PanoCommand::PanoCommand *> commands;
00370     HuginBase::UIntSet images;
00371     fill_set(images, 0, pano.getNrOfImages() - 1);
00372     // all images share the same lens
00373     commands.push_back(new PanoCommand::ChangePartNumberCmd(pano, images, 0, HuginBase::StandardImageVariableGroups::getLensVariables()));
00374     commands.push_back(new PanoCommand::ChangeImageProjectionCmd(pano, images, papyImages.projection));
00375     if (papyImages.focallength > 0)
00376     {
00377         commands.push_back(new PanoCommand::UpdateCropFactorCmd(pano, images, papyImages.cropfactor));
00378         commands.push_back(new PanoCommand::UpdateFocalLengthCmd(pano, images, papyImages.focallength));
00379     };
00380     // remove all existing stacks
00381     for (size_t i = 1; i < pano.getNrOfImages(); i++)
00382     {
00383         HuginBase::UIntSet imgs;
00384         imgs.insert(i);
00385         commands.push_back(new PanoCommand::NewPartCmd(pano, imgs, HuginBase::StandardImageVariableGroups::getStackVariables()));
00386     };
00387     // create stacks
00388     if (papyImages.HasBracketImages())
00389     {
00390         size_t stackNr = 0;
00391         size_t imgNr = 0;
00392         while (imgNr < pano.getNrOfImages())
00393         {
00394             HuginBase::UIntSet imgs;
00395             do
00396             {
00397                 imgs.insert(imgNr);
00398                 imgNr++;
00399             } while (imgNr < pano.getNrOfImages() && papyImages.images[imgNr].bracket != 1);
00400             commands.push_back(new PanoCommand::ChangePartNumberCmd(pano, imgs, stackNr, HuginBase::StandardImageVariableGroups::getStackVariables()));
00401             stackNr++;
00402         };
00403         // unlink position if wished by user
00404         if (!dialog.LinkStacks())
00405         {
00406             std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
00407             variables.insert(HuginBase::ImageVariableGroup::IVE_Yaw);
00408             variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
00409             variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
00410             variables.insert(HuginBase::ImageVariableGroup::IVE_X);
00411             variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
00412             variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
00413             variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
00414             variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
00415             commands.push_back(new PanoCommand::ChangePartImagesLinkingCmd(pano, images, variables, false, HuginBase::StandardImageVariableGroups::getStackVariables()));
00416         }
00417     };
00418     // now set the positions    
00419     HuginBase::VariableMapVector variables = pano.getVariables();
00420     for (size_t i = 0; i < papyImages.images.size(); ++i)
00421     {
00422         map_get(variables[i], "y").setValue(papyImages.images[i].yaw);
00423         map_get(variables[i], "p").setValue(papyImages.images[i].pitch);
00424         map_get(variables[i], "r").setValue(papyImages.images[i].roll);
00425         map_get(variables[i], "TrX").setValue(0);
00426         map_get(variables[i], "TrY").setValue(0);
00427         map_get(variables[i], "TrZ").setValue(0);
00428         map_get(variables[i], "Tpy").setValue(0);
00429         map_get(variables[i], "Tpp").setValue(0);
00430         // fov gets updated when focal length is set, this has not yet been happen
00431         // so remove fov from list to prevent overwritting with old value, because
00432         // variables have not yet been updated yet
00433         variables[i].erase("v");
00434     };
00435     commands.push_back(new PanoCommand::UpdateVariablesCmd(pano, variables));
00436     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::CombinedPanoCommand(pano, commands));
00437     
00438     // now create the cp
00439     if (dialog.RunCpfind())
00440     {
00441         //save project into temp directory
00442         wxString tempDir = wxConfig::Get()->Read(wxT("tempDir"), wxT(""));
00443         if (!tempDir.IsEmpty())
00444         {
00445             if (tempDir.Last() != wxFileName::GetPathSeparator())
00446             {
00447                 tempDir.Append(wxFileName::GetPathSeparator());
00448             }
00449         };
00450         wxFileName scriptFileName(wxFileName::CreateTempFileName(tempDir + wxT("hp")));
00451         std::ofstream script(scriptFileName.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
00452         script.exceptions(std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit);
00453         pano.printPanoramaScript(script, pano.getOptimizeVector(), pano.getOptions(), images, false);
00454         script.close();
00455         // build command queue
00456         const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
00457         HuginQueue::CommandQueue* commands=new HuginQueue::CommandQueue();
00458         const wxString quotedProject(HuginQueue::wxEscapeFilename(scriptFileName.GetFullPath()));
00459         commands->push_back(new HuginQueue::NormalCommand(HuginQueue::GetInternalProgram(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), wxT("cpfind")),
00460             dialog.GetCPFindParam() + wxT(" --prealigned -o ") + quotedProject + wxT(" ") + quotedProject, _("Searching for control points...")));
00461         if (dialog.RunGeocpset())
00462         {
00463             commands->push_back(new HuginQueue::NormalCommand(HuginQueue::GetInternalProgram(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), wxT("geocpset")),
00464                 wxT("-o ") + quotedProject + wxT(" ") + quotedProject, _("Connecting overlapping images")));
00465         };
00466         //execute queue
00467         MyExecuteCommandQueue(commands, wxGetActiveWindow(), _("Searching control points"));
00468         //read back panofile
00469         PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::wxLoadPTProjectCmd(pano,
00470             (const char *)scriptFileName.GetFullPath().mb_str(HUGIN_CONV_FILENAME),
00471             (const char *)scriptFileName.GetPath(wxPATH_NATIVE | wxPATH_GET_SEPARATOR).mb_str(HUGIN_CONV_FILENAME),
00472             false, false));
00473         //delete temporary files
00474         wxRemoveFile(scriptFileName.GetFullPath());
00475     };
00476     return true;
00477 }
00478 
00479 } // namespace Papywizard
00480 

Generated on 25 Apr 2018 for Hugintrunk by  doxygen 1.4.7