Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PreviewEditCPTool.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /*
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This software is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public
23  * License along with this software. If not, see
24  * <http://www.gnu.org/licenses/>.
25  *
26  */
27 
28 #include "panoinc_WX.h"
29 #include "panoinc.h"
31 #include <map>
32 #include "base_wx/CommandHistory.h"
33 #include "base_wx/wxPanoCommand.h"
34 
35 #include <wx/platform.h>
36 #ifdef __WXMAC__
37 #include <OpenGL/gl.h>
38 #else
39 #ifdef __WXMSW__
40 #include <vigra/windows.h>
41 #endif
42 #include <GL/gl.h>
43 #endif
44 
45 #include "GLPreviewFrame.h"
46 #include "GLViewer.h"
47 
48 // we want to handle the mouse events and to draw over the panorama when in use, so make sure we get notice.
50 {
54  m_mouseDown = false;
55  helper->SetStatusMessage(_("Drag a rectangle and select the desired action for the control points in the selected rectangle. Alt + drag to create a line control point."));
56  // set cursor to cross on preview
57  helper->GetPreviewFrame()->getPreview()->SetCursor(*wxCROSS_CURSOR);
58 }
59 
61 {
62  // reset cursor back to default
63  helper->GetPreviewFrame()->getPreview()->SetCursor(wxNullCursor);
64 }
65 
66 // The panorama has been drawn, now draw the selection rectangle.
68 {
69  if (m_mouseDown)
70  {
71  glDisable(GL_TEXTURE_2D);
73  // select color depending on size
74  if (m_line || (fabs(dist.x) > 10 && fabs(dist.y) > 10))
75  {
76  glColor3f(1.0f, 1.0f, 0.0f);
77  }
78  else
79  {
80  // selection is too small, use a gray color
81  glColor3f(0.7f, 0.7f, 0.7f);
82  }
83  if (m_line)
84  {
85  glBegin(GL_LINES);
86  glVertex2f(m_startPos.x, m_startPos.y);
87  glVertex2f(m_currentPos.x, m_currentPos.y);
88  glEnd();
89  }
90  else
91  {
92  glBegin(GL_LINES);
93  glVertex2f(m_startPos.x, m_startPos.y);
94  glVertex2f(m_currentPos.x, m_startPos.y);
95  glVertex2f(m_currentPos.x, m_startPos.y);
96  glVertex2f(m_currentPos.x, m_currentPos.y);
97  glVertex2f(m_currentPos.x, m_currentPos.y);
98  glVertex2f(m_startPos.x, m_currentPos.y);
99  glVertex2f(m_startPos.x, m_currentPos.y);
100  glVertex2f(m_startPos.x, m_startPos.y);
101  glEnd();
102  };
103  glEnable(GL_TEXTURE_2D);
104  };
105 };
106 
107 // update selection rectangle
108 void PreviewEditCPTool::MouseMoveEvent(double x, double y, wxMouseEvent & e)
109 {
110  if (m_mouseDown)
111  {
114  // force redrawing
117  };
118 }
119 
120 // handle mouse buttons
122 {
123  if (e.GetButton() && m_menuPopup)
124  {
125  // catch first mouse click after menu popup
126  // to correctly handle dismiss of popup menu
127  m_menuPopup = false;
128  }
129  else
130  {
131  if (e.ButtonDown(wxMOUSE_BTN_LEFT) && !m_mouseDown)
132  {
133  // start selecting rectangle
134  m_mouseDown = true;
137  m_CPinROI.clear();
138  m_line = e.AltDown();
139  }
140  else
141  {
142  if (e.ButtonUp(wxMOUSE_BTN_LEFT) && m_mouseDown)
143  {
144  // finish selecting
145  m_mouseDown = false;
148  if (m_line)
149  {
150  // now add the line cp
152  }
153  else
154  {
156  if (fabs(dist.x) > 10 && fabs(dist.y) > 10)
157  {
158  // build menu
159  wxMenu menu;
160  const vigra::Rect2D roi = GetSelectedROI();
161  // selected roi should have at least 10 pixel width and height in pano space
162  if (!roi.isEmpty() && roi.width() > 10 && roi.height() > 10)
163  {
164  menu.Append(ID_CREATE_CP, _("Create control points here"));
165  };
167  if (!m_CPinROI.empty())
168  {
169  menu.Append(ID_REMOVE_CP, wxString::Format(_("Remove %lu control points"), static_cast<unsigned long int>(m_CPinROI.size())));
170  };
171  if (!menu.GetMenuItems().IsEmpty())
172  {
173  m_menuPopup = true;
174  helper->GetPreviewFrame()->PopupMenu(&menu);
175  }
176  else
177  {
178  wxBell();
181  };
182  }
183  else
184  {
185  wxBell();
186  // we need to redraw so that the selection rectangle vanishes
189  };
190  };
191  };
192  };
193  };
194 };
195 
196 // find all cp in the given rectangle
198 {
200  HuginBase::UIntSet activeImages = pano->getActiveImages();
201  const hugin_utils::FDiff2D panoPos1(pos1.x < pos2.x ? pos1.x : pos2.x, pos1.y < pos2.y ? pos1.y : pos2.y);
202  const hugin_utils::FDiff2D panoPos2(pos1.x > pos2.x ? pos1.x : pos2.x, pos1.y > pos2.y ? pos1.y : pos2.y);
203  m_CPinROI.clear();
204  if (!activeImages.empty())
205  {
206  // create transformation objects
207  typedef std::map<size_t, HuginBase::PTools::Transform*> TransformMap;
208  TransformMap transformations;
209  for (HuginBase::UIntSet::iterator it = activeImages.begin(); it != activeImages.end(); ++it)
210  {
212  trans->createInvTransform(pano->getImage(*it), pano->getOptions());
213  transformations.insert(std::make_pair(*it, trans));
214  };
215  HuginBase::CPVector cps = pano->getCtrlPoints();
216  for (HuginBase::CPVector::const_iterator cpIt = cps.begin(); cpIt != cps.end(); ++cpIt)
217  {
218  // check cp only if both images are visible
219  if (set_contains(activeImages, cpIt->image1Nr) && set_contains(activeImages, cpIt->image2Nr))
220  {
223  // remove all control points, where both points are inside the given rectangle
224  if (transformations[cpIt->image1Nr]->transformImgCoord(pos1, hugin_utils::FDiff2D(cpIt->x1, cpIt->y1)) &&
225  transformations[cpIt->image2Nr]->transformImgCoord(pos2, hugin_utils::FDiff2D(cpIt->x2, cpIt->y2)))
226  {
227  if (panoPos1.x <= pos1.x && pos1.x <= panoPos2.x && panoPos1.y <= pos1.y && pos1.y <= panoPos2.y &&
228  panoPos1.x <= pos2.x && pos2.x <= panoPos2.x && panoPos1.y <= pos2.y && pos2.y <= panoPos2.y)
229  {
230  m_CPinROI.insert(cpIt - cps.begin());
231  };
232  };
233  };
234  };
235  for (TransformMap::iterator it = transformations.begin(); it != transformations.end(); ++it)
236  {
237  delete it->second;
238  };
239  };
240 };
241 
242 // return the selected ROI
244 {
245  vigra::Point2D p1;
248  vigra::Point2D p2;
251  return vigra::Rect2D(p1, p2) & vigra::Rect2D(helper->GetPanoramaPtr()->getOptions().getSize());
252 };
253 
254 // for correctly handling the popup menu
255 // when selecting the popup menu or dismiss the popup menu we get an additional mouse
256 // click, we need to ignore this one, this function sets the state back
258 {
259  m_menuPopup = false;
260 };
261 
263 {
266  if (imgs1.empty() || imgs2.empty())
267  {
268  // start or end point are not above any image
269  wxBell();
270  // we need to redraw so that the selection vanishes
273  }
274  else
275  {
276  HuginBase::UIntSet imgIntersection;
277  std::set_intersection(imgs1.begin(), imgs1.end(), imgs2.begin(), imgs2.end(), std::inserter(imgIntersection, imgIntersection.begin()));
280  if (!imgIntersection.empty())
281  {
282  // start and end point are on the same image
283  cp.image1Nr = *imgIntersection.begin();
285  transform.createTransform(pano->getImage(cp.image1Nr), pano->getOptions());
286  double image_x, image_y;
287  transform.transformImgCoord(image_x, image_y, pos1.x, pos1.y);
288  cp.x1 = image_x;
289  cp.y1 = image_y;
290  transform.transformImgCoord(image_x, image_y, pos2.x, pos2.y);
291  cp.image2Nr = cp.image1Nr;
292  cp.x2 = image_x;
293  cp.y2 = image_y;
294  }
295  else
296  {
297  // start and end point are on different images
298  cp.image1Nr = *imgs1.begin();
299  cp.image2Nr = *imgs2.begin();
300 
302  transform.createTransform(pano->getImage(cp.image1Nr), pano->getOptions());
303  double image_x, image_y;
304  transform.transformImgCoord(image_x, image_y, pos1.x, pos1.y);
305  cp.x1 = image_x;
306  cp.y1 = image_y;
307  transform.createTransform(pano->getImage(cp.image2Nr), pano->getOptions());
308  transform.transformImgCoord(image_x, image_y, pos2.x, pos2.y);
309  cp.x2 = image_x;
310  cp.y2 = image_y;
311  }
312  if (abs(pos1.x - pos2.x) < abs(pos1.y - pos2.y))
313  {
315  }
316  else
317  {
319  };
321  }
322 }
void Activate() override
activate the tool
void ReallyAfterDrawImagesEvent() override
draw selection rectangle
implementation of huginApp Class
hugin_utils::FDiff2D GetMousePanoPosition()
Definition: ToolHelper.cpp:296
void Deactivate() override
deactivate the tool, reset the cursor
HuginBase::Panorama * GetPanoramaPtr()
Definition: ToolHelper.cpp:311
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
include file for the hugin project
void SetMenuProcessed()
reset popup menu status
void ForceRequireRedraw()
Definition: ViewState.cpp:439
void NotifyMe(Event event, Tool *tool)
Definition: ToolHelper.cpp:316
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
hugin_utils::FDiff2D m_currentPosScreen
current position of selection in screen coordinates
add a control point
Definition: PanoCommand.h:268
represents a control point
Definition: ControlPoint.h:38
void AddLineCP(const hugin_utils::FDiff2D &pos1, const hugin_utils::FDiff2D &pos2)
called to add line control point
VisualizationState * GetVisualizationStatePtr()
Definition: ToolHelper.cpp:301
hugin_utils::FDiff2D GetMouseScreenPosition()
Definition: ToolHelper.cpp:291
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
ToolHelper * helper
The PreviewToolHelper that uses the same preview window and panorama as the tool should.
Definition: Tool.h:104
Model for a panorama.
Definition: Panorama.h:152
void createInvTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
create image-&gt;pano transformation
hugin_utils::FDiff2D m_currentPos
current position of selection
bool m_line
if selecting a rectangle or a line
wxwindows specific panorama commands
bool m_menuPopup
true, when popup menu is shown, this is to ignore a mouse event when the popup menu is closed ...
evaluate x, points are on a vertical line
Definition: ControlPoint.h:47
static GlobalCmdHist & getInstance()
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
bool m_mouseDown
mouse down status
include file for the hugin project
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
hugin_utils::FDiff2D m_startPos
position where the marking starts
void MouseButtonEvent(wxMouseEvent &e) override
mouse button handling
static T max(T x, T y)
Definition: svm.cpp:65
Holds transformations for Image -&gt; Pano and the other way.
void SetStatusMessage(wxString message)
Definition: ToolHelper.cpp:410
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
interface of ToolHelper for deleting control points in the pano space
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
GLPreview * getPreview()
HuginBase::UIntSet m_CPinROI
contains the found cp
void MouseMoveEvent(double x, double y, wxMouseEvent &e) override
mouse move handling
vigra::Size2D getSize() const
get size of output image
void FindCPInRect(const hugin_utils::FDiff2D &pos1, const hugin_utils::FDiff2D &pos2)
search for control points in selected rectangle
vigra::Rect2D GetSelectedROI()
returns selected ROI
evaluate y, points are on a horizontal line
Definition: ControlPoint.h:48
static T min(T x, T y)
Definition: svm.cpp:62
GLPreviewFrame * GetPreviewFrame()
Definition: ToolHelper.h:139
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
HuginBase::UIntSet GetImagesUnderPos(const hugin_utils::FDiff2D &pos)
Definition: ToolHelper.cpp:122
hugin_utils::FDiff2D m_startPosScreen
position where the marking starts in screen coordinates