Hugin trunk 0.1
Loading...
Searching...
No Matches
ToolHelper.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
25#ifdef _WIN32
26#include "wx/msw/wrapwin.h"
27#endif
28#include "ToolHelper.h"
29#include "Tool.h"
30#include "GLPreviewFrame.h"
31#include "GLViewer.h"
32#include "MeshManager.h"
33
48
52
54{
55 tools_deactivated.clear();
56 tool->Activate();
57 return tools_deactivated;
58}
59
75
76void ToolHelper::MouseMoved(int x, int y, wxMouseEvent & e)
77{
80 // now tell tools that want notification.
82 {
83 tool->MouseMoveEvent(mouse_screen_x, mouse_screen_y, e);
84 }
85 // If the mouse has moved, then we don't know what is underneath it anoymore
87}
88
90{
92 // if there are tools that want to know when the images under the mouse
93 // pointer change, we better detect the images and notfiy them is applicable
95 {
96 // there are tools that want to know... so find out:
97 std::set<unsigned int> old_images_under_mouse = images_under_mouse;
100 {
101 // The list has changed. Notifiy all tools that requested it.
103 {
104 tool->ImagesUnderMouseChangedEvent();
105 }
106 }
107 }
108}
109
111{
112 // We want to find out which images cover the point underneath the mouse
113 // pointer.
114 images_under_mouse.clear();
115 if (IsMouseOverPano())
116 {
118 };
120}
121
123{
125 const unsigned int num_images = pano->getNrOfImages();
127 for (unsigned int image_index = 0; image_index < num_images; image_index++)
128 {
129 // don't try any images that are turned off
131 {
132 // work out if the image covers the point under the mouse.
136 double image_x, image_y;
137 transform.transformImgCoord(image_x, image_y, pos.x, pos.y);
139 int(image_x), int(image_y))))
140 {
141 // this image is under the position, add it to the set.
142 imgUnderPos.insert(image_index);
143 };
144 };
145 };
146 return imgUnderPos;
147}
148
150{
152 {
153 tool->MouseButtonEvent(e);
154 }
155}
156
158{
159 for (auto& tool : mouse_wheel_notified_tools)
160 {
161 tool->MouseWheelEvent(e);
162 }
163}
164
165
167{
168 for (auto& tool : keypress_notified_tools)
169 {
170 tool->KeypressEvent(keycode, modifiers, pressed);
171 }
172}
173
175{
176 // let all tools that want to draw under the images do so.
177 for (auto& tool : draw_under_notified_tools)
178 {
179 tool->BeforeDrawImagesEvent();
180 }
181 // Since we are drawing a new frame, lets assume something has changed,
182 // however we want to keep with no images under the mouse if the mouse is
183 // not on the panorama.
184 if (mouse_over_pano)
185 {
187 }
188}
189
191{
192 // let all tools that want to draw on top of the images do so.
193 for (auto& tool : draw_over_notified_tools)
194 {
195 tool->AfterDrawImagesEvent();
196 }
197 // The overlays are done separetly to avoid errors with blending order.
199 {
200 tool->ReallyAfterDrawImagesEvent();
201 }
202}
203
205{
206 // let all tools that want to draw on top of the images do so.
207 for (auto& tool : m_tools_need_dirty_flag)
208 {
209 tool->MarkDirty();
210 }
211}
212
213bool ToolHelper::BeforeDrawImageNumber(unsigned int image)
214{
215 if (image_draw_begin_tools.size() > image)
216 {
217 if (!image_draw_begin_tools[image].empty())
218 {
219 bool result = true;
220 // BeforeDrawImageEvent can change image_draw_begin_tools[image]
221 // so we create a copy before to process all dependent tools, also
222 // when the set is modified in the BeforeDrawImageEvent function
223 const auto tools = image_draw_begin_tools[image];
224 for (auto tool : tools)
225 {
226 result &= tool->BeforeDrawImageEvent(image);
227 };
228 return result;
229 }
230 }
231 return true;
232}
233
234void ToolHelper::AfterDrawImageNumber(unsigned int image)
235{
236 if (image_draw_end_tools.size() > image)
237 {
238 if (!image_draw_end_tools[image].empty())
239 {
240 const auto tools = image_draw_end_tools[image];
241 for (auto tool : tools)
242 {
243 tool->BeforeDrawImageEvent(image);
244 }
245 }
246 }
247}
248
250{
251 // You might expect that this is redundant, because any MouseEnter will be
252 // accompanied by a MouseMove, which will achieve the same ends. However,
253 // this is not so. It's possible for the mouse to enter without moving.
254 // Morevover, some environments will trigger a MouseLeave+MouseEnter just
255 // before a MouseButton event; handling this is particularly critical for
256 // such cases.
257 mouse_over_pano = true;
258 mouse_screen_x = x;
259 mouse_screen_y = y;
260 // If the mouse has moved, then we don't know what is underneath it anoymore
262}
263
265{
266 // if the mouse leaves the preview, there are no images under the mouse
267 // pointer anymore.
268 mouse_over_pano = false;
269 images_under_mouse.clear();
272 {
273 // notify tools that the set has changed.
275 {
276 tool->ImagesUnderMouseChangedEvent();
277 }
278 }
279}
280
281
283{
285 {
287 }
288 return images_under_mouse;
289}
290
295
300
305
310
315
317{
318 switch (event)
319 {
320 case MOUSE_MOVE:
322 break;
323 case MOUSE_PRESS:
325 break;
326 case MOUSE_WHEEL:
328 break;
329 case KEY_PRESS:
331 break;
334 break;
335 case DRAW_OVER_IMAGES:
337 break;
340 break;
343 break;
344 case MARK_DIRTY:
346 break;
347 }
348}
349
355
361
363{
364 // TODO we should probably check that the tools have the notification they
365 // are trying to give up, as misbehaving tools could break another tool.
366 switch (event)
367 {
368 case MOUSE_MOVE:
370 break;
371 case MOUSE_PRESS:
373 break;
374 case MOUSE_WHEEL:
376 break;
377 case KEY_PRESS:
379 break;
382 break;
383 case DRAW_OVER_IMAGES:
385 break;
388 break;
391 break;
392 case MARK_DIRTY:
394 break;
395 }
396}
397
403
409
411{
412 // get the GLPreviewFrame to set its status bar's text.
414}
415
416
417// These functions remove tools from various things that keep pointers to them
418// so that they can be notified. They are called when we don't want to notify
419// them anymore.
420
422{
423 if (*single == tool)
424 {
425 *single = 0;
426 }
427}
428
430 std::set<Tool *> *set)
431{
432 auto foundTool = set->find(tool);
433 if (foundTool != set->end())
434 {
435 set->erase(foundTool);
436 }
437}
438
440 std::vector<std::set<Tool *> > *vector)
441{
442 // check every item for presence.
443 for (unsigned int image = 0; image < vector->size(); image++)
444 {
445 (*vector)[image].erase(tool);
446 }
447}
448
450 std::vector<std::set<Tool *> > *vector,
451 unsigned int index)
452{
453 if (vector->size() > index)
454 {
455 (*vector)[index].erase(tool);
456 }
457}
458
460{
461 if (*single != 0 || *single == tool)
462 {
464 }
465 *single = tool;
466}
467
468void ToolHelper::AddTool(Tool *tool, std::set<Tool *> *set)
469{
470 set->insert(tool);
471}
472
474 std::vector<std::set<Tool *> > *vector,
475 unsigned int index)
476{
477 if (vector->size() < index + 1)
478 {
479 // increase the size of the vector to handle enough elements for index
480 // to exist
481 vector->resize(index + 1, std::set<Tool*>());
482 }
483// else if ((*vector)[index] && (*vector)[index] != tool)
484// {
485// // if a different tool already was doing this, deactivate it.
486// DeactivateTool((*vector)[index]);
487// };
488// (*vector)[index] = tool;
489 (*vector)[index].insert(tool);
490}
491
492
494{
495 mouse_over_pano = true;
496 mouse_screen_x = x;
497 mouse_screen_y = y;
498 // work out where the pointer is in the panorama.
499 vigra::Rect2D visible = visualization_state->GetVisibleArea();
502 // now tell tools that want notification.
503 for (auto& tool : mouse_move_notified_tools)
504 {
505 tool->MouseMoveEvent(mouse_pano_x, mouse_pano_y, e);
506 }
507 // If the mouse has moved, then we don't know what is underneath it anoymore
509}
510
512{
514
515 double d = panostate->getR();
516 double r = panostate->getSphereRadius();
517
518 int tcanv_w, tcanv_h;
519 panostate->GetViewer()->GetClientSize(&tcanv_w,&tcanv_h);
520
521 double canv_w, canv_h;
522 canv_w = tcanv_w;
523 canv_h = tcanv_h;
524
525 const double fov = panostate->getFOV();
526 double fovScale = 1.0;
527
528 double fovy, fovx;
529 if (canv_w > canv_h)
530 {
531 fovy = DEG_TO_RAD(fov);
532 fovx = 2 * atan(tan(fovy / 2.0) * canv_w / canv_h);
533 fovScale = tan(fovy / 2.0) / (0.5 * canv_h);
534 }
535 else
536 {
537 fovx = DEG_TO_RAD(fov);
538 fovy = 2 * atan(tan(fovx / 2.0) * canv_h / canv_w);
539 fovScale = tan(fovx / 2.0) / (0.5 * canv_w);
540 };
541
542 if (panostate->isInsideView())
543 {
544 // we are looking from inside, mouse is always about the panosphere
545 mouse_over_pano = true;
546 const double xSrc = (x - canv_w / 2.0) * fovScale;
547 const double ySrc = (canv_h / 2.0 - y) * fovScale;
548 const double yaw = atan(xSrc) + panostate->getAngX() + M_PI / 2.0;
549 const double pitch = M_PI/2.0 - atan2(ySrc, std::sqrt(1.0 + xSrc * xSrc)) - panostate->getAngY();
550 //if (yaw < 0) yaw += 2 * M_PI;
551 //if (yaw > 2 * M_PI) yaw -= 2 * M_PI;
552 mouse_pano_x = yaw / (2 * M_PI) * panostate->GetOptions()->getWidth();
553 mouse_pano_y = pitch / (M_PI)*panostate->GetOptions()->getHeight();
554 }
555 else
556 {
557 // we are looking from outside, more calculation to find position needed
558 const double ax = tan(fovx / 2.0) * d * (x / (canv_w / 2.0) - 1);
559 const double ay = tan(fovy / 2.0) * d * (y / (canv_h / 2.0) - 1);
560
561 const double a_limit = r * d / sqrt(d * d - r * r);
562
563 if (ax * ax + ay * ay < a_limit * a_limit)
564 {
565 mouse_over_pano = true;
566
567 const double ta = (ax * ax + ay * ay) / (d * d) + 1;
568 const double tb = -2 * (ax * ax + ay * ay) / d;
569 const double tc = ax * ax + ay * ay - r * r;
570
571 const double pz = (-tb + sqrt(tb * tb - 4 * ta * tc)) / (2 * ta);
572 const double px = ax * (d - pz) / d;
573 const double py = ay * (d - pz) / d;
574
575 const double pl = sqrt(px * px + py * py + pz * pz);
576
577 const double pang_yaw = -atan(px / pz);
578 const double pang_pitch = asin(py / pl);
579
580 const double ang_yaw = panostate->getAngX();
581 const double ang_pitch = panostate->getAngY();
582
583 const double x = sin(ang_yaw) * cos(ang_pitch);
584 const double z = cos(ang_yaw) * cos(ang_pitch);
585 const double y = sin(ang_pitch);
586
587 const Vector3 vec(x, y, z);
588
589 const Vector3 top(0, 1, 0);
590
591 const Vector3 ptop = vec.Cross(top).Cross(vec).GetNormalized();
592
594 tres.x = ptop.x * (ptop.x * vec.x + ptop.y * vec.y + ptop.z * vec.z) + cos(pang_yaw) * (ptop.x * (-ptop.y * vec.y - ptop.z * vec.z) + vec.x * (ptop.y * ptop.y + ptop.z * ptop.z)) + sin(pang_yaw) * (-ptop.z * vec.y + ptop.y * vec.z);
595 tres.y = ptop.y * (ptop.x * vec.x + ptop.y * vec.y + ptop.z * vec.z) + cos(pang_yaw) * (ptop.y * (-ptop.x * vec.x - ptop.z * vec.z) + vec.y * (ptop.x * ptop.x + ptop.z * ptop.z)) + sin(pang_yaw) * (-ptop.z * vec.x + ptop.x * vec.z);
596 tres.z = ptop.z * (ptop.x * vec.x + ptop.y * vec.y + ptop.z * vec.z) + cos(pang_yaw) * (ptop.z * (-ptop.x * vec.x - ptop.y * vec.y) + vec.z * (ptop.x * ptop.x + ptop.y * ptop.y)) + sin(pang_yaw) * (-ptop.y * vec.x + ptop.x * vec.y);
597
599 Vector3 res;
600
601 res.x = pside.x * (pside.x * tres.x + pside.y * tres.y + pside.z * tres.z) + cos(pang_pitch) * (pside.x * (-pside.y * tres.y - pside.z * tres.z) + tres.x * (pside.y * pside.y + pside.z * pside.z)) + sin(pang_pitch) * (-pside.z * tres.y + pside.y * tres.z);
602 res.y = pside.y * (pside.x * tres.x + pside.y * tres.y + pside.z * tres.z) + cos(pang_pitch) * (pside.y * (-pside.x * tres.x - pside.z * tres.z) + tres.y * (pside.x * pside.x + pside.z * pside.z)) + sin(-pang_pitch) * (-pside.z * tres.x + pside.x * tres.z);
603 res.z = pside.z * (pside.x * tres.x + pside.y * tres.y + pside.z * tres.z) + cos(pang_pitch) * (pside.z * (-pside.x * tres.x - pside.y * tres.y) + tres.z * (pside.x * pside.x + pside.y * pside.y)) + sin(pang_pitch) * (-pside.y * tres.x + pside.x * tres.y);
604
605 double yaw, pitch;
606 pitch = asin(res.y);
607 yaw = atan2(res.x, res.z);
608
609 yaw += M_PI / 2.0;
610 if (yaw < 0) yaw += 2 * M_PI;
611 if (yaw > 2 * M_PI) yaw -= 2 * M_PI;
612
613 pitch += M_PI / 2.0;
614 pitch = M_PI - pitch;
615
616 mouse_pano_x = yaw / (2 * M_PI) * panostate->GetOptions()->getWidth();
617 mouse_pano_y = pitch / (M_PI)*panostate->GetOptions()->getHeight();
618
620 // cerr << "mouse " << mouse_pano_x << " " << mouse_pano_y << " ; " << canv_w << " " << canv_h);
621 // double t_mouse_pano_x = yaw M
622 }
623 else
624 {
625 mouse_over_pano = false;
626 };
627 };
628
630}
631
633 VisualizationState *visualization_state,
634 GLPreviewFrame * frame) : OverviewToolHelper(pano, visualization_state, frame) {}
635
637
654
671
673{
675 {
676 static_cast<PanosphereOverviewTool*>(tool)->BeforeDrawImagesBackEvent();
677 }
678}
679
681{
683 {
684 static_cast<PanosphereOverviewTool*>(tool)->BeforeDrawImagesFrontEvent();
685 }
686}
687
689{
691 {
692 static_cast<PanosphereOverviewTool*>(tool)->AfterDrawImagesBackEvent();
693 }
694}
695
697{
699 {
700 static_cast<PanosphereOverviewTool*>(tool)->AfterDrawImagesFrontEvent();
701 }
702}
703
713
714
716 VisualizationState *visualization_state,
717 GLPreviewFrame * frame) : OverviewToolHelper(pano, visualization_state, frame) {}
718
720
722{
723
725
726 double d = panostate->getR();
727
728 int tcanv_w, tcanv_h;
729 panostate->GetViewer()->GetClientSize(&tcanv_w,&tcanv_h);
730
731 double canv_w, canv_h;
732 canv_w = tcanv_w;
733 canv_h = tcanv_h;
734
735 double fov = panostate->getFOV();
736
737 double fovy, fovx;
738 if (canv_w > canv_h) {
739 fovy = DEG_TO_RAD(fov);
740 fovx = 2 * atan( tan(fovy / 2.0) * canv_w / canv_h);
741 } else {
742 fovx = DEG_TO_RAD(fov);
743 fovy = 2 * atan( tan(fovx / 2.0) * canv_h / canv_w);
744 }
745
746 double vis_w, vis_h;
747 vis_w = 2.0 * tan ( fovx / 2.0 ) * d;
748 vis_h = 2.0 * tan ( fovy / 2.0 ) * d;
749
750 //position of the mouse on the z=0 plane
751 double prim_x, prim_y;
752 prim_x = (double) x / canv_w * vis_w - vis_w / 2.0 + panostate->getX();
753 prim_y = ((double) y / canv_h * vis_h - vis_h / 2.0 - panostate->getY());
754
755// std::cout << "mouse ov" << plane_x << " " << plane_y << std::endl;
756 plane_x = prim_x;
757 plane_y = prim_y;
758
759 double width, height;
760 HuginBase::PanoramaOptions * opts = panostate->GetOptions();
761 width = opts->getWidth();
762 height = opts->getHeight();
763
766
767// std::cout << "plane mouse " << mouse_pano_x << " " << mouse_pano_y << " ; " << prim_x << " " << prim_y << " ; " << width << " " << height << std::endl;
768// cerr << "plane mouse " << mouse_pano_x << " " << mouse_pano_y);
769
770 mouse_over_pano = true;
771
773}
774
775
776
#define M_PI
The OpenGL preview frame.
void SetStatusMessage(wxString message)
Holds transformations for Image -> Pano and the other way.
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
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->image transformation
Panorama image options.
unsigned int getWidth() const
unsigned int getHeight() const
get panorama height
Model for a panorama.
Definition Panorama.h:153
UIntSet getActiveImages() const
get active images
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
bool isInside(vigra::Point2D p, bool ignoreMasks=false) const
check if a coordinate is inside the source image
std::set< Tool * > draw_under_notified_tools_back
Definition ToolHelper.h:231
std::set< Tool * > draw_over_notified_tools_back
Definition ToolHelper.h:233
PanosphereOverviewToolHelper(HuginBase::Panorama *pano, VisualizationState *visualization_state, GLPreviewFrame *frame)
std::set< Tool * > draw_over_notified_tools_front
Definition ToolHelper.h:234
std::set< Tool * > draw_under_notified_tools_front
Definition ToolHelper.h:232
void NotifyMe(PanosphereOverviewEvent event, PanosphereOverviewTool *tool)
void DeactivateTool(Tool *tool)
void MouseMoved(int x, int y, wxMouseEvent &e)
void DoNotNotifyMe(PanosphereOverviewEvent event, PanosphereOverviewTool *tool)
void MouseMoved(int x, int y, wxMouseEvent &e)
PlaneOverviewToolHelper(HuginBase::Panorama *pano, VisualizationState *visualization_state, GLPreviewFrame *frame)
void MouseMoved(int x, int y, wxMouseEvent &e)
double mouse_pano_x
Definition ToolHelper.h:148
void DoNotNotifyMeAfterDrawing(unsigned int image_nr, Tool *tool)
hugin_utils::FDiff2D GetMousePanoPosition()
void InvalidateImagesUnderMouse()
void NotifyMeAfterDrawing(unsigned int image_nr, Tool *tool)
bool IsMouseOverPano()
Definition ToolHelper.h:136
void KeypressEvent(int keycode, int modifiers, bool pressed)
std::set< unsigned int > images_under_mouse
Definition ToolHelper.h:178
void UpdateImagesUnderMouse()
void MouseEnter(int x, int y, wxMouseEvent &e)
std::vector< std::set< Tool * > > image_draw_begin_tools
Definition ToolHelper.h:161
HuginBase::Panorama * GetPanoramaPtr()
void NotifyMe(Event event, Tool *tool)
std::set< Tool * > ActivateTool(Tool *tool)
std::set< Tool * > keypress_notified_tools
Definition ToolHelper.h:153
std::set< Tool * > mouse_wheel_notified_tools
Definition ToolHelper.h:158
std::set< Tool * > m_tools_need_dirty_flag
Definition ToolHelper.h:159
std::set< Tool * > draw_over_notified_tools
Definition ToolHelper.h:155
bool mouse_over_pano
Definition ToolHelper.h:176
void MouseButtonEvent(wxMouseEvent &e)
GLPreviewFrame * frame
Definition ToolHelper.h:145
bool BeforeDrawImageNumber(unsigned int image)
double mouse_pano_y
Definition ToolHelper.h:148
virtual ~ToolHelper()
std::vector< std::set< Tool * > > image_draw_end_tools
Definition ToolHelper.h:162
HuginBase::UIntSet GetImagesUnderPos(const hugin_utils::FDiff2D &pos)
virtual void DeactivateTool(Tool *tool)
VisualizationState * visualization_state
Definition ToolHelper.h:144
void AddTool(Tool *tool, Tool **single)
ViewState * GetViewStatePtr()
std::set< Tool * > mouse_button_notified_tools
Definition ToolHelper.h:152
double mouse_screen_x
Definition ToolHelper.h:147
virtual void MouseMoved(int x, int y, wxMouseEvent &e)
VisualizationState * GetVisualizationStatePtr()
std::set< Tool * > images_under_mouse_notified_tools
Definition ToolHelper.h:157
void NotifyMeBeforeDrawing(unsigned int image_nr, Tool *tool)
void MouseWheelEvent(wxMouseEvent &e)
std::set< Tool * > really_draw_over_notified_tools
Definition ToolHelper.h:156
std::set< Tool * > mouse_move_notified_tools
Definition ToolHelper.h:151
bool images_under_mouse_current
Definition ToolHelper.h:176
ToolHelper(HuginBase::Panorama *pano, VisualizationState *visualization_state, GLPreviewFrame *frame)
void BeforeDrawImages()
void MouseLeave()
std::set< Tool * > draw_under_notified_tools
Definition ToolHelper.h:154
void DoNotNotifyMe(Event event, Tool *tool)
std::set< unsigned int > GetImageNumbersUnderMouse()
void DoNotNotifyMeBeforeDrawing(unsigned int image_nr, Tool *tool)
hugin_utils::FDiff2D GetMouseScreenPosition()
@ IMAGES_UNDER_MOUSE_CHANGE
Definition ToolHelper.h:83
@ REALLY_DRAW_OVER_IMAGES
Definition ToolHelper.h:83
@ DRAW_UNDER_IMAGES
Definition ToolHelper.h:82
@ DRAW_OVER_IMAGES
Definition ToolHelper.h:82
double mouse_screen_y
Definition ToolHelper.h:147
std::set< Tool * > tools_deactivated
Definition ToolHelper.h:142
void AfterDrawImages()
void AfterDrawImageNumber(unsigned int image)
HuginBase::Panorama * pano
Definition ToolHelper.h:143
void RemoveTool(Tool *tool, Tool **single)
void MarkDirty()
void SetStatusMessage(wxString message)
Definition Tool.h:43
general : Vector3 is a class for handling 3D Vectors manipulation.
Definition Vector3.h:44
double x
x,y,z coordinates, 0 at the initialisation
Definition Vector3.h:47
Vector3 Cross(const Vector3 &v) const
cross product
Definition Vector3.h:163
Vector3 GetNormalized() const
return a normalized vector
Definition Vector3.cpp:95
double z
Definition Vector3.h:47
double y
Definition Vector3.h:47
HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
vigra::Rect2D GetVisibleArea()
Definition ViewState.h:222
virtual HuginBase::PanoramaOptions * GetOptions()
virtual HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
ViewState * getViewState()
Definition ViewState.h:239
#define DEG_TO_RAD(x)
Definition hugin_math.h:44
std::set< unsigned int > UIntSet
TDiff2D< double > FDiff2D
Definition hugin_math.h:162
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition stl_utils.h:74
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