PreviewEditCPTool.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00011 /*
00012  *  This program is free software; you can redistribute it and/or
00013  *  modify it under the terms of the GNU General Public
00014  *  License as published by the Free Software Foundation; either
00015  *  version 2 of the License, or (at your option) any later version.
00016  *
00017  *  This software is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  *  General Public License for more details.
00021  *
00022  *  You should have received a copy of the GNU General Public
00023  *  License along with this software. If not, see
00024  *  <http://www.gnu.org/licenses/>.
00025  *
00026  */
00027 
00028 #include "hugin/PreviewEditCPTool.h"
00029 #include "panoinc_WX.h"
00030 #include "panoinc.h"
00031 #include <map>
00032 
00033 #include <wx/platform.h>
00034 #ifdef __WXMAC__
00035 #include <OpenGL/gl.h>
00036 #else
00037 #ifdef __WXMSW__
00038 #include <vigra/windows.h>
00039 #endif
00040 #include <GL/gl.h>
00041 #endif
00042 
00043 #include "GLPreviewFrame.h"
00044 
00045 // we want to handle the mouse events and to draw over the panorama when in use, so make sure we get notice.
00046 void PreviewEditCPTool::Activate()
00047 {
00048     helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this);
00049     helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this);
00050     helper->NotifyMe(PreviewToolHelper::REALLY_DRAW_OVER_IMAGES, this);
00051     m_mouseDown = false;
00052     helper->SetStatusMessage(_("Drag a rectangle and select the desired action for the control points in the selected rectangle."));
00053 };
00054 
00055 // The panorama has been drawn, now draw the selection rectangle.
00056 void PreviewEditCPTool::ReallyAfterDrawImagesEvent()
00057 {
00058     if (m_mouseDown)
00059     {
00060         glDisable(GL_TEXTURE_2D);
00061         const hugin_utils::FDiff2D dist(m_currentPosScreen - m_startPosScreen);
00062         // select color depending on size
00063         if (fabs(dist.x) > 10 && fabs(dist.y) > 10)
00064         {
00065             glColor3f(1.0f, 1.0f, 0.0f);
00066         }
00067         else
00068         {
00069             // selection is too small, use a gray color
00070             glColor3f(0.7f, 0.7f, 0.7f);
00071         }
00072         glBegin(GL_LINES);
00073         glVertex2f(m_startPos.x, m_startPos.y);
00074         glVertex2f(m_currentPos.x, m_startPos.y);
00075         glVertex2f(m_currentPos.x, m_startPos.y);
00076         glVertex2f(m_currentPos.x, m_currentPos.y);
00077         glVertex2f(m_currentPos.x, m_currentPos.y);
00078         glVertex2f(m_startPos.x, m_currentPos.y);
00079         glVertex2f(m_startPos.x, m_currentPos.y);
00080         glVertex2f(m_startPos.x, m_startPos.y);
00081         glEnd();
00082         glEnable(GL_TEXTURE_2D);
00083     };
00084 };
00085 
00086 // update selection rectangle
00087 void PreviewEditCPTool::MouseMoveEvent(double x, double y, wxMouseEvent & e)
00088 {
00089     if (m_mouseDown)
00090     {
00091         m_currentPos = helper->GetMousePanoPosition();
00092         m_currentPosScreen = helper->GetMouseScreenPosition();
00093         // force redrawing
00094         helper->GetVisualizationStatePtr()->ForceRequireRedraw();
00095         helper->GetVisualizationStatePtr()->Redraw();
00096     };
00097 }
00098 
00099 // handle mouse buttons
00100 void PreviewEditCPTool::MouseButtonEvent(wxMouseEvent &e)
00101 {
00102     if (e.GetButton() && m_menuPopup)
00103     {
00104         // catch first mouse click after menu popup
00105         // to correctly handle dismiss of popup menu
00106         m_menuPopup = false;
00107     }
00108     else
00109     {
00110         if (e.ButtonDown(wxMOUSE_BTN_LEFT) && !m_mouseDown)
00111         {
00112             // start selecting rectangle
00113             m_mouseDown = true;
00114             m_startPos = helper->GetMousePanoPosition();
00115             m_startPosScreen = helper->GetMouseScreenPosition();
00116             m_CPinROI.clear();
00117         }
00118         else
00119         {
00120             if (e.ButtonUp(wxMOUSE_BTN_LEFT) && m_mouseDown)
00121             {
00122                 // finish selecting
00123                 m_mouseDown = false;
00124                 m_currentPos = helper->GetMousePanoPosition();
00125                 m_currentPosScreen = helper->GetMouseScreenPosition();
00126                 const hugin_utils::FDiff2D dist (m_currentPosScreen - m_startPosScreen);
00127                 if (fabs(dist.x)>10 && fabs(dist.y)>10)
00128                 {
00129                     // build menu
00130                     wxMenu menu;
00131                     const vigra::Rect2D roi = GetSelectedROI();
00132                     // selected roi should have at least 10 pixel width and height in pano space
00133                     if (!roi.isEmpty() && roi.width() > 10 && roi.height() > 10)
00134                     {
00135                         menu.Append(ID_CREATE_CP, _("Create control points here"));
00136                     }
00137                     FindCPInRect(m_startPos, m_currentPos);
00138                     if (!m_CPinROI.empty())
00139                     {
00140                         menu.Append(ID_REMOVE_CP, wxString::Format(_("Remove %lu control points"), static_cast<unsigned long int>(m_CPinROI.size())));
00141                     }
00142                     if (!menu.GetMenuItems().IsEmpty())
00143                     {
00144                         m_menuPopup = true;
00145                         helper->GetPreviewFrame()->PopupMenu(&menu);
00146                     }
00147                     else
00148                     {
00149                         wxBell();
00150                         helper->GetVisualizationStatePtr()->ForceRequireRedraw();
00151                         helper->GetVisualizationStatePtr()->Redraw();
00152                     }
00153                 }
00154                 else
00155                 {
00156                     wxBell();
00157                     // we need to redraw so that the selection rectangle vanishes
00158                     helper->GetVisualizationStatePtr()->ForceRequireRedraw();
00159                     helper->GetVisualizationStatePtr()->Redraw();
00160                 };
00161             };
00162         };
00163     };
00164 };
00165 
00166 // find all cp in the given rectangle
00167 void PreviewEditCPTool::FindCPInRect(const hugin_utils::FDiff2D& pos1, const hugin_utils::FDiff2D& pos2)
00168 {
00169     HuginBase::Panorama* pano = helper->GetPanoramaPtr();
00170     HuginBase::UIntSet activeImages = pano->getActiveImages();
00171     const hugin_utils::FDiff2D panoPos1(pos1.x < pos2.x ? pos1.x : pos2.x, pos1.y < pos2.y ? pos1.y : pos2.y);
00172     const hugin_utils::FDiff2D panoPos2(pos1.x > pos2.x ? pos1.x : pos2.x, pos1.y > pos2.y ? pos1.y : pos2.y);
00173     m_CPinROI.clear();
00174     if (!activeImages.empty())
00175     {
00176         // create transformation objects
00177         typedef std::map<size_t, HuginBase::PTools::Transform*> TransformMap;
00178         TransformMap transformations;
00179         for (HuginBase::UIntSet::iterator it = activeImages.begin(); it != activeImages.end(); ++it)
00180         {
00181             HuginBase::PTools::Transform* trans = new HuginBase::PTools::Transform();
00182             trans->createInvTransform(pano->getImage(*it), pano->getOptions());
00183             transformations.insert(std::make_pair(*it, trans));
00184         };
00185         HuginBase::CPVector cps = pano->getCtrlPoints();
00186         for (HuginBase::CPVector::const_iterator cpIt = cps.begin(); cpIt != cps.end(); ++cpIt)
00187         {
00188             // check cp only if both images are visible
00189             if (set_contains(activeImages, cpIt->image1Nr) && set_contains(activeImages, cpIt->image2Nr))
00190             {
00191                 hugin_utils::FDiff2D pos1;
00192                 hugin_utils::FDiff2D pos2;
00193                 // remove all control points, where both points are inside the given rectangle
00194                 if (transformations[cpIt->image1Nr]->transformImgCoord(pos1, hugin_utils::FDiff2D(cpIt->x1, cpIt->y1)) &&
00195                     transformations[cpIt->image2Nr]->transformImgCoord(pos2, hugin_utils::FDiff2D(cpIt->x2, cpIt->y2)))
00196                 {
00197                     if (panoPos1.x <= pos1.x && pos1.x <= panoPos2.x && panoPos1.y <= pos1.y && pos1.y <= panoPos2.y &&
00198                         panoPos1.x <= pos2.x && pos2.x <= panoPos2.x && panoPos1.y <= pos2.y && pos2.y <= panoPos2.y)
00199                     {
00200                         m_CPinROI.insert(cpIt - cps.begin());
00201                     };
00202                 };
00203             };
00204         };
00205         for (TransformMap::iterator it = transformations.begin(); it != transformations.end(); ++it)
00206         {
00207             delete it->second;
00208         };
00209     };
00210 };
00211 
00212 // return the selected ROI
00213 vigra::Rect2D PreviewEditCPTool::GetSelectedROI()
00214 {
00215     vigra::Point2D p1;
00216     p1.x = std::min(m_startPos.x, m_currentPos.x);
00217     p1.y = std::min(m_startPos.y, m_currentPos.y);
00218     vigra::Point2D p2;
00219     p2.x = std::max(m_startPos.x, m_currentPos.x);
00220     p2.y = std::max(m_startPos.y, m_currentPos.y);
00221     return vigra::Rect2D(p1, p2) & vigra::Rect2D(helper->GetPanoramaPtr()->getOptions().getSize());
00222 };
00223 
00224 // for correctly handling the popup menu 
00225 // when selecting the popup menu or dismiss the popup menu we get an additional mouse
00226 // click, we need to ignore this one, this function sets the state back
00227 void PreviewEditCPTool::SetMenuProcessed()
00228 {
00229     m_menuPopup = false;
00230 };

Generated on 23 Jan 2018 for Hugintrunk by  doxygen 1.4.7