Hugin trunk 0.1
Loading...
Searching...
No Matches
DragTool.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
23#include "hugin_config.h"
24#include "panoinc_WX.h"
25#include "panoinc.h"
26
27#include "DragTool.h"
29#include "base_wx/PanoCommand.h"
31
32#include <math.h>
33#include <wx/platform.h>
34#ifdef __WXMAC__
35#include <OpenGL/gl.h>
36#else
37#include <GL/gl.h>
38#endif
39
40#include "GLPreviewFrame.h"
41
43 : Tool(helper), drag_mode(drag_mode_normal)
44{
45}
46
51
56
57//find Tr parameters shift based on polar coordinates
67
68
70{
71 drag_yaw = false; drag_pitch = false; drag_roll = false;
72 shift = false; control = false;
73 // register notifications
77 // a handy message for the user:
78 helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or Ctrl-drag"));
79}
80
81void DragTool::MouseMoveEvent(double x, double y, wxMouseEvent & e)
82{
84 x = pos.x;
85 y = pos.y;
87 {
88
89
90 // how far are we moving?
91 if (drag_yaw || drag_pitch)
92 {
93
94 double yaw, pitch;
96 pitch, x, y);
97 shift_coordinates.x = yaw;
98 shift_coordinates.y = pitch;
99 shift = e.m_shiftDown;
100 if (shift)
101 {
102 if (std::abs(shift_coordinates.x - start_coordinates.x)
104 {
106 helper->SetStatusMessage(_("Currently constrained to moving only pitch. Make a larger movement in the opposite direction to constrain to yaw."));
107
108 } else {
110 helper->SetStatusMessage(_("Currently constrained to moving only yaw. Make a larger movement in the opposite direction to constrain to pitch."));
111 }
112 }
113
114 }
115 if (drag_roll)
116 {
118 }
119
120 // move the selected images on the tempory copies for display.
121 // first calculate a matrix representing the transformation
123 //if in mosaic drag mode do not adjust yaw and pitch, just roll
124 SetRotationMatrix(0,0,shift_angle, 0,0,0);
125 } else {
128 }
129
130 std::map<unsigned int, ParamStore>::iterator i;
131 for (i = image_params.begin(); i != image_params.end(); ++i )
132 {
134 GetSrcImage(i->first);
136
138 //if in mosaic mode shift TrX and TrY parameters based on modified yaw and pitch
139 double shift_x, shift_y;
141 i->second.TrX = img.getX() + shift_x;
142 i->second.TrY = img.getY() + shift_y;
143 }
145 img.setX(new_TrX);
146 img.setY(new_TrY);
147 img.setZ(new_TrZ);
148 img.setTranslationPlaneYaw(new_Tpy);
149 img.setTranslationPlanePitch(new_Tpp);
150 img.setYaw(new_yaw);
151 img.setPitch(new_pitch);
152 img.setRoll(new_roll);
153 helper->GetViewStatePtr()->SetSrcImage(i->first, &img);
154 }
155
156 // redraw
158 }
159}
160
162{
163 if (e.ButtonDown())
164 {
165
166 if (helper->IsMouseOverPano()) {
167
168 control = e.m_controlDown;
169 shift = e.m_shiftDown;
170
172
173 std::set<unsigned int> images_under_mouse = helper->GetImageNumbersUnderMouse();
174 std::set<unsigned int>::iterator it;
175 for(it = images_under_mouse.begin() ; it != images_under_mouse.end() ; ++it) {
176 if (shift) {
178 } else {
180 }
181 }
182 return;
183
184 }
185
186 switch (e.GetButton())
187 {
188 // primary button
189 case wxMOUSE_BTN_LEFT:
190 // different things depending on modifier keys.
191
192 // Either no key modifiers we care about, or shift.
193 // With shift we determine an adaptive constraint based on
194 // movement in both directions.
195 drag_yaw = true; drag_pitch = true;
196 break;
198 drag_roll = true;
199 break;
200 }
201 if (drag_roll)
202 {
203 // set centre and angle
205 centre.x, centre.y, 0.0, 0.0);
206 centre.x += 0.5;
207 centre.y += 0.5;
210 shift_angle = 0.0;
211 // we'll always rotate around the centre of the panorama.
214 helper->SetStatusMessage(_("Rotate around the centre to roll"));
215 }
216 if (drag_yaw || drag_pitch)
217 {
218 // We want to keep the point under the mouse pointer now under there
219 // wherever it goes. We'll calculate the roll, pitch, and yaw
220 // required to bring the centre to the point under the mouse. Then
221 // we rotate the panorama's images using the yaw and pitch of the
222 // movement. (Rotate start point to the centre, rotate by difference
223 // in yaw and pitch gained so far while dragging, then do the
224 // inverse of the rotation from start point to the centre on the
225 // result.
226 // set angles
227 double yaw, pitch;
230 pitch, mouse_pos.x, mouse_pos.y);
231 start_coordinates.x = yaw; start_coordinates.y = pitch;
232 shift_coordinates.x = yaw; shift_coordinates.y = pitch;
233 // provide a helpfull message to the user via the staus bar.
234 if (shift) {
235 helper->SetStatusMessage(_("Constrained drag: make a movement and it will be snapped to the yaw or pitch"));
236 } else {
237 helper->SetStatusMessage(_("Drag to move"));
238 }
239 }
240 if (drag_roll || drag_yaw || drag_pitch)
241 {
242 shift_angle = 0.0;
243 // record where the images are so we know what the difference is.
244 // Use the component the mouse points to instead of every image.
245 // Find the components
246
247 /*
248 TODO: depending on state from the preview frame is not nice.
249 but this cannot be avoided in this case as the drag tool must depend on a central state,
250 which in this case is neither provided by the possibility of a central (parent) DragTool
251 nor a parent ToolHelper.
252 This is also the case for the identify tools, which inorder to interact with eachother
253 must rely on a central tool.
254 So the code at some point need to be refactored to provide central tool helper
255 and central tools, similarly as the ViewState is now central
256 compared to the VisualizationState which is specific to each visualization.
257 */
259 if (customDragging) {
261 std::set<unsigned int>::iterator i, end;
262 end = draging_images.end();
263 for (i = draging_images.begin(); i != end; ++i)
264 {
265 image_params[*i].Set(
267 }
268
269 } else {
270
271
274 const size_t n = components.size();
275 // If there is only component, we can drag everything. Otherwise the
276 // component we want is the lowest numbered image under the mouse.
277 if (n == 1)
278 {
279 unsigned int imgs = helper->GetPanoramaPtr()->getNrOfImages();
280 draging_images.clear();
281 fill_set(draging_images, 0, imgs - 1);
282
284 for (unsigned int i = 0; i < imgs; i++)
285 {
286 image_params[i].Set(view_state_ptr->GetSrcImage(i));
287 };
288 } else
289 {
290 // multiple components or none at all.
291 if (n == 0 || helper->GetImageNumbersUnderMouse().empty())
292 {
293 // we can't drag nothing.
294 drag_roll = false; drag_yaw = false; drag_pitch = false;
295 return;
296 }
297
298 // Find the component containing the topmost image under mouse
299 unsigned int img = *helper->GetImageNumbersUnderMouse().begin();
300 for (size_t component_index = 0;
302 {
303 if (components[component_index].count(img))
304 {
305 // Found it, record which images and where they are.
307 std::set<unsigned int>::iterator i, end;
308 end = draging_images.end();
309 for (i = draging_images.begin(); i != end; ++i)
310 {
311 image_params[*i].Set(
313 }
314 break;
315 }
316 }
317 }
318 }
322 }
323 }
324 } else {
325 // check this wasn't an attempt to drag empty space.
326 if (! (drag_pitch || drag_roll || drag_yaw)) return;
327
328 // Finished draging images:
329 drag_yaw = false; drag_pitch = false; drag_roll = false;
330 // Apply the rotations permanently.
331 // find where the images end up.
332 std::vector<HuginBase::SrcPanoImage> src_images(draging_images.size() + 1);
333 std::map<unsigned int, ParamStore>::iterator i;
334 unsigned int count = 0;
335 for (i = image_params.begin(); i != image_params.end(); ++i)
336 {
337 double nyaw, npitch, nroll, nx, ny, nz, npy, npp;
338 i->second.Move(&rotation_matrix, nyaw, npitch, nroll, nx, ny, nz, npy, npp);
339 src_images[count] = helper->GetPanoramaPtr()->getSrcImage(i->first);
340 src_images[count].setX(nx);
341 src_images[count].setY(ny);
342 src_images[count].setZ(nz);
343 src_images[count].setTranslationPlaneYaw(npy);
344 src_images[count].setTranslationPlanePitch(npp);
345 src_images[count].setYaw(nyaw);
346 src_images[count].setPitch(npitch);
347 src_images[count].setRoll(nroll);
348 count++;
349 }
354 );
355 // stop dragging
356 image_params.clear();
357
358 helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or Ctrl-drag"));
359 }
360}
361
362
363
365{
366 yaw = img->getYaw();
367 pitch = img->getPitch();
368 roll = img->getRoll();
369 TrX = img->getX();
370 TrY = img->getY();
371 TrZ = img->getZ();
372 Tpy = img->getTranslationPlaneYaw();
373 Tpp = img->getTranslationPlanePitch();
374}
375
377 double &yaw_out, double &pitch_out, double &roll_out,
378 double &TrX_out, double &TrY_out, double &TrZ_out,
379 double &Tpy_out, double &Tpp_out)
380{
381 Matrix3 start, output_matrix;
382 // convert the location of this image to a matrix.
383 start.SetRotationPT(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), DEG_TO_RAD(roll));
384 // move it by the matrix specified.
385 output_matrix = *matrix * start;
386 // get the angles from the matrix
391
392 if(TrX != 0.0 || TrY != 0.0 || TrZ != 0.0)
393 {
394 // rotate translation vector
395 Vector3 vecRot=matrix->Inverse().TransformVector(Vector3(TrZ, TrX, TrY));
397 TrY_out=vecRot.z;
398 TrZ_out=vecRot.x;
399 // rotate translation plane
400 start.SetRotationPT(DEG_TO_RAD(Tpy), DEG_TO_RAD(Tpp), 0.0);
401 output_matrix = (*matrix) * start;
402 double dummy;
406 }
407 else
408 {
409 TrX_out=0;
410 TrY_out=0;
411 TrZ_out=0;
412 Tpy_out=0;
413 Tpp_out=0;
414 };
415}
416
418 double roll_shift,
419 double yaw_start, double pitch_start,
420 double roll_start)
421{
423 // rotates the start point to the centre
425 p1_mat.SetRotationPT(0.0, DEG_TO_RAD(pitch_start), 0.0);
426 // rolls the image
427 r_mat.SetRotationPT(0.0, 0.0, roll_shift);
428 // rotates the centre to the destination point
429 p2_mat.SetRotationPT(0.0, -DEG_TO_RAD(pitch_shift), 0.0);
430 y2_mat.SetRotationPT(DEG_TO_RAD(yaw_shift), 0.0, 0.0);
431
433}
434
436{
437 // draw guide lines down the middle.
439 double width = (double) opts->getSize().width(),
440 height = (double) opts->getSize().height();
441 // Invert the color underneath.
445 glColor3f(1.0, 1.0, 1.0);
446 glPushMatrix();
447 glTranslatef(-0.5, -0.5, -0.5);
449 glVertex2f(width / 2.0, 0.0);
450 glVertex2f(width / 2.0, height);
451 glVertex2f(0.0, height / 2.0);
452 glVertex2f(width, height / 2.0);
453 glEnd();
454 // draw lines if we are dragging
455 if (drag_roll)
456 {
457 // when rolling, a line from the centre (where we rotate around) in the
458 // direction of the mouse pointer should help the user.
459 double distance = width * width + height * height,
461 glPushMatrix();
464 // starting angle
465 glVertex2d(0.0, 0.0);
466 glVertex2f(distance * cos(angle), distance * sin(angle));
467 // angle now used
469 glVertex2d(0.0, 0.0);
470 glVertex2f(distance * cos(angle), distance * sin(angle));
471 glEnd();
472 glPopMatrix();
473 }
474 if (drag_pitch || drag_yaw)
475 {
476 // Draw a straight line in the spherical space, from the start point to
477 // under the mouse. It only appears straight when using a cylinderical
478 // projection or similar though, so we draw it as many line segments.
480 for (double t = 0.0; t <= 1.0; t+= 0.005)
481 {
482 double x, y, ti = 1.0 - t;
484 x, y,
487 glVertex2d(x, y);
488 }
489 glEnd();
490 }
491 glPopMatrix();
494}
495
500
void Set(HuginBase::SrcPanoImage *img)
Definition DragTool.cpp:364
void Move(Matrix3 *matrix, double &yaw_out, double &pitch_out, double &roll_out, double &TrX_out, double &TrY_out, double &TrZ_out, double &Tpy_out, double &Tpp_out)
Definition DragTool.cpp:376
Matrix3 rotation_matrix
Definition DragTool.h:87
double shift_angle
Definition DragTool.h:84
bool control
Definition DragTool.h:86
bool drag_roll
Definition DragTool.h:83
@ drag_mode_mosaic
Definition DragTool.h:73
void MouseMoveEvent(double x, double y, wxMouseEvent &e)
Notify when the mouse pointer has moved over the panorama preview.
Definition DragTool.cpp:81
void Activate()
Switch on a tool.
Definition DragTool.cpp:69
std::map< unsigned int, ParamStore > image_params
Definition DragTool.h:81
bool shift
Definition DragTool.h:86
void setDragMode(DragMode drag_mode)
Definition DragTool.cpp:47
hugin_utils::FDiff2D start_coordinates
Definition DragTool.h:85
void MouseButtonEvent(wxMouseEvent &e)
Notify of a mouse button press on the panorama preview.
Definition DragTool.cpp:161
DragTool(ToolHelper *helper)
Definition DragTool.cpp:42
hugin_utils::FDiff2D shift_coordinates
Definition DragTool.h:85
DragMode drag_mode
Definition DragTool.h:92
hugin_utils::FDiff2D centre
Definition DragTool.h:85
bool drag_pitch
Definition DragTool.h:83
DragMode getDragMode()
Definition DragTool.cpp:52
double start_angle
Definition DragTool.h:84
void SetRotationMatrix(double yaw_shift, double pitch_shift, double roll_shift, double yaw_start, double pitch_start, double roll_start)
Definition DragTool.cpp:417
void getTranslationShift(double &delta_x, double &delta_y)
Definition DragTool.cpp:58
std::set< unsigned int > draging_images
Definition DragTool.h:82
bool drag_yaw
Definition DragTool.h:83
HuginBase::UIntSet GetDragGroupImages()
void RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box=true)
void AddImageToDragGroup(unsigned int image_nr, bool update_check_box=true)
Panorama image options.
vigra::Size2D getSize() const
get size of output image
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition ImageGraph.h:45
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
Definition ImageGraph.h:50
general : Matrix3 is a class for handling 3x3 Matrix manipulation.
Definition Matrix3.h:38
void SetRotationPT(double yaw, double pitch, double roll)
set rotation in panotools style, code adapted from Panotools-Script by Bruno Postle
Definition Matrix3.cpp:110
void GetRotationPT(double &Yaw, double &Pitch, double &Roll)
GetRotation in panotools style.
Definition Matrix3.cpp:157
bool AngularToImage(double &image_x, double &image_y, double yaw, double pitch)
bool ImageToAngular(double &yaw, double &pitch, double image_x, double image_y)
void ReallyAfterDrawImagesEvent()
Draw (using OpenGL) the overlays, e.g. crop highlights, guides.
Definition DragTool.cpp:496
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
static GlobalCmdHist & getInstance()
void ReallyAfterDrawImagesEvent()
Draw (using OpenGL) the overlays, e.g. crop highlights, guides.
Definition DragTool.cpp:435
void DisableTexture(bool maskOnly=false)
hugin_utils::FDiff2D GetMousePanoPosition()
GLPreviewFrame * GetPreviewFrame()
Definition ToolHelper.h:139
bool IsMouseOverPano()
Definition ToolHelper.h:136
HuginBase::Panorama * GetPanoramaPtr()
void NotifyMe(Event event, Tool *tool)
ViewState * GetViewStatePtr()
VisualizationState * GetVisualizationStatePtr()
std::set< unsigned int > GetImageNumbersUnderMouse()
@ REALLY_DRAW_OVER_IMAGES
Definition ToolHelper.h:83
void SetStatusMessage(wxString message)
Definition Tool.h:43
ToolHelper * helper
The PreviewToolHelper that uses the same preview window and panorama as the tool should.
Definition Tool.h:109
general : Vector3 is a class for handling 3D Vectors manipulation.
Definition Vector3.h:44
double y
Definition Vector3.h:47
void SetSrcImage(unsigned int image_nr, HuginBase::SrcPanoImage *new_img)
OutputProjectionInfo * GetProjectionInfo()
HuginBase::PanoramaOptions * GetOptions()
HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
TextureManager * GetTextureManager()
Definition ViewState.h:104
virtual OutputProjectionInfo * GetProjectionInfo()
implementation of huginApp Class
#define RAD_TO_DEG(x)
Definition hugin_math.h:45
#define DEG_TO_RAD(x)
Definition hugin_math.h:44
include file for the hugin project
include file for the hugin project
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition stl_utils.h:81
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41