Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GLPreviewFrame.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
26 #include <bitset>
27 #include <limits>
28 #include <iostream>
29 
30 #include "hugin_config.h"
31 
32 #if !defined HAVE_EPOXY || !HAVE_EPOXY
33 #include <GL/glew.h>
34 #endif
35 
36 #include "panoinc_WX.h"
37 #include "panoinc.h"
38 #include <wx/msgdlg.h>
39 
40 #include "base_wx/platform.h"
41 #include "base_wx/wxPlatform.h"
42 #include "base_wx/LensTools.h"
49 
51 #include "base_wx/wxPanoCommand.h"
52 
53 #include "hugin/config_defaults.h"
54 #include "hugin/GLPreviewFrame.h"
55 #include "hugin/huginApp.h"
56 #include "hugin/MainFrame.h"
57 #include "hugin/ImagesPanel.h"
58 #include "base_wx/CommandHistory.h"
59 #include "hugin/GLViewer.h"
61 #include "hugin/PanoOperation.h"
62 #include "hugin/PanoOutputDialog.h"
64 #include "base_wx/PTWXDlg.h"
66 #include "vigra_ext/Correlation.h"
69 
70 extern "C" {
71 #include <pano13/queryfeature.h>
72 }
73 
74 #include "ToolHelper.h"
75 #include "Tool.h"
76 #include "DragTool.h"
77 #include "PreviewCropTool.h"
78 #include "PreviewIdentifyTool.h"
79 #include "PreviewCameraTool.h"
80 #include "PreviewDifferenceTool.h"
81 #include "PreviewPanoMaskTool.h"
83 #include "PreviewLayoutLinesTool.h"
84 #include "PreviewColorPickerTool.h"
85 #include "PreviewGuideTool.h"
86 #include "PreviewEditCPTool.h"
87 
88 #include "ProjectionGridTool.h"
89 #include "PanosphereSphereTool.h"
90 
91 #include "OverviewCameraTool.h"
92 #include "OverviewOutlinesTool.h"
93 
94 #include <wx/progdlg.h>
95 #include <wx/infobar.h>
96 
97 // a random id, hope this doesn't break something..
98 enum {
99  ID_TOGGLE_BUT = wxID_HIGHEST+500,
100  PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1300,
101  PROJ_PARAM_VAL_ID = wxID_HIGHEST+1400,
102  PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500,
103  PROJ_PARAM_RESET_ID = wxID_HIGHEST+1550,
104  ID_TOGGLE_BUT_LEAVE = wxID_HIGHEST+1600,
105  ID_FULL_SCREEN = wxID_HIGHEST+1710,
106  ID_SHOW_ALL = wxID_HIGHEST+1711,
107  ID_SHOW_NONE = wxID_HIGHEST+1712,
108  ID_HIDE_HINTS = wxID_HIGHEST+1715,
109  ID_ASSISTANT_MENU = wxID_HIGHEST+1800,
110  ID_CREATEPANO_MENU = wxID_HIGHEST+1810,
111  ID_ASS_LOAD_IMAGES = wxID_HIGHEST+1820
112 };
113 
115 enum{
122 };
123 
124 //------------------------------------------------------------------------------
125 BEGIN_EVENT_TABLE(GLwxAuiFloatingFrame, wxAuiFloatingFrame)
126  EVT_ACTIVATE(GLwxAuiFloatingFrame::OnActivate)
128 
129 BEGIN_EVENT_TABLE(GLPreviewFrame, wxFrame)
130  EVT_CLOSE(GLPreviewFrame::OnClose)
131  EVT_SHOW(GLPreviewFrame::OnShowEvent)
132  //for some reason only key up is sent, key down event is not sent
133 // EVT_KEY_DOWN(GLPreviewFrame::KeyDown)
134 // EVT_KEY_UP(GLPreviewFrame::KeyUp)
135  EVT_BUTTON(XRCID("preview_center_tool"), GLPreviewFrame::OnCenterHorizontally)
136  EVT_BUTTON(XRCID("preview_fit_pano_tool"), GLPreviewFrame::OnFitPano)
137  EVT_BUTTON(XRCID("preview_fit_pano_tool2"), GLPreviewFrame::OnFitPano)
138  EVT_BUTTON(XRCID("preview_straighten_pano_tool"), GLPreviewFrame::OnStraighten)
139  EVT_BUTTON(XRCID("apply_num_transform"), GLPreviewFrame::OnNumTransform)
140  EVT_TEXT_ENTER(XRCID("input_yaw"), GLPreviewFrame::OnNumTransform)
141  EVT_TEXT_ENTER(XRCID("input_pitch"), GLPreviewFrame::OnNumTransform)
142  EVT_TEXT_ENTER(XRCID("input_roll"), GLPreviewFrame::OnNumTransform)
143  EVT_TEXT_ENTER(XRCID("input_x"), GLPreviewFrame::OnNumTransform)
144  EVT_TEXT_ENTER(XRCID("input_y"), GLPreviewFrame::OnNumTransform)
145  EVT_TEXT_ENTER(XRCID("input_z"), GLPreviewFrame::OnNumTransform)
146  EVT_BUTTON(ID_SHOW_ALL, GLPreviewFrame::OnShowAll)
147  EVT_BUTTON(ID_SHOW_NONE, GLPreviewFrame::OnShowNone)
148  EVT_CHECKBOX(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric)
149  EVT_TOGGLEBUTTON(XRCID("preview_identify_toggle_button"), GLPreviewFrame::OnIdentify)
150  EVT_TOGGLEBUTTON(XRCID("preview_color_picker_toggle_button"), GLPreviewFrame::OnColorPicker)
151  EVT_TOGGLEBUTTON(XRCID("preview_edit_cp_toggle_button"), GLPreviewFrame::OnEditCPTool)
152  EVT_CHECKBOX(XRCID("preview_control_point_tool"), GLPreviewFrame::OnControlPoint)
153  EVT_BUTTON(XRCID("preview_autocrop_tool"), GLPreviewFrame::OnAutocrop)
154  EVT_BUTTON(XRCID("preview_stack_autocrop_tool"), GLPreviewFrame::OnStackAutocrop)
155  EVT_BUTTON(XRCID("preview_autocrop_outside_tool"), GLPreviewFrame::OnAutocropOutside)
156  EVT_NOTEBOOK_PAGE_CHANGED(XRCID("mode_toolbar_notebook"), GLPreviewFrame::OnSelectMode)
157  EVT_NOTEBOOK_PAGE_CHANGING(XRCID("mode_toolbar_notebook"), GLPreviewFrame::OnToolModeChanging)
158  EVT_BUTTON(ID_HIDE_HINTS, GLPreviewFrame::OnHideProjectionHints)
159  EVT_BUTTON(XRCID("exposure_default_button"), GLPreviewFrame::OnDefaultExposure)
160  EVT_SPIN_DOWN(XRCID("exposure_spin"), GLPreviewFrame::OnDecreaseExposure)
161  EVT_SPIN_UP(XRCID("exposure_spin"), GLPreviewFrame::OnIncreaseExposure)
162  EVT_SPIN_DOWN(XRCID("range_compression_spin"), GLPreviewFrame::OnRangeCompressionDecrease)
163  EVT_SPIN_UP(XRCID("range_compression_spin"), GLPreviewFrame::OnRangeCompressionIncrease)
164  EVT_TEXT_ENTER(XRCID("range_compression_text"), GLPreviewFrame::OnRangeCompressionChanged)
165  EVT_CHOICE(XRCID("blend_mode_choice"), GLPreviewFrame::OnBlendChoice)
166  EVT_CHOICE(XRCID("drag_mode_choice"), GLPreviewFrame::OnDragChoice)
167  EVT_CHOICE(XRCID("projection_choice"), GLPreviewFrame::OnProjectionChoice)
168  EVT_CHOICE(XRCID("overview_mode_choice"), GLPreviewFrame::OnOverviewModeChoice)
169  EVT_CHOICE(XRCID("preview_guide_choice_crop"), GLPreviewFrame::OnGuideChanged)
170  EVT_CHOICE(XRCID("preview_guide_choice_drag"), GLPreviewFrame::OnGuideChanged)
171  EVT_CHOICE(XRCID("preview_guide_choice_proj"), GLPreviewFrame::OnGuideChanged)
172  EVT_MENU(XRCID("action_show_overview"), GLPreviewFrame::OnOverviewToggle)
173  EVT_MENU(XRCID("action_show_grid"), GLPreviewFrame::OnSwitchPreviewGrid)
174  EVT_MENU(ID_CREATE_CP, GLPreviewFrame::OnCreateCP)
175  EVT_MENU(ID_REMOVE_CP, GLPreviewFrame::OnRemoveCP)
176  EVT_MENU_CLOSE(GLPreviewFrame::OnMenuClose)
177 #ifndef __WXMAC__
178  EVT_COMMAND_SCROLL(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
179  EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV)
180  EVT_COMMAND_SCROLL_CHANGED(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
181 #else
182  EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV)
183  EVT_COMMAND_SCROLL(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
184  EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV)
185  EVT_COMMAND_SCROLL_THUMBTRACK(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
186 #endif
187  EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV)
188  EVT_TEXT_ENTER(XRCID("pano_text_hfov"), GLPreviewFrame::OnHFOVChanged )
189  EVT_TEXT_ENTER(XRCID("pano_text_vfov"), GLPreviewFrame::OnVFOVChanged )
190  EVT_TEXT_ENTER(XRCID("pano_val_roi_left"), GLPreviewFrame::OnROIChanged)
191  EVT_TEXT_ENTER(XRCID("pano_val_roi_top"), GLPreviewFrame::OnROIChanged)
192  EVT_TEXT_ENTER(XRCID("pano_val_roi_right"), GLPreviewFrame::OnROIChanged)
193  EVT_TEXT_ENTER(XRCID("pano_val_roi_bottom"), GLPreviewFrame::OnROIChanged)
194  EVT_BUTTON(XRCID("reset_crop_button"), GLPreviewFrame::OnResetCrop)
195  EVT_BUTTON(XRCID("crop_aspect_button"), GLPreviewFrame::OnSetCropAspect)
196  EVT_TEXT_ENTER(XRCID("exposure_text"), GLPreviewFrame::OnExposureChanged)
197  EVT_COMMAND_RANGE(PROJ_PARAM_VAL_ID,PROJ_PARAM_VAL_ID+PANO_PROJECTION_MAX_PARMS,wxEVT_COMMAND_TEXT_ENTER,GLPreviewFrame::OnProjParameterChanged)
198  EVT_BUTTON(PROJ_PARAM_RESET_ID, GLPreviewFrame::OnProjParameterReset)
199  EVT_TOOL(ID_FULL_SCREEN, GLPreviewFrame::OnFullScreen)
200  EVT_COLOURPICKER_CHANGED(XRCID("preview_background"), GLPreviewFrame::OnPreviewBackgroundColorChanged)
201  EVT_MENU(XRCID("ID_SHOW_FULL_SCREEN_PREVIEW"), GLPreviewFrame::OnFullScreen)
202  EVT_MENU(XRCID("action_show_main_frame"), GLPreviewFrame::OnShowMainFrame)
203  EVT_MENU(XRCID("action_exit_preview"), GLPreviewFrame::OnUserExit)
204  EVT_BUTTON ( XRCID("ass_load_images_button"), GLPreviewFrame::OnLoadImages)
205  EVT_BUTTON ( XRCID("ass_align_button"), GLPreviewFrame::OnAlign)
206  EVT_BUTTON ( XRCID("ass_create_button"), GLPreviewFrame::OnCreate)
207  // context menu of select all button
208  EVT_MENU(XRCID("selectMenu_selectAll"), GLPreviewFrame::OnSelectAllMenu)
209  EVT_MENU(XRCID("selectMenu_selectMedian"), GLPreviewFrame::OnSelectMedianMenu)
210  EVT_MENU(XRCID("selectMenu_selectBrightest"), GLPreviewFrame::OnSelectDarkestMenu)
211  EVT_MENU(XRCID("selectMenu_selectDarkest"), GLPreviewFrame::OnSelectBrightestMenu)
212  EVT_MENU(XRCID("selectMenu_keepCurrentSelection"), GLPreviewFrame::OnSelectKeepSelection)
213  EVT_MENU(XRCID("selectMenu_resetSelection"), GLPreviewFrame::OnSelectResetSelection)
215 
216 BEGIN_EVENT_TABLE(ImageToogleButtonEventHandler, wxEvtHandler)
217  EVT_ENTER_WINDOW(ImageToogleButtonEventHandler::OnEnter)
218  EVT_LEAVE_WINDOW(ImageToogleButtonEventHandler::OnLeave)
219  EVT_TOGGLEBUTTON(-1, ImageToogleButtonEventHandler::OnChange)
221 
222 BEGIN_EVENT_TABLE(ImageGroupButtonEventHandler, wxEvtHandler)
223  EVT_ENTER_WINDOW(ImageGroupButtonEventHandler::OnEnter)
224  EVT_LEAVE_WINDOW(ImageGroupButtonEventHandler::OnLeave)
225  EVT_CHECKBOX(-1, ImageGroupButtonEventHandler::OnChange)
227 
228 #define PF_STYLE (wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
229 GLwxAuiFloatingFrame* GLwxAuiManager::CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p)
230 {
231  DEBUG_DEBUG("CREATING FLOATING FRAME");
232  frame->PauseResize();
233  GLwxAuiFloatingFrame* fl_frame = new GLwxAuiFloatingFrame(parent, this, p);
234  DEBUG_DEBUG("CREATED FLOATING FRAME");
235  return fl_frame;
236 }
237 
238 void GLwxAuiFloatingFrame::OnActivate(wxActivateEvent& evt)
239 {
240  DEBUG_DEBUG("FRAME ACTIVATE");
241  GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
242  frame->ContinueResize();
243  evt.Skip();
244 }
245 
247 {
248  DEBUG_DEBUG("FRAME ON MOVE FINISHED");
249  GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
250  frame->PauseResize();
251  wxAuiFloatingFrame::OnMoveFinished();
252  DEBUG_DEBUG("FRAME AFTER ON MOVE FINISHED");
253 }
254 
256 {
257  DEBUG_DEBUG("PAUSE RESIZE");
258  GLresize = false;
259 }
260 
262 {
263  GLresize = true;
264  wxSizeEvent event = wxSizeEvent(wxSize());
265  m_GLPreview->Resized(event);
266  m_GLOverview->Resized(event);
267 }
268 
269 #include <iostream>
271  : wxFrame(frame,-1, _("Fast Panorama preview"), wxDefaultPosition, wxDefaultSize,
272  PF_STYLE),
273  m_pano(pano)
274 {
275 
276  DEBUG_TRACE("");
277 
278  // initialize pointer
279  preview_helper = NULL;
281  plane_overview_helper = NULL;
282  crop_tool = NULL;
283  drag_tool = NULL;
284  color_picker_tool = NULL;
285  edit_cp_tool = NULL;
286  overview_drag_tool = NULL;
287  identify_tool = NULL ;
288  camera_tool = NULL;
291  difference_tool = NULL;
292  plane_difference_tool = NULL;
294  pano_mask_tool = NULL;
295  preview_guide_tool = NULL;
297 #ifdef __WXGTK__
298  loadedLayout=false;
299 #endif
300 
301  m_mode = -1;
302  m_oldProjFormat = -1;
303  // add a status bar
304  CreateStatusBar(3);
305  int widths[3] = {-3, 150, 150};
306  SetStatusWidths(3, widths);
307  SetStatusText(wxT(""),1);
308  SetStatusText(wxT(""),2);
309  wxConfigBase * cfg = wxConfigBase::Get();
310 
311  wxPanel *tool_panel = wxXmlResource::Get()->LoadPanel(this,wxT("mode_panel"));
312  XRCCTRL(*this,"preview_center_tool",wxButton)->SetBitmapMargins(0,5);
313  XRCCTRL(*this,"preview_fit_pano_tool",wxButton)->SetBitmapMargins(0,5);
314  XRCCTRL(*this,"preview_straighten_pano_tool",wxButton)->SetBitmapMargins(0,5);
315  XRCCTRL(*this,"preview_fit_pano_tool2",wxButton)->SetBitmapMargins(0,5);
316  XRCCTRL(*this,"preview_autocrop_tool",wxButton)->SetBitmapMargins(0,5);
317  XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->SetBitmapMargins(0,5);
318  XRCCTRL(*this, "preview_autocrop_outside_tool", wxButton)->SetBitmapMargins(0, 5);
319 
320  m_tool_notebook = XRCCTRL(*this, "mode_toolbar_notebook", wxNotebook);
321  m_identify_togglebutton = XRCCTRL(*this, "preview_identify_toggle_button", wxToggleButton);
322  m_identify_togglebutton->SetBitmapMargins(0, 5);
323  m_colorpicker_togglebutton = XRCCTRL(*this, "preview_color_picker_toggle_button", wxToggleButton);
324  m_colorpicker_togglebutton->SetBitmapMargins(0, 5);
325  m_editCP_togglebutton = XRCCTRL(*this, "preview_edit_cp_toggle_button", wxToggleButton);
326  m_editCP_togglebutton->SetBitmapMargins(0, 5);
327  wxBitmap bitmap;
328 #if !wxCHECK_VERSION(3,1,1)
329  bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/identify_tool.png"), wxBITMAP_TYPE_PNG);
330  m_identify_togglebutton->SetBitmap(bitmap, wxTOP);
331  bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/preview_white_balance.png"), wxBITMAP_TYPE_PNG);
332  m_colorpicker_togglebutton->SetBitmap(bitmap, wxTOP);
333  bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/preview_control_point_tool.png"), wxBITMAP_TYPE_PNG);
334  m_editCP_togglebutton->SetBitmap(bitmap, wxTOP);
335 #endif
336 
337  //build menu bar
338 #ifdef __WXMAC__
339  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
340 #endif
341  wxMenuBar* simpleMenu=wxXmlResource::Get()->LoadMenuBar(this, wxT("preview_simple_menu"));
342  m_filemenuSimple=wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu"));
343  m_filemenuAdvanced = wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu_advanced"));
344  MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuSimple->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
345  MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuAdvanced->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
346  MainFrame::Get()->GetFileHistory()->AddFilesToMenu();
347  simpleMenu->Insert(0, m_filemenuSimple, _("&File"));
348  SetMenuBar(simpleMenu);
349 
350  // initialize preview background color
351  wxString c = cfg->Read(wxT("/GLPreviewFrame/PreviewBackground"),wxT(HUGIN_PREVIEW_BACKGROUND));
352  m_preview_background_color = wxColour(c);
353  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->SetColour(m_preview_background_color);
354  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Refresh();
355  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Update();
356 
357  m_topsizer = new wxBoxSizer( wxVERTICAL );
358 
359  wxPanel * toggle_panel = new wxPanel(this);
360 
361  bool overview_hidden;
362  cfg->Read(wxT("/GLPreviewFrame/overview_hidden"), &overview_hidden, false);
363  GetMenuBar()->FindItem(XRCID("action_show_overview"))->Check(!overview_hidden);
364 
365  m_ToggleButtonSizer = new wxStaticBoxSizer(
366  new wxStaticBox(toggle_panel, -1, _("displayed images")),
367  wxHORIZONTAL );
368  toggle_panel->SetSizer(m_ToggleButtonSizer);
369 
370  m_ButtonPanel = new wxScrolledWindow(toggle_panel, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
371  //Horizontal scroll bars only
372  m_ButtonPanel->SetScrollRate(10, 0);
373  m_ButtonSizer = new wxBoxSizer(wxHORIZONTAL);
374  m_ButtonPanel->SetAutoLayout(true);
375  m_ButtonPanel->SetSizer(m_ButtonSizer);
376 
377  wxPanel *panel = new wxPanel(toggle_panel);
378  bitmap.LoadFile(huginApp::Get()->GetXRCPath()+wxT("data/preview_show_all.png"),wxBITMAP_TYPE_PNG);
379  m_selectAllButton = new SplitButton(panel, ID_SHOW_ALL, _("All"), wxDefaultPosition, wxDefaultSize);
380  m_selectAllButton->SetBitmap(bitmap);
381  //m_selectAllButton->SetBitmapMargins(5, 0);
382  m_selectAllButton->LoadMenu(wxT("preview_select_menu"));
383  // read last used setting
384  long mode = cfg->Read(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
385  m_selectAllMode = static_cast<SelectAllMode>(mode);
386  switch (m_selectAllMode)
387  {
389  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectMedian"), true);
390  break;
392  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectDarkest"), true);
393  break;
395  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectBrightest"), true);
396  break;
397  case SELECT_ALL_IMAGES:
398  default:
399  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectAll"), true);
400  break;
401  };
402  m_selectKeepSelection = (cfg->Read(wxT("/GLPreviewFrame/SelectAllKeepSelection"), 1l) == 1l);
404  {
405  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_keepCurrentSelection"), true);
406  }
407  else
408  {
409  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_resetSelection"), true);
410  };
411  bitmap.LoadFile(huginApp::Get()->GetXRCPath()+wxT("data/preview_show_none.png"),wxBITMAP_TYPE_PNG);
412  wxButton* select_none = new wxButton(panel, ID_SHOW_NONE, _("None"));
413  select_none->SetBitmap(bitmap,wxLEFT);
414  select_none->SetBitmapMargins(5,0);
415 
416  wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
417  sizer->Add(m_selectAllButton,0,wxALIGN_CENTER_VERTICAL | wxLEFT | wxTOP | wxBOTTOM,5);
418  sizer->Add(select_none,0,wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP | wxBOTTOM,5);
419  panel->SetSizer(sizer);
420  m_ToggleButtonSizer->Add(panel, 0, wxALIGN_CENTER_VERTICAL);
421  m_ToggleButtonSizer->Add(m_ButtonPanel, 1, wxALIGN_CENTER_VERTICAL, 0);
422 
423  m_topsizer->Add(tool_panel, 0, wxEXPAND | wxALL, 2);
424  m_topsizer->Add(toggle_panel, 0, wxEXPAND | wxBOTTOM, 5);
425 
426  m_infoBar = new wxInfoBar(this);
427  m_infoBar->AddButton(ID_HIDE_HINTS,_("Hide"));
428  m_infoBar->Connect(ID_HIDE_HINTS,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(GLPreviewFrame::OnHideProjectionHints),NULL,this);
429  m_topsizer->Add(m_infoBar, 0, wxEXPAND);
430 
431  //create panel that will hold gl canvases
432  wxPanel * vis_panel = new wxPanel(this);
433 
434  wxPanel * preview_panel = new wxPanel(vis_panel);
435  wxPanel * overview_panel = new wxPanel(vis_panel);
436 
437  // create our Viewers
438  int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0};
439  m_GLPreview = new GLPreview(preview_panel, pano, args, this);
440  m_GLOverview = new GLOverview(overview_panel, pano, args, this, m_GLPreview->GetContext());
442 
443 #ifdef __WXGTK__
444  // on wxGTK we can not create the OpenGL context with a hidden window
445  // therefore we need to create the overview window open and later hide it
446  overview_hidden=false;
447 #endif
448  m_GLOverview->SetActive(!overview_hidden);
449 
450  // set the AUI manager to our panel
452  m_mgr->SetManagedWindow(vis_panel);
453  vis_panel->SetMinSize(wxSize(200,150));
454 
455  //create the sizer for the preview
456  wxFlexGridSizer * flexSizer = new wxFlexGridSizer(2,0,5,5);
457  flexSizer->AddGrowableCol(0);
458  flexSizer->AddGrowableRow(0);
459 
460  //overview sizer
461  wxBoxSizer * overview_sizer = new wxBoxSizer(wxVERTICAL);
462 
463 
464  flexSizer->Add(m_GLPreview,
465  1, // not vertically stretchable
466  wxEXPAND | // horizontally stretchable
467  wxALL, // draw border all around
468  5); // border width
469 
470  m_VFOVSlider = new wxSlider(preview_panel, -1, 1,
471  1, 180,
472  wxDefaultPosition, wxDefaultSize,
473  wxSL_VERTICAL | wxSL_AUTOTICKS,
474  wxDefaultValidator,
475  _("VFOV"));
476  m_VFOVSlider->SetLineSize(1);
477  m_VFOVSlider->SetPageSize(10);
478  m_VFOVSlider->SetTickFreq(5);
479  m_VFOVSlider->SetToolTip(_("drag to change the vertical field of view"));
480 
481  flexSizer->Add(m_VFOVSlider, 0, wxEXPAND);
482 
483  m_HFOVSlider = new wxSlider(preview_panel, -1, 1,
484  1, 360,
485  wxDefaultPosition, wxDefaultSize,
486  wxSL_HORIZONTAL | wxSL_AUTOTICKS,
487  wxDefaultValidator,
488  _("HFOV"));
489  m_HFOVSlider->SetPageSize(10);
490  m_HFOVSlider->SetLineSize(1);
491  m_HFOVSlider->SetTickFreq(5);
492 
493  m_HFOVSlider->SetToolTip(_("drag to change the horizontal field of view"));
494 
495  m_HFOVText = XRCCTRL(*this, "pano_text_hfov" ,wxTextCtrl);
497  m_HFOVText->PushEventHandler(new TextKillFocusHandler(this));
498  m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
500  m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
501 
502  m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
504  m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
505 
506  m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
508  m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
509 
510  m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
512  m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
513 
514  m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
516  m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(this));
517 
518  m_GuideChoiceCrop = XRCCTRL(*this, "preview_guide_choice_crop", wxChoice);
519  m_GuideChoiceProj = XRCCTRL(*this, "preview_guide_choice_proj", wxChoice);
520  m_GuideChoiceDrag = XRCCTRL(*this, "preview_guide_choice_drag", wxChoice);
521  int guide=cfg->Read(wxT("/GLPreviewFrame/guide"),0l);
522  m_GuideChoiceCrop->SetSelection(guide);
523  m_GuideChoiceProj->SetSelection(guide);
524  m_GuideChoiceDrag->SetSelection(guide);
525 
526  flexSizer->Add(m_HFOVSlider, 0, wxEXPAND);
527 
528  m_overviewCommandPanel = wxXmlResource::Get()->LoadPanel(overview_panel,wxT("overview_command_panel"));
529  m_OverviewModeChoice = XRCCTRL(*this, "overview_mode_choice", wxChoice);
530 #if wxCHECK_VERSION(3,1,0)
531  const wxSize dpiSize(m_overviewCommandPanel->FromDIP(wxSize(200, 20)));
532  m_overviewCommandPanel->SetSize(0, 0, dpiSize.GetWidth(), dpiSize.GetHeight(), wxSIZE_AUTO_WIDTH);
533 #else
534  m_overviewCommandPanel->SetSize(0, 0, 200, 20, wxSIZE_AUTO_WIDTH);
535 #endif
536 
537  overview_sizer->Add(m_overviewCommandPanel, 0, wxEXPAND);
538  overview_sizer->Add(m_GLOverview, 1, wxEXPAND);
539 
540  bool showGrid;
541  cfg->Read(wxT("/GLPreviewFrame/showPreviewGrid"),&showGrid,true);
542  GetMenuBar()->FindItem(XRCID("action_show_grid"))->Check(showGrid);
543 
544  preview_panel->SetSizer(flexSizer);
545  overview_panel->SetSizer(overview_sizer);
546 
547  m_mgr->AddPane(preview_panel,
548  wxAuiPaneInfo(
549  ).Name(wxT("preview")
550  ).MinSize(300,200
551  ).CloseButton(false
552  ).CaptionVisible(false
553  ).Caption(_("Preview")
554  ).Floatable(false
555  ).Dockable(false
556  ).Center(
557  )
558  );
559 
560  m_mgr->AddPane(overview_panel,
561  wxAuiPaneInfo(
562  ).Name(wxT("overview")
563  ).MinSize(300,200
564  ).CloseButton(false
565  ).CaptionVisible(
566  ).Caption(_("Overview")
567  ).FloatingSize(100,100
568  ).FloatingPosition(500,500
569  ).Dockable(true
570  ).PinButton(
571  ).Left(
572  ).Show(!overview_hidden
573  )
574  );
575 
576 
577  m_topsizer->Add(vis_panel, 1, wxEXPAND);
578 
579  //assistant related controls
580  m_loadImagesButton = XRCCTRL(*this, "ass_load_images_button", SplitButton);
582  m_loadImagesButton->GetSplitButtonMenu()->Append(ID_ASS_LOAD_IMAGES, _("Load images (autodetect lens type)..."));
583  Bind(wxEVT_MENU, &GLPreviewFrame::OnLoadImages, this, ID_ASS_LOAD_IMAGES);
584  m_loadImagesButton->GetSplitButtonMenu()->AppendSeparator();
585  // now add all lens types to menu
587  int lensTypeId = ID_ASS_LOAD_IMAGES + 1;
588  for (auto& lensType : lensInfoVector)
589  {
590  m_loadImagesButton->GetSplitButtonMenu()->Append(lensTypeId, wxString::Format(_("Load images (lens type: %s)..."), lensType.name));
591  const int lensId = lensType.id;
592  Bind(wxEVT_MENU, [this, lensId](wxCommandEvent&) { LoadImages(lensId); }, lensTypeId);
593  ++lensTypeId;
594  };
595 
596  m_alignButton = XRCCTRL(*this, "ass_align_button", SplitButton);
598  m_alignButton->Disable();
599  // add default assistant to drop down menu
600  m_alignButton->GetSplitButtonMenu()->Append(ID_ASSISTANT_MENU, _("Panorama assistant (default)"), m_alignButton->GetToolTipText());
601  Bind(wxEVT_MENU, &GLPreviewFrame::OnAlign, this, ID_ASSISTANT_MENU);
602  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
603  // provide help texts in the status bar, add the necessary event handlers
604  m_alignButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { SetStatusText(wxString()); });
605  m_alignButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_HIGHLIGHT,
606  [this](wxMenuEvent& e) { if (e.GetId() > 0) SetStatusText(m_alignButton->GetSplitButtonMenu()->GetHelpString(e.GetId())); }
607  );
608 
609  m_createButton = XRCCTRL(*this, "ass_create_button", SplitButton);
611  m_createButton->Disable();
612  // add default create function to drop down menu
613  m_createButton->GetSplitButtonMenu()->Append(ID_CREATEPANO_MENU, _("Stitch normal panorama (default)"), m_createButton->GetToolTipText());
614  Bind(wxEVT_MENU, &GLPreviewFrame::OnCreate, this, ID_CREATEPANO_MENU);
615  m_createButton->GetSplitButtonMenu()->AppendSeparator();
616  // provide help texts in the status bar, add the necessary event handlers
617  m_createButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { SetStatusText(wxString()); });
618  m_createButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_HIGHLIGHT,
619  [this](wxMenuEvent& e) { if (e.GetId() > 0) SetStatusText(m_createButton->GetSplitButtonMenu()->GetHelpString(e.GetId())); }
620  );
621 
622  m_ProjectionChoice = XRCCTRL(*this,"projection_choice",wxChoice);
623 
624  /* populate with all available projection types */
625  int nP = panoProjectionFormatCount();
626  for(int n=0; n < nP; n++) {
627  pano_projection_features proj;
628  if (panoProjectionFeaturesQuery(n, &proj)) {
629  wxString str2(proj.name, wxConvLocal);
630  m_ProjectionChoice->Append(wxGetTranslation(str2));
631  }
632  }
633  m_ProjectionChoice->SetSelection(2);
634 
636  // Blend mode
637  // remaining blend mode should be added after OpenGL context has been created
638  // see FillBlendMode()
639  m_differenceIndex = -1;
640  // create choice item
641  m_BlendModeChoice = XRCCTRL(*this,"blend_mode_choice",wxChoice);
642  m_BlendModeChoice->Append(_("normal"));
643  m_BlendModeChoice->SetSelection(0);
644 
645  m_DragModeChoice = XRCCTRL(*this, "drag_mode_choice", wxChoice);
647  bool individualDrag;
648  cfg->Read(wxT("/GLPreviewFrame/individualDragMode"), &individualDrag, false);
649  if(individualDrag)
650  {
651  m_DragModeChoice->SetSelection(1);
652  }
653  else
654  {
655  m_DragModeChoice->SetSelection(0);
656  };
657  // default drag mode
659 
660  // TODO implement hdr display in OpenGL, if possible?
661  // Disabled until someone can figure out HDR display in OpenGL.
662  /*
664  // LDR, HDR
665  blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")),
666  0, // not vertically strechable
667  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
668  5); // border width
669 
670  m_choices[0] = _("LDR");
671  m_choices[1] = _("HDR");
672  m_outputModeChoice = new wxChoice(this, ID_OUTPUTMODE_CHOICE,
673  wxDefaultPosition, wxDefaultSize,
674  2, m_choices);
675  m_outputModeChoice->SetSelection(0);
676  blendModeSizer->Add(m_outputModeChoice,
677  0,
678  wxALL | wxALIGN_CENTER_VERTICAL,
679  5);
680  */
681 
683  // exposure
684  m_defaultExposureBut = XRCCTRL(*this, "exposure_default_button", wxBitmapButton);
685 
686  m_exposureTextCtrl = XRCCTRL(*this, "exposure_text", wxTextCtrl);
687  m_exposureTextCtrl->PushEventHandler(new TextKillFocusHandler(this));
688 
689  m_exposureSpinBut = XRCCTRL(*this, "exposure_spin", wxSpinButton);
690  m_exposureSpinBut->SetValue(0);
691  m_exposureSpinBut->SetMaxSize(wxSize(-1, m_exposureTextCtrl->GetSize().GetHeight()));
692 
693  m_rangeCompressionTextCtrl = XRCCTRL(*this, "range_compression_text", wxTextCtrl);
694  m_rangeCompressionTextCtrl->PushEventHandler(new TextKillFocusHandler(this));
695 
696  m_rangeCompressionSpinBut = XRCCTRL(*this, "range_compression_spin", wxSpinButton);
697  m_rangeCompressionSpinBut->SetValue(0);
698  m_rangeCompressionSpinBut->SetMaxSize(wxSize(-1, m_rangeCompressionTextCtrl->GetSize().GetHeight()));
699 
700  m_projection_panel = XRCCTRL(*this, "projection_panel", wxPanel);
701  m_projParamSizer = new wxBoxSizer(wxHORIZONTAL);
702 
703  wxBitmapButton * resetProjButton=new wxBitmapButton(m_projection_panel, PROJ_PARAM_RESET_ID,
704  wxArtProvider::GetBitmap(wxART_REDO));
705  resetProjButton->SetToolTip(_("Resets the projection's parameters to their default values."));
706  m_projParamSizer->Add(resetProjButton, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
707 
708  m_projParamNamesLabel.resize(PANO_PROJECTION_MAX_PARMS);
709  m_projParamTextCtrl.resize(PANO_PROJECTION_MAX_PARMS);
710  m_projParamSlider.resize(PANO_PROJECTION_MAX_PARMS);
711 
712  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++) {
713 
714  wxBoxSizer* paramBoxSizer = new wxBoxSizer(wxVERTICAL);
715  m_projParamNamesLabel[i] = new wxStaticText(m_projection_panel, PROJ_PARAM_NAMES_ID+i, _("param:"));
716  paramBoxSizer->Add(m_projParamNamesLabel[i],
717  0, // not vertically strechable
718  wxLEFT | wxRIGHT, // draw border all around
719  5); // border width
720  m_projParamTextCtrl[i] = new wxTextCtrl(m_projection_panel, PROJ_PARAM_VAL_ID+i, wxT("0"),
721  wxDefaultPosition, wxSize(35,-1), wxTE_PROCESS_ENTER);
722  m_projParamTextCtrl[i]->PushEventHandler(new TextKillFocusHandler(this));
723  paramBoxSizer->Add(m_projParamTextCtrl[i],
724  0, // not vertically strechable
725  wxLEFT | wxRIGHT, // draw border all around
726  5); // border width
727 
728  m_projParamSizer->Add(paramBoxSizer);
729  m_projParamSlider[i] = new wxSlider(m_projection_panel, PROJ_PARAM_SLIDER_ID+i, 0, -90, 90);
731  1, // not vertically strechable
732  wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL , // draw border all around
733  5); // border width
734  }
735 
736  m_projection_panel->GetSizer()->Add(m_projParamSizer, 1, wxALIGN_CENTER_VERTICAL);
737 
738  // do not show projection param sizer
739  m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
740 
741  // the initial size as calculated by the sizers
742  this->SetSizer( m_topsizer );
743  m_topsizer->SetSizeHints( this );
744 
745  // set the minimize icon
746 #ifdef __WXMSW__
747  wxIconBundle myIcons(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
748  SetIcons(myIcons);
749 #else
750  wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
751  SetIcon(myIcon);
752 #endif
753 
754  m_pano.addObserver(this);
755 
756  RestoreFramePosition(this, wxT("GLPreviewFrame"));
757 
758 #ifdef __WXMSW__
759  // wxFrame does have a strange background color on Windows..
760  this->SetBackgroundColour(m_GLPreview->GetBackgroundColour());
761 #endif
762 
763  m_showProjectionHints = cfg->Read(wxT("/GLPreviewFrame/ShowProjectionHints"), HUGIN_SHOW_PROJECTION_HINTS) == 1;
764  m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigitsEdit"),3);
765 
766  // tell the manager to "commit" all the changes just made
767  m_mgr->Update();
768 
769  if (cfg->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0)
770  {
771 #if defined __WXMSW__ || defined __WXMAC__
772  InitPreviews();
773  Show();
774 #else
775  Show();
777 #endif
778  }
779  SetDropTarget(new PanoDropTarget(m_pano, true));
780 #if defined __WXMAC__
781  Layout();
782  Update();
783 #endif
784 }
785 
787 {
788 #ifdef __WXGTK__
789  if(loadedLayout)
790  {
791  return;
792  };
793  loadedLayout=true;
794 #endif
795  wxString OpenGLLayout=wxConfig::Get()->Read(wxT("/GLPreviewFrame/OpenGLLayout"));
796  if(!OpenGLLayout.IsEmpty())
797  {
798  m_mgr->LoadPerspective(OpenGLLayout,true);
799 #ifdef __WXGTK__
800  if(!GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked())
801  {
802  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
803  if (inf.IsOk())
804  {
805  inf.Hide();
806  }
807  m_GLOverview->SetActive(false);
808  };
809  m_mgr->Update();
810  wxShowEvent dummy;
811  dummy.SetShow(true);
812  OnShowEvent(dummy);
813 #endif
814  };
815  FillBlendChoice();
816 };
817 
819 {
820  wxConfigBase * cfg = wxConfigBase::Get();
821 
822  StoreFramePosition(this, wxT("GLPreviewFrame"));
823 
824  if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
825  cfg->Write(wxT("/GLPreviewFrame/isShown"), 1l);
826  } else {
827  cfg->Write(wxT("/GLPreviewFrame/isShown"), 0l);
828  }
829 
830  cfg->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection());
831  cfg->Write(wxT("/GLPreviewFrame/OpenGLLayout"), m_mgr->SavePerspective());
832  cfg->Write(wxT("/GLPreviewFrame/overview_hidden"), !(GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()));
833  cfg->Write(wxT("/GLPreviewFrame/showPreviewGrid"), GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked());
834  cfg->Write(wxT("/GLPreviewFrame/individualDragMode"), individualDragging());
835  cfg->Write(wxT("/GLPreviewFrame/guide"),m_GuideChoiceProj->GetSelection());
836 };
837 
839 {
840  DEBUG_TRACE("dtor writing config");
842 
843  // delete all of the tools. When the preview is never used we never get an
844  // OpenGL context and therefore don't create the tools.
845  if (crop_tool)
846  {
854  preview_helper->DeactivateTool(preview_control_point_tool); delete preview_control_point_tool;
858  }
869  }
877  }
878  m_exposureTextCtrl->PopEventHandler(true);
879  m_HFOVText->PopEventHandler(true);
880  m_rangeCompressionTextCtrl->PopEventHandler(true);
881  m_VFOVText->PopEventHandler(true);
882  m_ROILeftTxt->PopEventHandler(true);
883  m_ROIRightTxt->PopEventHandler(true);
884  m_ROITopTxt->PopEventHandler(true);
885  m_ROIBottomTxt->PopEventHandler(true);
886  for (int i=0; i < m_ToggleButtons.size(); i++)
887  {
888  m_ToggleButtons[i]->PopEventHandler(true);
889  m_GroupToggleButtons[i]->PopEventHandler(true);
890  }
891  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++)
892  {
893  m_projParamTextCtrl[i]->PopEventHandler(true);
894  };
895  m_pano.removeObserver(this);
896 
897  // deinitialize the frame manager
898  m_mgr->UnInit();
899  if (m_mgr) {
900  delete m_mgr;
901  }
903  {
904  delete m_filemenuSimple;
905  }
906  else
907  {
908  delete m_filemenuAdvanced;
909  };
910 
911  DEBUG_TRACE("dtor end");
912 }
913 
915 {
917  {
921  };
922 };
923 
928 {
929  if (m_BlendModeChoice != NULL)
930  {
931  int index=m_BlendModeChoice->GetSelection();
932  if(index==0)
933  {
934  // normal mode
935  if (preview_helper != NULL
936  && difference_tool != NULL)
937  {
939  };
940 
941  if (panosphere_overview_helper != NULL
942  && panosphere_difference_tool != NULL)
943  {
945  };
946 
947  if (plane_overview_helper != NULL
948  && plane_difference_tool != NULL)
949  {
951  };
952 
953 
954  }
955  else
956  {
957  if(index==m_differenceIndex)
958  {
959  // difference mode
960  if (preview_helper != NULL
961  && identify_tool != NULL
962  && difference_tool != NULL )
963  {
965 // preview_helper->DeactivateTool(identify_tool);
966  m_identify_togglebutton->SetValue(false);
969  };
970 
971  // difference mode
972  if (panosphere_overview_helper != NULL
974  && panosphere_difference_tool != NULL)
975  {
976 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
979  };
980 
981  // difference mode
982  if (plane_overview_helper != NULL
983  && plane_overview_identify_tool != NULL
984  && plane_difference_tool != NULL)
985  {
986 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
989  };
990 
991  }
992  else
993  {
994  DEBUG_WARN("Unknown blend mode selected");
995  };
996  }
997  }
998 }
999 
1001 {
1002  m_ROILeftTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().left() ));
1003  m_ROIRightTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().right() ));
1004  m_ROITopTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().top() ));
1005  m_ROIBottomTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().bottom() ));
1006 
1007  // display the current aspect ratio
1008  if (opts.getROI().area() > 0)
1009  {
1010  const int commonDivisor = hugin_utils::gcd(opts.getROI().width(), opts.getROI().height());
1011  wxString labelAspectRatio;
1012  if (commonDivisor > std::pow(10, hugin_utils::floori(log10f(std::max(opts.getROI().width(), opts.getROI().height()))) - 2))
1013  {
1014  labelAspectRatio = wxString::Format("%d:%d", opts.getROI().width() / commonDivisor, opts.getROI().height() / commonDivisor);
1015  }
1016  else
1017  {
1018  const float ratio = 1.0f * opts.getROI().width() / opts.getROI().height();
1019  if (ratio > 1.0f)
1020  {
1021  labelAspectRatio=wxString::Format("%.2f:1", ratio);
1022  }
1023  else
1024  {
1025  labelAspectRatio=wxString::Format("1:%.2f", 1.0f / ratio);
1026  };
1027  };
1028  XRCCTRL(*this, "crop_aspect_label", wxStaticText)->SetLabel(labelAspectRatio);
1029  };
1030 
1031 };
1032 
1034 {
1035  m_alignButton->Enable(pano.getNrOfImages()>0);
1036 
1037  if(pano.getNrOfImages()==0)
1038  {
1039  m_createButton->Disable();
1040  XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("No images loaded."));
1041  }
1042  else
1043  {
1044  bool enableCreate = false;
1045  // check if images are at position 0
1046  for (size_t i = 0; i < pano.getNrOfImages(); ++i)
1047  {
1048  const HuginBase::SrcPanoImage& img = pano.getImage(i);
1049  if (img.getYaw() != 0.0 || img.getPitch() != 0.0 || img.getRoll() != 0.0)
1050  {
1051  enableCreate = true;
1052  break;
1053  };
1054  };
1055  // disable create button after loading images
1056  const std::string lastCmd = PanoCommand::GlobalCmdHist::getInstance().getLastCommandName();
1057  if (lastCmd == "add images" || lastCmd == "add and distribute images")
1058  {
1059  enableCreate = false;
1060  };
1061  if (!enableCreate && pano.getNrOfImages() == 1)
1062  {
1063  // some more checks for single image projects
1065  {
1066  enableCreate = true;
1067  };
1068  if (pano.getOptions().getROI() != vigra::Rect2D(pano.getOptions().getSize()))
1069  {
1070  enableCreate = true;
1071  };
1072  if (pano.getImage(0).getProjection() == HuginBase::SrcPanoImage::EQUIRECTANGULAR)
1073  {
1074  enableCreate = true;
1075  };
1076  };
1077  m_createButton->Enable(enableCreate);
1078  }
1079 
1080  if (pano.getNrOfImages() > 1)
1081  {
1082  // in wxWidgets 2.9, format must have types that exactly match.
1083  // However std::size_t could be any unsiged integer, so we cast it to
1084  // unsigned long.int to be on the safe side.
1085  wxString alignMsg = wxString::Format(_("%lu images are connected by %lu control points.\n"), (unsigned long int) pano.getNrOfImages(), (unsigned long int) pano.getCtrlPoints().size());
1086 
1087  if (m_pano.getNrOfCtrlPoints() > 0)
1088  {
1089  // find components..
1091  const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
1092  if (comps.size() > 1)
1093  {
1094  alignMsg += wxString::Format(_("%lu unconnected image groups found: %s\n"), static_cast<unsigned long int>(comps.size()), Components2Str(comps).c_str());
1095  }
1096  else
1097  {
1098  if (m_pano.needsOptimization())
1099  {
1100  alignMsg += _("Images or control points have changed, new alignment is needed.");
1101  }
1102  else
1103  {
1104  HuginBase::CalculateCPStatisticsError calcStats(m_pano, MainFrame::Get()->GetOptimizeOnlyActiveImages(), MainFrame::Get()->GetOptimizeIgnoreLineCp());
1105  calcStats.run();
1106  const double max = calcStats.getResultMax();
1107  const double mean = calcStats.getResultMean();
1108 
1109  if (max != 0.0)
1110  {
1111  alignMsg = alignMsg + wxString::Format(_("Mean error after optimization: %.1f pixel, max: %.1f"), mean, max);
1112  }
1113  }
1114  }
1115  }
1116  wxStaticText* statusCtrl = XRCCTRL(*this, "ass_status_text", wxStaticText);
1117  statusCtrl->SetLabel(alignMsg);
1118  statusCtrl->InvalidateBestSize();
1119  m_tool_notebook->GetPage(0)->Layout();
1120  Refresh();
1121  }
1122  else
1123  {
1124  if (pano.getNrOfImages() == 1)
1125  {
1126  XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("One image loaded."));
1127  };
1128  };
1129 
1130  GetMenuBar()->Enable(XRCID("ID_EDITUNDO"), PanoCommand::GlobalCmdHist::getInstance().canUndo());
1131  GetMenuBar()->Enable(XRCID("ID_EDITREDO"), PanoCommand::GlobalCmdHist::getInstance().canRedo());
1132 
1133  // TODO: update meaningful help text and dynamic links to relevant tabs
1134 
1135  const HuginBase::PanoramaOptions & opts = pano.getOptions();
1136 
1137  wxString projection;
1138  m_ProjectionChoice->SetSelection(opts.getProjection());
1139  m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
1140 
1141  // No HDR display yet.
1142  /*
1143  m_outputModeChoice->SetSelection(opts.outputMode);
1144  if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
1145  m_exposureTextCtrl->Hide();
1146  m_defaultExposureBut->Hide();
1147  m_decExposureBut->Hide();
1148  m_incExposureBut->Hide();
1149  } else {
1150  m_exposureTextCtrl->Show();
1151  m_defaultExposureBut->Show();
1152  m_decExposureBut->Show();
1153  m_incExposureBut->Show();
1154  }*/
1155  m_exposureTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal));
1156  m_rangeCompressionTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputRangeCompression, 1).c_str(), wxConvLocal));
1157 
1158  const bool activeImgs = !pano.getActiveImages().empty();
1159 
1160  // TODO: enable display of parameters and set their limits, if projection has some.
1161 
1162  int nParam = opts.m_projFeatures.numberOfParameters;
1163  bool relayout = false;
1164  // if the projection format has changed
1165  if (opts.getProjection() != m_oldProjFormat) {
1166  DEBUG_DEBUG("Projection format changed");
1167  if (nParam) {
1168  // show parameters and update labels.
1169  m_projection_panel->GetSizer()->Show(m_projParamSizer, true, true);
1170  int i;
1171  for (i=0; i < nParam; i++) {
1172  const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
1173  wxString str2(pp->name, wxConvLocal);
1174  str2 = wxGetTranslation(str2);
1175  m_projParamNamesLabel[i]->SetLabel(str2);
1176  m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
1177  }
1178  for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
1179  m_projParamNamesLabel[i]->Hide();
1180  m_projParamSlider[i]->Hide();
1181  m_projParamTextCtrl[i]->Hide();
1182  }
1183  relayout = true;
1184  } else {
1185  m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
1186  relayout = true;
1187  }
1188  }
1189  if (nParam) {
1190  // display new values
1191  std::vector<double> params = opts.getProjectionParameters();
1192  assert((int) params.size() == nParam);
1193  for (int i=0; i < nParam; i++) {
1194  wxString val = wxString(hugin_utils::doubleToString(params[i],1).c_str(), wxConvLocal);
1195  m_projParamTextCtrl[i]->ChangeValue(wxString(val.wc_str(), wxConvLocal));
1196  m_projParamSlider[i]->SetValue(hugin_utils::roundi(params[i]));
1197  }
1198  }
1199  if (relayout) {
1200  m_projection_panel->Layout();
1201  Refresh();
1202  }
1203  SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2);
1204  m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
1205  m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
1206  std::string val;
1207  val = hugin_utils::doubleToString(opts.getHFOV(),1);
1208  m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1209  val = hugin_utils::doubleToString(opts.getVFOV(),1);
1210  m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1211  m_VFOVText->Enable(opts.fovCalcSupported(opts.getProjection()));
1212 
1213  m_oldProjFormat = opts.getProjection();
1214 
1215  XRCCTRL(*this,"preview_autocrop_tool",wxButton)->Enable(activeImgs);
1216  XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->Enable(activeImgs);
1217  UpdateRoiDisplay(opts);
1218 
1220  {
1222  };
1223  redrawPreview();
1224 }
1225 
1227 {
1228  DEBUG_TRACE("");
1229 
1230  bool dirty = false;
1231 
1232  unsigned int nrImages = pano.getNrOfImages();
1233  unsigned int nrButtons = m_ToggleButtons.size();
1234 
1235  GetMenuBar()->Enable(XRCID("action_optimize"), nrImages > 0);
1236 
1237 // m_displayedImgs.clear();
1238 
1239  // remove items for nonexisting images
1240  for (int i=nrButtons-1; i>=(int)nrImages; i--)
1241  {
1242  m_ButtonSizer->Detach(m_ToggleButtonPanel[i]);
1243  // Image toggle buttons have a event handler on the stack which
1244  // must be removed before the buttons get destroyed.
1245  m_ToggleButtons[i]->PopEventHandler();
1246  m_GroupToggleButtons[i]->PopEventHandler();
1247  delete m_ToggleButtons[i];
1248  delete m_GroupToggleButtons[i];
1249  delete m_ToggleButtonPanel[i];
1250  m_ToggleButtons.pop_back();
1251  m_GroupToggleButtons.pop_back();
1252  m_ToggleButtonPanel.pop_back();
1253  delete toogle_button_event_handlers[i];
1254  toogle_button_event_handlers.pop_back();
1257  dirty = true;
1258  }
1259 
1260  //change overview mode to panosphere if the translation plane parameter are non zero
1262  {
1264  {
1266  m_OverviewModeChoice->SetSelection(0);
1267  //check if drag mode is mosaic, if so reset to normal
1268  if(drag_tool)
1269  {
1271  {
1272  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
1275  // adjust the layout
1276  DragChoiceLayout(m_DragModeChoice->GetSelection());
1277  };
1278  };
1279  }
1280  }
1281 
1282  // add buttons
1283  if ( nrImages >= nrButtons ) {
1284  for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
1285  if (*it >= nrButtons) {
1286  // create new item.
1287 // wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
1288  //put wxToggleButton in a wxPanel because
1289  //on Windows the background colour of wxToggleButton can't be changed
1290  wxPanel *pan = new wxPanel(m_ButtonPanel);
1291  wxBoxSizer * siz = new wxBoxSizer(wxVERTICAL);
1292  pan->SetSizer(siz);
1293  wxToggleButton * but = new wxToggleButton(pan,
1294  ID_TOGGLE_BUT + *it,
1295  wxString::Format(wxT(" %d "),*it),
1296  wxDefaultPosition, wxDefaultSize,
1297  wxBU_EXACTFIT);
1298 
1299  wxCheckBox *butcheck = new wxCheckBox(pan, wxID_ANY, wxT(""));
1300 
1301 #if defined __WXMSW__ || defined __WXMAC__
1302  //we need a border around the button to see the colored panel
1303  //because changing backgroundcolor of wxToggleButton does not work in wxMSW
1304  siz->AddSpacer(5);
1305  siz->Add(butcheck, 0, wxALIGN_CENTRE_HORIZONTAL | wxFIXED_MINSIZE, 0);
1306  siz->Add(but,0,wxLEFT | wxRIGHT | wxBOTTOM , 5);
1307 #else
1308  siz->Add(but,0,wxALL ,0);
1309  siz->Add(butcheck, 0, wxALL | wxFIXED_MINSIZE, 0);
1310 #endif
1311  // for the identification tool to work, we need to find when the
1312  // mouse enters and exits the button. We use a custom event
1313  // handler, which will also toggle the images:
1314  ImageToogleButtonEventHandler * event_handler = new ImageToogleButtonEventHandler(*it, m_identify_togglebutton, &m_pano);
1315  event_handler->AddIdentifyTool(&identify_tool);
1318  toogle_button_event_handlers.push_back(event_handler);
1319  but->PushEventHandler(event_handler);
1320 
1321  ImageGroupButtonEventHandler * group_event_handler = new
1322  ImageGroupButtonEventHandler(*it, this, &m_pano);
1323  group_event_handler->AddDragTool((DragTool**) &drag_tool);
1324  group_event_handler->AddDragTool((DragTool**) &overview_drag_tool);
1325  group_event_handler->AddIdentifyTool(&identify_tool);
1326  group_event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
1327  group_event_handler->AddIdentifyTool(&plane_overview_identify_tool);
1328  toggle_group_button_event_handlers.push_back(group_event_handler);
1329  butcheck->PushEventHandler(group_event_handler);
1330  butcheck->Show(individualDragging() && m_mode==mode_drag);
1331 
1332  but->SetValue(true);
1333  m_ButtonSizer->Add(pan,
1334  0,
1335  wxLEFT | wxTOP,
1336  0);
1337  m_ToggleButtons.push_back(but);
1338  m_GroupToggleButtons.push_back(butcheck);
1339  m_ToggleButtonPanel.push_back(pan);
1340  dirty = true;
1341  }
1342  }
1343  }
1344 
1345  // update existing items
1346  HuginBase::UIntSet displayedImages = m_pano.getActiveImages();
1347  for (unsigned i=0; i < nrImages; i++) {
1348  m_ToggleButtons[i]->SetValue(set_contains(displayedImages, i));
1349  wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
1350  m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
1351  }
1352 
1353  if (dirty) {
1354  m_ButtonSizer->FitInside(m_ButtonPanel);
1355  Layout();
1356  SendSizeEvent();
1357  DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
1358  DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
1359  }
1360  if(nrImages==0)
1361  {
1363  m_tool_notebook->ChangeSelection(mode_assistant);
1364  };
1365  for(size_t i=2; i<m_tool_notebook->GetPageCount();i++)
1366  {
1367  m_tool_notebook->GetPage(i)->Enable(nrImages!=0);
1368  };
1369  redrawPreview();
1370 }
1371 
1373 {
1374  m_GLPreview->Refresh();
1375  m_GLOverview->Refresh();
1376 }
1377 
1379 {
1380  if (preview_helper)
1381  {
1383  m_GLPreview->Redraw();
1384  };
1385 }
1386 
1387 void GLPreviewFrame::OnShowEvent(wxShowEvent& e)
1388 {
1389 
1390  DEBUG_TRACE("OnShow");
1391  bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1392  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
1393  if (inf.IsOk()) {
1394  if (e.IsShown()) {
1395  if (!inf.IsShown() && toggle_on ) {
1396  inf.Show();
1397  m_mgr->Update();
1398  }
1399  } else {
1400  if (inf.IsFloating() && inf.IsShown()) {
1401  DEBUG_DEBUG("hiding overview float");
1402  inf.Hide();
1403  m_mgr->Update();
1404  }
1405  }
1406  }
1407 
1408 }
1409 
1410 //the following methods are to substitude the GLViewer KeyUp and KeyDown methods
1411 //so that tools use key events that happen globally to the preview frame
1412 //however only key up event is sent, and not key down
1413 //so until this is resolved they will remain to be handled by GLViewer
1414 void GLPreviewFrame::KeyDown(wxKeyEvent& e)
1415 {
1416  if (preview_helper) {
1417  preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1418  }
1419  if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1421  if (plane_overview_helper) {
1422  plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1423  }
1426  panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1427  }
1428  }
1429 
1430  }
1431  e.Skip();
1432 }
1433 
1434 void GLPreviewFrame::KeyUp(wxKeyEvent& e)
1435 {
1436  if (preview_helper) {
1437  preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1438  }
1439  if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1441  if (plane_overview_helper) {
1442  plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1443  }
1444  }
1447  panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1448  }
1449  }
1450 
1451  }
1452  e.Skip();
1453 }
1454 
1455 
1456 
1457 void GLPreviewFrame::OnOverviewToggle(wxCommandEvent& e)
1458 {
1459  DEBUG_TRACE("overview toggle");
1460  bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1461  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
1462  if (inf.IsOk()) {
1463  if (inf.IsShown() && !toggle_on) {
1464  inf.Hide();
1465  m_GLOverview->SetActive(false);
1466  m_mgr->Update();
1467  } else if (!(inf.IsShown() && toggle_on)) {
1468  inf.Show();
1469 #if defined __WXMSW__ || defined __WXMAC__
1470  m_GLOverview->SetActive(true);
1471  m_mgr->Update();
1472 #else
1473  m_mgr->Update();
1474  m_GLOverview->SetActive(true);
1475 #endif
1476  }
1477  }
1478 }
1479 
1480 void GLPreviewFrame::OnSwitchPreviewGrid(wxCommandEvent & e)
1481 {
1482  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
1483  {
1486  }
1487  else
1488  {
1491  }
1492  m_GLPreview->Refresh();
1493  m_GLOverview->Refresh();
1494 }
1495 
1496 void GLPreviewFrame::OnClose(wxCloseEvent& event)
1497 {
1498  DEBUG_TRACE("OnClose")
1499  // do not close, just hide if we're not forced
1500  if(m_guiLevel==GUI_SIMPLE)
1501  {
1502  if(!MainFrame::Get()->CloseProject(event.CanVeto(), MainFrame::CLOSE_PROGRAM))
1503  {
1504  if (event.CanVeto())
1505  {
1506  event.Veto();
1507  return;
1508  };
1509  };
1510  MainFrame::Get()->Close(true);
1511  }
1512  else
1513  {
1514  if (event.CanVeto())
1515  {
1516  event.Veto();
1517  Hide();
1518  DEBUG_DEBUG("hiding");
1519  }
1520  else
1521  {
1522  DEBUG_DEBUG("closing");
1523  this->Destroy();
1524  }
1525  };
1526 }
1527 
1528 #if 0
1529 // need to add the wxChoice somewhere
1530 void PreviewFrame::OnProjectionChanged()
1531 {
1532  PanoramaOptions opt = m_pano.getOptions();
1533  int lt = m_ProjectionChoice->GetSelection();
1534  wxString Ip;
1535  switch ( lt ) {
1536  case PanoramaOptions::RECTILINEAR: Ip = _("Rectilinear"); break;
1537  case PanoramaOptions::CYLINDRICAL: Ip = _("Cylindrical"); break;
1538  case PanoramaOptions::EQUIRECTANGULAR: Ip = _("Equirectangular"); break;
1539  }
1540  opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
1542  new PanoCommand::SetPanoOptionsCmd( pano, opt )
1543  );
1544  DEBUG_DEBUG ("Projection changed: " << lt << ":" << Ip )
1545 
1546 
1547 }
1548 #endif
1549 
1551 {
1552  if (m_pano.getActiveImages().empty()) return;
1553 
1554  // reset zoom so that full pano is visible
1555  ResetPreviewZoom();
1558  );
1559 }
1560 
1561 void GLPreviewFrame::OnStraighten(wxCommandEvent & e)
1562 {
1563  if (m_pano.getNrOfImages() == 0) return;
1564 
1567  );
1568 }
1569 
1570 void GLPreviewFrame::OnFitPano(wxCommandEvent & e)
1571 {
1572  if (m_pano.getActiveImages().empty()) return;
1573 
1574  DEBUG_TRACE("");
1577  fitPano.run();
1578  opt.setHFOV(fitPano.getResultHorizontalFOV());
1580 
1581  // reset zoom so that full pano is visible
1582  ResetPreviewZoom();
1583 
1586  );
1587 
1588  DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
1589 }
1590 
1591 void GLPreviewFrame::OnShowAll(wxCommandEvent & e)
1592 {
1593  if (m_pano.getNrOfImages() == 0) return;
1594 
1595  HuginBase::UIntSet displayedImgs;
1597  {
1598  fill_set(displayedImgs, 0, m_pano.getNrOfImages() - 1);
1599  }
1600  else
1601  {
1603  {
1604  displayedImgs = m_pano.getActiveImages();
1605  };
1606  std::vector<HuginBase::UIntVector> stackedImg = HuginBase::getSortedStacks(&m_pano);
1607  for (size_t i = 0; i < stackedImg.size(); ++i)
1608  {
1609  switch (m_selectAllMode)
1610  {
1612  displayedImgs.insert(*(stackedImg[i].rbegin()));
1613  break;
1614  case SELECT_DARKEST_IMAGES:
1615  displayedImgs.insert(*(stackedImg[i].begin()));
1616  break;
1617  case SELECT_MEDIAN_IMAGES:
1618  default:
1619  displayedImgs.insert(stackedImg[i][stackedImg[i].size() / 2]);
1620  break;
1621  };
1622  };
1623  };
1625  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
1626  );
1627 }
1628 
1629 void GLPreviewFrame::OnShowNone(wxCommandEvent & e)
1630 {
1631  if (m_pano.getNrOfImages() == 0) return;
1632 
1634  for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
1635  m_ToggleButtons[i]->SetValue(false);
1636  }
1637  HuginBase::UIntSet displayedImgs;
1639  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
1640  );
1641 }
1642 
1643 void GLPreviewFrame::OnNumTransform(wxCommandEvent & e)
1644 {
1645  if (m_pano.getNrOfImages() == 0) return;
1646 
1647  wxString text;
1648  double y;
1649  double p;
1650  double r;
1651  double x;
1652  double z;
1653 
1654  int index = m_DragModeChoice->GetSelection();
1655  switch (index) {
1656  case 0: //normal
1657  case 1: //normal, individual
1658  //@TODO limit numeric transform to selected images
1659  text = XRCCTRL(*this,"input_yaw",wxTextCtrl)->GetValue();
1660  if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1661  {
1662  wxBell();
1663  wxMessageBox(_("Yaw value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1664  return;
1665  }
1666  text = XRCCTRL(*this,"input_pitch",wxTextCtrl)->GetValue();
1667  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), p))
1668  {
1669  wxBell();
1670  wxMessageBox(_("Pitch value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1671  return;
1672  }
1673  text = XRCCTRL(*this,"input_roll",wxTextCtrl)->GetValue();
1674  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), r))
1675  {
1676  wxBell();
1677  wxMessageBox(_("Roll value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1678  return;
1679  }
1681  new PanoCommand::RotatePanoCmd(m_pano, y, p, r)
1682  );
1683  break;
1684  case 2: //mosaic
1685  case 3: //mosaic, individual
1686  //@TODO limit numeric transform to selected images
1687  text = XRCCTRL(*this,"input_x",wxTextCtrl)->GetValue();
1688  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), x))
1689  {
1690  wxBell();
1691  wxMessageBox(_("X value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1692  return;
1693  }
1694  text = XRCCTRL(*this,"input_y",wxTextCtrl)->GetValue();
1695  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1696  {
1697  wxBell();
1698  wxMessageBox(_("Y value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1699  return;
1700  }
1701  text = XRCCTRL(*this,"input_z",wxTextCtrl)->GetValue();
1702  if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), z))
1703  {
1704  wxBell();
1705  wxMessageBox(_("Z value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1706  return;
1707  }
1710  );
1711  break;
1712  }
1713 }
1714 
1715 void GLPreviewFrame::OnExposureChanged(wxCommandEvent & e)
1716 {
1718  // exposure
1719  wxString text = m_exposureTextCtrl->GetValue();
1720  DEBUG_INFO ("target exposure = " << text.mb_str(wxConvLocal) );
1721  double p = 0;
1722  if (text != wxT("")) {
1723  if (!hugin_utils::str2double(text, p)) {
1724  wxLogError(_("Value must be numeric."));
1725  return;
1726  }
1727  }
1728  opts.outputExposureValue = p;
1731  );
1732 }
1733 
1735 {
1740  );
1741 }
1742 
1744 {
1749  );
1750 }
1751 
1753 {
1755  // range compression
1756  const wxString text = m_rangeCompressionTextCtrl->GetValue();
1757  if (!text.IsEmpty())
1758  {
1759  double p = 0;
1760  if (!hugin_utils::str2double(text, p))
1761  {
1762  wxLogError(_("Value must be numeric."));
1763  return;
1764  };
1765  if (p < 0 || p>20)
1766  {
1767  wxLogError(_("Value for range compression is outside of valid range."));
1768  return;
1769  };
1770  if (p != opts.outputRangeCompression)
1771  {
1772  opts.outputRangeCompression = p;
1775  );
1776  };
1777  };
1778 }
1779 
1780 
1782 {
1784  int nParam = opts.m_projFeatures.numberOfParameters;
1785  std::vector<double> para = opts.getProjectionParameters();
1786  for (int i = 0; i < nParam; i++) {
1787  if (e.GetEventObject() == m_projParamTextCtrl[i]) {
1788  wxString text = m_projParamTextCtrl[i]->GetValue();
1789  DEBUG_INFO ("param " << i << ": = " << text.mb_str(wxConvLocal) );
1790  double p = 0;
1791  if (text != wxT("")) {
1792  if (!hugin_utils::str2double(text, p)) {
1793  wxLogError(_("Value must be numeric."));
1794  return;
1795  }
1796  }
1797  para[i] = p;
1798  }
1799  }
1800  opts.setProjectionParameters(para);
1803  );
1804 }
1805 
1807 {
1812  );
1813 };
1814 
1815 void GLPreviewFrame::OnChangeFOV(wxScrollEvent & e)
1816 {
1817  DEBUG_TRACE("");
1818 
1820 
1821  if (e.GetEventObject() == m_HFOVSlider) {
1822  DEBUG_DEBUG("HFOV changed (slider): " << e.GetInt() << " == " << m_HFOVSlider->GetValue());
1823  opt.setHFOV(e.GetInt());
1824  } else if (e.GetEventObject() == m_VFOVSlider) {
1825  DEBUG_DEBUG("VFOV changed (slider): " << e.GetInt());
1826  opt.setVFOV(e.GetInt());
1827  } else if (e.GetEventObject() == XRCCTRL(*this,"layout_scale_slider",wxSlider)) {
1828  DEBUG_DEBUG("Layout scale changed (slider): " << e.GetInt());
1830  } else {
1831  int nParam = opt.m_projFeatures.numberOfParameters;
1832  std::vector<double> para = opt.getProjectionParameters();
1833  for (int i = 0; i < nParam; i++) {
1834  if (e.GetEventObject() == m_projParamSlider[i]) {
1835  // update
1836  para[i] = e.GetInt();
1837  break;
1838  }
1839  }
1840  opt.setProjectionParameters(para);
1841  opt.setHFOV(m_HFOVSlider->GetValue());
1842  opt.setVFOV(m_VFOVSlider->GetValue());
1843  }
1844 
1847  );
1848 }
1849 
1850 void GLPreviewFrame::OnTrackChangeFOV(wxScrollEvent & e)
1851 {
1852  DEBUG_TRACE("");
1853  DEBUG_TRACE("fov change " << e.GetInt());
1855 
1856  if (e.GetEventObject() == m_HFOVSlider) {
1857  opt.setHFOV(e.GetInt());
1858  } else if (e.GetEventObject() == m_VFOVSlider) {
1859  opt.setVFOV(e.GetInt());
1860  } else {
1861  int nParam = opt.m_projFeatures.numberOfParameters;
1862  std::vector<double> para = opt.getProjectionParameters();
1863  for (int i = 0; i < nParam; i++) {
1864  if (e.GetEventObject() == m_projParamSlider[i]) {
1865  // update
1866  para[i] = e.GetInt();
1867  m_projParamTextCtrl[i]->ChangeValue(wxString::Format("%d", e.GetInt()));
1868  break;
1869  }
1870  }
1871  opt.setProjectionParameters(para);
1872  }
1873  // we only actually update the panorama fully when the mouse is released.
1874  // As we are dragging it we don't want to create undo events, but we would
1875  // like to update the display, so we change the GLViewer's ViewState and
1876  // request a redraw.
1878  m_GLPreview->Refresh();
1879 }
1880 
1881 void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e)
1882 {
1883  if (e.GetEventObject() == m_BlendModeChoice)
1884  {
1885  updateBlendMode();
1886  }
1887  else
1888  {
1889  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
1890  }
1891 }
1892 
1893 void GLPreviewFrame::OnDragChoice(wxCommandEvent & e)
1894 {
1895  if (drag_tool)
1896  {
1898  int index = m_DragModeChoice->GetSelection();
1899  switch (index) {
1900  case 0: //normal
1901  case 1:
1902  newDragMode=DragTool::drag_mode_normal;
1903  break;
1904  case 2: //mosaic
1905  case 3:
1906  newDragMode=DragTool::drag_mode_mosaic;
1907  break;
1908  }
1909  if(newDragMode==DragTool::drag_mode_mosaic)
1910  {
1912  {
1913  if(wxMessageBox(_("The mosaic/plane mode works only correct for a remapping plane of yaw=0 and pitch=0.\nBut your project has non-zero Tpy and Tpp parameters.\nShould the Tpy and Tpp parameters reset to zero?"),
1914 #ifdef __WXMSW__
1915  _("Hugin"),
1916 #else
1917  wxEmptyString,
1918 #endif
1919  wxYES_NO | wxICON_QUESTION, this) == wxYES)
1920  {
1922  }
1923  else
1924  {
1925  m_DragModeChoice->SetSelection(index-2);
1926  return;
1927  };
1928  };
1929  //switch overview mode to plane
1930  UpdateOverviewMode(1);
1931  m_OverviewModeChoice->SetSelection(1);
1932  }
1933  else
1934  {
1935  //new mode is normal
1936  //set overview back to panosphere mode
1937  UpdateOverviewMode(0);
1938  m_OverviewModeChoice->SetSelection(0);
1941  };
1942  //update drag mode
1943  drag_tool->setDragMode(newDragMode);
1945  // adjust the layout
1946  DragChoiceLayout(index);
1947  };
1948 };
1949 
1951 {
1952  size_t nr = m_pano.getNrOfImages();
1953  for (size_t i = 0 ; i < nr; i++)
1954  {
1955  if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
1956  m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
1957  {
1958  return true;
1959  };
1960  }
1961  return false;
1962 };
1963 
1965 {
1966  HuginBase::UIntSet imgs;
1968  size_t nr = newPan.getNrOfImages();
1969  for (size_t i = 0 ; i < nr ; i++)
1970  {
1971  HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
1972  img.setTranslationPlaneYaw(0);
1973  img.setTranslationPlanePitch(0);
1974  newPan.setSrcImage(i,img);
1975  imgs.insert(i);
1976  }
1979  );
1980 };
1981 
1983 {
1985  if (newMode == 1)
1986  {
1987  newOverviewMode = GLOverview::PANOSPHERE_INSIDE;
1988  }
1989  else
1990  {
1991  if (newMode == 2)
1992  {
1993  newOverviewMode = GLOverview::PLANE;
1994  };
1995  };
1996  if(m_GLOverview->GetMode()==newOverviewMode)
1997  {
1998  return true;
1999  };
2000  if (newOverviewMode == GLOverview::PLANE)
2001  {
2003  {
2005  return true;
2006  }
2007  else
2008  {
2009  if(wxMessageBox(_("The mosaic/plane mode works only correct for a remapping plane of yaw=0 and pitch=0.\nBut your project has non-zero Tpy and Tpp parameters.\nShould the Tpy and Tpp parameters reset to zero?"),
2010 #ifdef __WXMSW__
2011  _("Hugin"),
2012 #else
2013  wxEmptyString,
2014 #endif
2015  wxYES_NO | wxICON_QUESTION, this) == wxYES)
2016  {
2019  return true;
2020  }
2021  else
2022  {
2023  return false;
2024  };
2025  };
2026  }
2027  else
2028  {
2029  m_GLOverview->SetMode(newOverviewMode);
2030  return true;
2031  }
2032 };
2033 
2034 void GLPreviewFrame::OnOverviewModeChoice( wxCommandEvent & e)
2035 {
2036  if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
2037  {
2040  //set drag mode to normal if new mode is panosphere mode
2042  {
2043  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
2044  OnDragChoice(e);
2045  };
2046  }
2047  else
2048  {
2049  //change mode was not successful or canceled by user, set mode choice back
2050  switch (m_GLOverview->GetMode())
2051  {
2053  m_OverviewModeChoice->SetSelection(0);
2054  break;
2056  m_OverviewModeChoice->SetSelection(1);
2057  break;
2058  case GLOverview::PLANE:
2059  m_OverviewModeChoice->SetSelection(2);
2060  break;
2061  };
2062  };
2063 };
2064 
2066 {
2067  // visibility of controls based on selected drag mode
2068  bool normalMode=index==0 || index==1;
2069  XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
2070  XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
2071  XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
2072  XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
2073  XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
2074  XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
2075  XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
2076  XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
2077  XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
2078  XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
2079  XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
2080  XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
2081  // redraw layout to compress empty space
2082  XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
2083 }
2084 
2085 void GLPreviewFrame::OnDefaultExposure( wxCommandEvent & e )
2086 {
2087  if (m_pano.getActiveImages().size() > 0) {
2092  );
2093  }
2094 }
2095 
2096 void GLPreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
2097 {
2099  opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
2102  );
2103 }
2104 
2105 void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
2106 {
2108  opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
2111  );
2112 }
2113 
2114 void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
2115 {
2116  if (e.GetEventObject() == m_ProjectionChoice) {
2118  int lt = m_ProjectionChoice->GetSelection();
2119  wxString Ip;
2123  );
2124  DEBUG_DEBUG ("Projection changed: " << lt);
2125  m_projection_panel->Layout();
2126  Refresh();
2127  } else {
2128  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2129  }
2130 }
2131 
2132 /* We don't have an OpenGL hdr display yet
2133 void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
2134 {
2135  if (e.GetEventObject() == m_outputModeChoice) {
2136  PanoramaOptions opt = m_pano.getOptions();
2137  int lt = m_outputModeChoice->GetSelection();
2138  wxString Ip;
2139  opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
2140  PanoCommand::GlobalCmdHist::getInstance().addCommand(
2141  new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
2142  );
2143 
2144  } else {
2145  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2146  }
2147 }
2148 */
2149 
2150 void GLPreviewFrame::SetStatusMessage(wxString message)
2151 {
2152  SetStatusText(message, 0);
2153 }
2154 
2155 void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
2156 {
2157  m_GLPreview->SetPhotometricCorrect(e.IsChecked());
2158 }
2159 
2161 {
2162  // create the tool objects.
2163  // we delay this until we have an OpenGL context so that they are free to
2164  // create texture objects and display lists before they are used.
2165  preview_helper = preview_helper_in;
2176  preview_control_point_tool = new PreviewControlPointTool(preview_helper);
2178 
2180  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2181  {
2183  };
2186 
2187  // activate tools that are always active.
2189  // update the blend mode which activates some tools
2190  updateBlendMode();
2192  // update toolbar
2194 }
2195 
2197 {
2198  panosphere_overview_helper = panosphere_overview_helper_in;
2204 
2207 
2209  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2210  {
2212  }
2213 
2214 
2218 
2221 
2222 
2223 
2224 }
2225 
2227 {
2228  plane_overview_helper = plane_overview_helper_in;
2231 
2235 
2238 
2241 
2242 }
2243 
2244 void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
2245 {
2246  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2247  if (e.IsChecked())
2248  {
2249  m_BlendModeChoice->SetSelection(0);
2256 // TurnOffTools(preview_helper->ActivateTool(identify_tool));
2257 // TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
2258 // TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
2259  } else {
2260  identify_tool->setConstantOn(false);
2263 // preview_helper->DeactivateTool(identify_tool);
2264 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2265 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2267  }
2268  m_GLPreview->Refresh();
2269  m_GLOverview->Refresh();
2270 }
2271 
2272 void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
2273 {
2274  if (!m_editCP_togglebutton->GetValue())
2275  {
2276  //process event only if edit cp tool is disabled
2277  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2278  if (e.IsChecked())
2279  {
2280  TurnOffTools(preview_helper->ActivateTool(preview_control_point_tool));
2283  }
2284  else {
2285  preview_helper->DeactivateTool(preview_control_point_tool);
2288  }
2289  m_GLPreview->Refresh();
2290  m_GLOverview->Refresh();
2291  };
2292 }
2293 
2294 void GLPreviewFrame::TurnOffTools(std::set<Tool*> tools)
2295 {
2296  std::set<Tool*>::iterator i;
2297  for (i = tools.begin(); i != tools.end(); ++i)
2298  {
2299  if (*i == crop_tool)
2300  {
2301  // cover up the guidelines
2302  m_GLPreview->Refresh();
2303  } else if (*i == drag_tool)
2304  {
2305  // cover up its boxes
2306  m_GLPreview->Refresh();
2307  } else if (*i == identify_tool)
2308  {
2309  // disabled the identify tool, toggle its button off.
2310  m_identify_togglebutton->SetValue(false);
2311  // cover up its indicators and restore normal button colours.
2312  m_GLPreview->Refresh();
2313  m_GLOverview->Refresh();
2315  } else if (*i == preview_control_point_tool)
2316  {
2317  // disabled the control point tool.
2318  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2319  // cover up the control point lines.
2320  m_GLPreview->Refresh();
2321  m_GLOverview->Refresh();
2322  }
2323  }
2324 }
2325 
2326 void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr,
2327  unsigned char red,
2328  unsigned char green,
2329  unsigned char blue)
2330 {
2331  // 0, 0, 0 indicates we want to go back to the system colour.
2332  // TODO: Maybe we should test this better on different themes.
2333 #if defined __WXMSW__ || defined __WXMAC__
2334  if (red || green || blue)
2335  {
2336  // the identify tool wants us to highlight an image button in the given
2337  // colour, to match up with the display in the preview.
2338  // on windows change the color of the surhugin_utils::rounding wxPanel
2339  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2340  }
2341  else
2342  {
2343  // return to the normal colour
2344  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(m_ToggleButtonPanel[image_nr]->GetParent()->GetBackgroundColour());
2345  }
2346  m_ToggleButtonPanel[image_nr]->Refresh();
2347 #else
2348  if (red || green || blue)
2349  {
2350  // change the color of the wxToggleButton
2351  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
2352  m_ToggleButtons[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2353  // black should be visible on the button's vibrant colours.
2354  m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
2355  }
2356  else
2357  {
2358  // return to the normal colour
2359  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2360  m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
2361  m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
2362  };
2363  m_ToggleButtons[image_nr]->Refresh();
2364 #endif
2365 }
2366 
2368 {
2369  // when we turn off the identification tool, any buttons that were coloured
2370  // to match the image in the preview should be given back the system themed
2371  // colours.
2372  unsigned int nr_images = m_pano.getNrOfImages();
2373  for (unsigned image = 0; image < nr_images; image++)
2374  {
2375 #if defined __WXMSW__ || defined __WXMAC__
2376  m_ToggleButtonPanel[image]->SetBackgroundColour(m_ToggleButtonPanel[image]->GetParent()->GetBackgroundColour());
2377  m_ToggleButtonPanel[image]->Refresh();
2378 #else
2379  m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2380  m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
2381  m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
2382  m_ToggleButtons[image]->Refresh();
2383 #endif
2384  }
2385 }
2386 
2387 void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
2388 {
2389  // blank status text as it refers to an old tool.
2390  SetStatusText(wxT(""), 0);
2391  if (e.IsChecked())
2392  {
2393  // deactivate delete cp tool if active
2395  m_editCP_togglebutton->SetValue(false);
2397  }
2398  else
2399  {
2401  };
2402  m_GLPreview->Refresh();
2403 };
2404 
2405 void GLPreviewFrame::UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
2406 {
2408  new PanoCommand::UpdateWhiteBalance(m_pano, redFactor, blueFactor)
2409  );
2410  //now toggle button and deactivate tool
2411  m_colorpicker_togglebutton->SetValue(false);
2412  //direct deactivation of tool does not work because this function is called by the tool itself
2413  //so we are send an event to deactivate the tool
2414  wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, XRCID("preview_color_picker_tool"));
2415  e.SetInt(0);
2416  GetEventHandler()->AddPendingEvent(e);
2417 };
2418 
2419 void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
2420 {
2421  // blank status text as it refers to an old tool.
2422  SetStatusText(wxT(""), 0);
2423  if (e.IsChecked())
2424  {
2425  // deactivate color picker tool
2427  m_colorpicker_togglebutton->SetValue(false);
2428  // show automatically all cp
2429  preview_helper->ActivateTool(preview_control_point_tool);
2431  }
2432  else
2433  {
2434  if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
2435  {
2436  preview_helper->DeactivateTool(preview_control_point_tool);
2437  };
2439  };
2440  m_GLPreview->Refresh();
2441 };
2442 
2444  unsigned int image_number_in,
2445  wxToggleButton* identify_button_in,
2446  HuginBase::Panorama * m_pano_in)
2447 {
2448  image_number = image_number_in;
2449  m_identify_button = identify_button_in;
2450  m_pano = m_pano_in;
2451 }
2452 
2454 {
2455  // When using the identify tool, we want to identify image locations when
2456  // the user moves the mouse over the image buttons, but only if the image
2457  // is being shown.
2458  if (
2459  m_identify_button->GetValue() &&
2461  {
2462  std::vector<PreviewIdentifyTool**>::iterator it;
2463  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2464  (*(*it))->ShowImageNumber(image_number);
2465  }
2466  }
2467  e.Skip();
2468 }
2469 
2471 {
2472  // if the mouse left one of the image toggle buttons with the identification
2473  // tool active, we should stop showing the image indicator for that button.
2474  if (
2475  m_identify_button->GetValue() &&
2477  {
2478  std::vector<PreviewIdentifyTool**>::iterator it;
2479  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2480  (*(*it))->StopShowingImages();
2481  }
2482  }
2483  e.Skip();
2484 }
2485 
2487 {
2488  // the user is turning on or off an image using its button. We want to turn
2489  // the indicators on and off if appropriate correctly to. We use OnEnter
2490  // and OnLeave for the indicators, but these only work when the image is
2491  // showing, so we are carefull of the order:
2492  HuginBase::UIntSet activeImages = m_pano->getActiveImages();
2493  wxMouseEvent null_event;
2494  if (e.IsChecked()) {
2495  activeImages.insert(image_number);
2497  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2498  );
2499  OnEnter(null_event);
2500  } else {
2501  OnLeave(null_event);
2502  activeImages.erase(image_number);
2504  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2505  );
2506  }
2507 }
2508 
2510  identify_tools.push_back(identify_tool_in);
2511 }
2512 
2513 ImageGroupButtonEventHandler::ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame* frame_in, HuginBase::Panorama* m_pano)
2514  : image_number(image_number), frame(frame_in), m_pano(m_pano) {}
2515 
2517  identify_tools.push_back(identify_tool_in);
2518 }
2519 
2520 
2522 {
2523  //mark the image
2524  if (m_pano->getActiveImages().count(image_number))
2525  {
2526  std::vector<PreviewIdentifyTool**>::iterator it;
2527  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2528  (*(*it))->ShowImageNumber(image_number);
2529  }
2530  }
2531  e.Skip();
2532 }
2533 
2535 {
2536  //unmark the image
2537  if (m_pano->getActiveImages().count(image_number))
2538  {
2539  std::vector<PreviewIdentifyTool**>::iterator it;
2540  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2541  (*(*it))->StopShowingImages();
2542  }
2543  }
2544  e.Skip();
2545 }
2546 
2548 {
2549  wxMouseEvent null_event;
2550  if (e.IsChecked()) {
2552  OnEnter(null_event);
2553  } else {
2554  OnLeave(null_event);
2556  }
2557 }
2558 
2560  drag_tools.push_back(drag_tool_in);
2561 }
2562 
2564 {
2565  return m_DragModeChoice->GetSelection()==1 ||
2566  m_DragModeChoice->GetSelection()==3;
2567 }
2568 
2569 void GLPreviewFrame::ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box) {
2570  if (imageDragGroup.count(image_nr) == 0) {
2571  this->AddImageToDragGroup(image_nr, update_check_box);
2572  } else {
2573  this->RemoveImageFromDragGroup(image_nr, update_check_box);
2574  }
2575 }
2576 void GLPreviewFrame::RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box) {
2577  imageDragGroup.erase(image_nr);
2578  if (update_check_box) {
2579  m_GroupToggleButtons[image_nr]->SetValue(false);
2580  }
2581 }
2582 void GLPreviewFrame::AddImageToDragGroup(unsigned int image_nr, bool update_check_box) {
2583  imageDragGroup.insert(image_nr);
2584  if (update_check_box) {
2585  m_GroupToggleButtons[image_nr]->SetValue(true);
2586  }
2587 }
2588 void GLPreviewFrame::SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box) {
2589  imageDragGroup.swap(imageDragGroup_in);
2590  std::vector<wxCheckBox*>::iterator it;
2591  unsigned int nr = 0;
2592  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2593  (*it)->SetValue(imageDragGroup.count(nr++)>0);
2594  }
2595 }
2597  return imageDragGroup;
2598 }
2599 void GLPreviewFrame::ClearDragGroupImages(bool update_check_box) {
2600  imageDragGroup.clear();
2601  std::vector<wxCheckBox*>::iterator it;
2602  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2603  (*it)->SetValue(false);
2604  }
2605 }
2606 
2608 {
2609  std::vector<wxCheckBox*>::iterator it;
2610  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
2611  {
2612  (*it)->Show(isShown);
2613  }
2614  Layout();
2615 };
2616 
2619 {
2621  m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
2622  // update size
2623  m_BlendModeChoice->InvalidateBestSize();
2624  m_BlendModeChoice->GetParent()->Layout();
2625  Refresh();
2626  // get blend mode last state
2627  unsigned int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l);
2628  // limit old state to max available states
2629  if (oldMode >= m_BlendModeChoice->GetCount())
2630  {
2631  oldMode = 0;
2632  }
2633  m_BlendModeChoice->SetSelection(oldMode);
2634  updateBlendMode();
2635 };
2636 
2637 void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
2638 {
2639  DEBUG_INFO("Dirty ROI Calc\n");
2640  if (m_pano.getActiveImages().empty())
2641  {
2642  return;
2643  };
2644 
2645  vigra::Rect2D newROI;
2646  {
2647  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2648  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2649  cropPano.run();
2650  if (cropPano.hasRunSuccessfully())
2651  {
2652  newROI = cropPano.getResultOptimalROI();
2653  };
2654  };
2655 
2656  //set the ROI - fail if the right/bottom is zero, meaning all zero
2657  if(!newROI.isEmpty())
2658  {
2660  opt.setROI(newROI);
2663  );
2664  }
2665 }
2666 
2667 void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
2668 {
2669  DEBUG_INFO("Dirty ROI Calc\n");
2670  if (m_pano.getActiveImages().empty())
2671  {
2672  return;
2673  };
2674 
2675  vigra::Rect2D newROI;
2676  {
2677  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2678  HuginBase::UIntSet activeImages = m_pano.getActiveImages();
2679  std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
2680  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2681  //only use hdr autocrop for projects with stacks
2682  //otherwise fall back to "normal" autocrop
2683  if (stackImgs.size()<activeImages.size())
2684  {
2685  cropPano.setStacks(stackImgs);
2686  }
2687  cropPano.run();
2688  if (cropPano.hasRunSuccessfully())
2689  {
2690  newROI = cropPano.getResultOptimalROI();
2691  };
2692  };
2693 
2694  //set the ROI - fail if the right/bottom is zero, meaning all zero
2695  if(!newROI.isEmpty())
2696  {
2698  opt.setROI(newROI);
2701  );
2702  }
2703 }
2704 
2705 void GLPreviewFrame::OnAutocropOutside(wxCommandEvent& e)
2706 {
2707  DEBUG_INFO("Dirty ROI Calc\n");
2708  if (m_pano.getActiveImages().empty())
2709  {
2710  return;
2711  };
2712 
2713  vigra::Rect2D newROI;
2714  {
2715  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2716  HuginBase::CalculateOptimalROIOutside cropPano(m_pano, &progress);
2717  cropPano.run();
2718  if (cropPano.hasRunSuccessfully())
2719  {
2720  newROI = cropPano.getResultOptimalROI();
2721  };
2722  };
2723 
2724  //set the ROI - fail if the right/bottom is zero, meaning all zero
2725  if (!newROI.isEmpty())
2726  {
2728  opt.setROI(newROI);
2731  );
2732  }
2733 }
2734 
2735 void GLPreviewFrame::OnFullScreen(wxCommandEvent & e)
2736 {
2737  ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
2738 };
2739 
2740 void GLPreviewFrame::SetMode(int newMode)
2741 {
2742  if(m_mode==newMode)
2743  return;
2744  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2745  switch(m_mode)
2746  {
2747  case mode_assistant:
2748  case mode_preview:
2749  // switch off identify and show cp tool
2750  identify_tool->setConstantOn(false);
2754  m_colorpicker_togglebutton->SetValue(false);
2755 // preview_helper->DeactivateTool(identify_tool);
2756 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2757 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2759  m_editCP_togglebutton->SetValue(false);
2760 
2762  m_identify_togglebutton->SetValue(false);
2763  preview_helper->DeactivateTool(preview_control_point_tool);
2766  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2767  break;
2768  case mode_layout:
2769  // disable layout mode.
2773  // reactivate identify and camera tool when leaving layout mode
2778  m_GLPreview->SetLayoutMode(false);
2779  m_GLOverview->SetLayoutMode(false);
2780  // Switch the panorama mask back on.
2782  //restore blend mode
2784  updateBlendMode();
2785  break;
2786  case mode_projection:
2788  break;
2789  case mode_drag:
2793  if (individualDragging()) {
2794  std::vector<wxCheckBox*>::iterator it;
2795  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2796  (*it)->Show(false);
2797  }
2798  }
2799  break;
2800  case mode_crop:
2804  break;
2805  };
2806  m_mode=newMode;
2807  wxScrollEvent dummy;
2808  switch(m_mode)
2809  {
2810  case mode_assistant:
2811  case mode_preview:
2812  break;
2813  case mode_layout:
2814  //save blend mode setting, set to normal for layout mode
2815  non_layout_blend_mode=m_BlendModeChoice->GetSelection();
2816  m_BlendModeChoice->SetSelection(0);
2817  updateBlendMode();
2818  // turn off things not used in layout mode.
2821  // deactivate identify tool in layout mode
2825  m_GLPreview->SetLayoutMode(true);
2826  m_GLOverview->SetLayoutMode(true);
2830  // we need to update the meshes after switch to layout mode
2831  // otherwise the following update of scale has no meshes to scale
2832  m_GLPreview->Update();
2833  m_GLOverview->Update();
2834  OnLayoutScaleChange(dummy);
2835  break;
2836  case mode_projection:
2838  break;
2839  case mode_drag:
2843  if (individualDragging()) {
2844  std::vector<wxCheckBox*>::iterator it;
2845  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2846  (*it)->Show(true);
2847  }
2848  }
2849  break;
2850  case mode_crop:
2854  break;
2855  };
2856  //enable group checkboxes only for drag mode tab
2858  m_GLPreview->Refresh();
2859 };
2860 
2861 void GLPreviewFrame::OnSelectMode(wxNotebookEvent &e)
2862 {
2863  if(m_mode!=-1)
2864  SetMode(e.GetSelection());
2865 };
2866 
2867 void GLPreviewFrame::OnToolModeChanging(wxNotebookEvent &e)
2868 {
2869  if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
2870  {
2871  wxBell();
2872  e.Veto();
2873  };
2874 };
2875 
2876 void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
2877 {
2879  long left, right, top, bottom;
2880  if (!m_ROITopTxt->GetValue().ToLong(&top)) {
2881  wxLogError(_("Top needs to be an integer bigger than 0"));
2882  return;
2883  }
2884  if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
2885  wxLogError(_("left needs to be an integer bigger than 0"));
2886  return;
2887  }
2888  if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
2889  wxLogError(_("right needs to be an integer bigger than 0"));
2890  return;
2891  }
2892  if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
2893  wxLogError(_("bottom needs to be an integer bigger than 0"));
2894  return;
2895  }
2896  opt.setROI(vigra::Rect2D(left, top, right, bottom));
2897  // make sure that left is really to the left of right
2898  if(opt.getROI().width()<1) {
2899  wxLogError(_("left boundary must be smaller than right"));
2901  return;
2902  }
2903  // make sure that top is really higher than bottom
2904  if(opt.getROI().height()<1) {
2905  wxLogError(_("top boundary must be smaller than bottom"));
2907  return;
2908  }
2909 
2912  );
2913 };
2914 
2915 void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
2916 {
2918  opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
2920 };
2921 
2922 void GLPreviewFrame::OnSetCropAspect(wxCommandEvent& e)
2923 {
2924  // ask user for a setting
2925  SelectAspectRatioDialog dlg(this);
2926  if (dlg.ShowModal() == wxID_OK)
2927  {
2929  const double aspectRatio = dlg.GetSelectedAspectRatio();
2930  // calculate the new ROI, move crop if necessary
2931  int left = opt.getROI().left();
2932  int top = opt.getROI().top();
2933  int width = opt.getROI().width();
2934  int height = opt.getROI().height();
2935  const int newHeight = 1.0 * width / aspectRatio;
2936  if (newHeight > height)
2937  {
2938  const int newWidth = 1.0 * height * aspectRatio;
2939  left = left + (width - newWidth) / 2.0;
2940  width = newWidth;
2941  }
2942  else
2943  {
2944  top = top + (height - newHeight) / 2.0;
2945  height = newHeight;
2946  };
2947  // finally set new crop
2948  opt.setROI(vigra::Rect2D(left, top, left + width, top + height));
2950  };
2951 }
2952 
2953 void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
2954 {
2956 
2957 
2958  wxString text = m_HFOVText->GetValue();
2959  DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
2960  if (text == wxT("")) {
2961  return;
2962  }
2963 
2964  double hfov;
2965  if (!hugin_utils::str2double(text, hfov)) {
2966  wxLogError(_("Value must be numeric."));
2967  return;
2968  }
2969 
2970  if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
2971  wxLogError(wxString::Format(
2972  _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
2973  opt.getMaxHFOV()));
2974  hfov=opt.getMaxHFOV();
2975  }
2976  opt.setHFOV(hfov);
2977  // recalculate panorama height...
2980  );
2981 
2982  DEBUG_INFO ( "new hfov: " << hfov )
2983 };
2984 
2985 void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
2986 {
2988 
2989  wxString text = m_VFOVText->GetValue();
2990  DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
2991  if (text == wxT("")) {
2992  return;
2993  }
2994 
2995  double vfov;
2996  if (!hugin_utils::str2double(text, vfov)) {
2997  wxLogError(_("Value must be numeric."));
2998  return;
2999  }
3000 
3001  if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
3002  wxLogError(wxString::Format(
3003  _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
3004  opt.getMaxVFOV()));
3005  vfov = opt.getMaxVFOV();
3006  }
3007  opt.setVFOV(vfov);
3008  // recalculate panorama height...
3011  );
3012 
3013  DEBUG_INFO ( "new vfov: " << vfov )
3014 };
3015 
3017 {
3018  if(m_mode==mode_layout)
3019  {
3020  double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
3021  m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
3022  m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
3023  m_GLPreview->Refresh();
3024  m_GLOverview->Refresh();
3025  };
3026 };
3027 
3029 {
3031  double hfov = opts.getHFOV();
3032  double vfov = opts.getVFOV();
3033  double maxfov = hfov > vfov ? hfov : vfov;
3034  wxString message;
3035  // If this is set to true, offer rectilinear as an alternative if it fits.
3036  bool rectilinear_option = false;
3037  switch (opts.getProjection()) {
3039  if (maxfov > 120.0) {
3040  // wide rectilinear image
3041  message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
3042  if (vfov < 110) {
3043  message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
3044  } else {
3045  message += _("For a very wide panorama, try equirectangular projection instead.");
3046  }
3047  message += wxT(" ");
3048  message += _("You could also try Panini projection.");
3049  }
3050  break;
3052  if (vfov > 120.0) {
3053  message = _("With a wide vertical field of view, panoramas with cylindrical projection get very stretched at the top and bottom.\nAn equirectangular projection would fit the same content in less vertical space.");
3054  } else rectilinear_option = true;
3055  break;
3057  if (vfov < 110.0 && hfov > 120.0)
3058  {
3059  message = _("Since the vertical field of view is not too wide, you could try setting the panorama projection to cylindrical.\nCylindrical projection preserves vertical lines, unlike equirectangular.");
3060  } else rectilinear_option = true;
3061  break;
3063  if (maxfov < 280.0) {
3064  rectilinear_option = true;
3065  message = _("Stereographic projection is conformal, unlike this Fisheye panorama projection.\nA conformal projection preserves angles around a point, which often makes it easier on the eye.");
3066  }
3067  break;
3069  if (maxfov > 300.0) {
3070  message = _("Panoramas with stereographic projection and a very wide field of view stretch the image around the edges a lot.\nThe Fisheye panorama projection compresses it, so you can fit in a wide field of view and still have a reasonable coverage of the middle.");
3071  } else rectilinear_option = true;
3072  break;
3073  default:
3074  rectilinear_option = true;
3075  }
3076  if (rectilinear_option && maxfov < 110.0) {
3077  message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
3078  }
3079  if (message.IsEmpty()) {
3080  // no message needed.
3081  m_infoBar->Dismiss();
3082  } else {
3083  m_infoBar->ShowMessage(message, wxICON_INFORMATION);
3084  }
3085 };
3086 
3088 {
3089  m_showProjectionHints=new_value;
3091  {
3092  m_infoBar->Dismiss();
3093  };
3094 };
3095 
3097 {
3098  wxMessageBox(_("You have hidden the infobar, which shows hints about selection of projection.\nIf you want to see the bar again, activate the bar in the preferences again."),
3099 #ifdef __WXMSW__
3100  _("Hugin"),
3101 #else
3102  wxT(""),
3103 #endif
3104  wxOK | wxICON_INFORMATION, this);
3105 
3106  wxConfigBase* cfg=wxConfigBase::Get();
3107  cfg->Write(wxT("/GLPreviewFrame/ShowProjectionHints"), false);
3108  m_showProjectionHints=false;
3109  cfg->Flush();
3110  e.Skip();
3111 };
3112 
3113 void GLPreviewFrame::UpdateIdentifyTools(std::set<unsigned int> new_image_set)
3114 {
3115  if(identify_tool)
3116  {
3117  identify_tool->UpdateWithNewImageSet(new_image_set);
3118  };
3120  {
3122  };
3124  {
3126  };
3127 }
3128 
3130  m_preview_background_color = XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->GetColour();
3131  wxString c = m_preview_background_color.GetAsString(wxC2S_HTML_SYNTAX);
3132  wxConfigBase* cfg=wxConfigBase::Get();
3133  cfg->Write(wxT("/GLPreviewFrame/PreviewBackground"), c);
3134  cfg->Flush();
3138  redrawPreview();
3139 }
3140 
3143 }
3144 
3145 void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
3146 {
3147  if(preview_guide_tool)
3148  {
3149  int selection=e.GetSelection();
3151  //synchronize wxChoice in projection and crop tab
3152  m_GuideChoiceCrop->SetSelection(selection);
3153  m_GuideChoiceProj->SetSelection(selection);
3154  m_GuideChoiceDrag->SetSelection(selection);
3155  redrawPreview();
3156  };
3157 };
3158 
3160 {
3161  int old_selection=m_DragModeChoice->GetSelection();
3162  if(old_selection==wxNOT_FOUND)
3163  {
3164  old_selection=0;
3165  };
3166  m_DragModeChoice->Clear();
3167  m_DragModeChoice->Append(_("normal"));
3168  m_DragModeChoice->Append(_("normal, individual"));
3169  if(newLevel==GUI_EXPERT)
3170  {
3171  m_DragModeChoice->Append(_("mosaic"));
3172  m_DragModeChoice->Append(_("mosaic, individual"));
3173  m_DragModeChoice->SetSelection(old_selection);
3174  }
3175  else
3176  {
3177  if(old_selection>1)
3178  {
3179  m_DragModeChoice->SetSelection(old_selection-2);
3180  }
3181  else
3182  {
3183  m_DragModeChoice->SetSelection(old_selection);
3184  };
3185  };
3186  DragChoiceLayout(m_DragModeChoice->GetSelection());
3187  wxCommandEvent dummy;
3188  OnDragChoice(dummy);
3189 
3190  old_selection=m_OverviewModeChoice->GetSelection();
3191  m_OverviewModeChoice->Clear();
3192  m_OverviewModeChoice->Append(_("Panosphere (outside)"));
3193  m_OverviewModeChoice->Append(_("Panosphere (inside)"));
3194  if(newLevel==GUI_EXPERT)
3195  {
3196  m_OverviewModeChoice->Append(_("Mosaic plane"));
3197  };
3198  if(newLevel==GUI_EXPERT && old_selection==2)
3199  {
3200  m_OverviewModeChoice->SetSelection(2);
3201  }
3202  else
3203  {
3205  m_OverviewModeChoice->SetSelection(0);
3206  };
3207  if(newLevel==GUI_SIMPLE)
3208  {
3209 #ifdef __WXMAC__
3210  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
3211 #endif
3212  if(m_guiLevel!=GUI_SIMPLE)
3213  {
3214  GetMenuBar()->Remove(0);
3215  GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
3216  };
3217  SetTitle(MainFrame::Get()->GetTitle());
3218  }
3219  else
3220  {
3221 #ifdef __WXMAC__
3222  wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
3223 #endif
3224  if(m_guiLevel==GUI_SIMPLE)
3225  {
3226  GetMenuBar()->Remove(0);
3227  GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
3228  };
3229  SetTitle(_("Fast Panorama preview"));
3230  };
3231  m_guiLevel=newLevel;
3232  // update menu items
3233  switch(m_guiLevel)
3234  {
3235  case GUI_SIMPLE:
3236  GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
3237  break;
3238  case GUI_ADVANCED:
3239  GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
3240  break;
3241  case GUI_EXPERT:
3242  GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
3243  break;
3244  };
3245 };
3246 
3247 void GLPreviewFrame::AddUserDefinedSequence(int id, const wxString& desc, const wxString& help)
3248 {
3249  if (id == -1)
3250  {
3251  m_createButton->GetSplitButtonMenu()->AppendSeparator();
3252  }
3253  else
3254  {
3255  m_createButton->GetSplitButtonMenu()->Append(id, desc, help);
3256  };
3257 };
3258 
3259 void GLPreviewFrame::AddUserDefinedAssistant(int id, const wxString& desc, const wxString& help)
3260 {
3261  if (id == -1)
3262  {
3263  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
3264  }
3265  else
3266  {
3267  m_alignButton->GetSplitButtonMenu()->Append(id, desc, help);
3268  };
3269 };
3270 
3271 void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
3272 {
3273  MainFrame::Get()->Show();
3274  MainFrame::Get()->Raise();
3275 };
3276 
3277 void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
3278 {
3279  Close();
3280 };
3281 
3283 {
3284  if (wxConfig::Get()->Read(wxT("/ShowFisheyeCropHint"), 1l) == 1)
3285  {
3286  // show hint about crop and open tab when requested
3287  wxDialog dlg;
3288  wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("fisheye_show_crop_dlg"));
3289  if (dlg.ShowModal() == wxID_OK)
3290  {
3291  MainFrame::Get()->ShowMaskEditor(0, true);
3292  };
3293  if (XRCCTRL(dlg, "fisheye_crop_dont_ask_checkbox", wxCheckBox)->IsChecked())
3294  {
3295  wxConfig::Get()->Write(wxT("/ShowFisheyeCropHint"), 0l);
3296  };
3297  };
3298 }
3299 
3300 void GLPreviewFrame::OnLoadImages(wxCommandEvent& e)
3301 {
3302  // load all images with default lens type
3303  LoadImages(-1);
3304 }
3305 
3306 void GLPreviewFrame::LoadImages(int preferredLensType)
3307 {
3308  // load the images.
3309  PanoOperation::AddImageOperation addImage(preferredLensType);
3310  HuginBase::UIntSet images;
3311  PanoCommand::PanoCommand* cmd=addImage.GetCommand(wxGetActiveWindow(), m_pano, images, m_guiLevel);
3312  if(cmd==NULL)
3313  {
3314  return;
3315  }
3316  //distribute images only if the existing images are not connected
3317  //otherwise it would destruct the existing image pattern
3318  const bool distributeImages=m_pano.getNrOfCtrlPoints()==0;
3319 
3320  const long autoAlign = wxConfigBase::Get()->Read(wxT("/Assistant/autoAlign"), HUGIN_ASS_AUTO_ALIGN);
3321  if (autoAlign)
3322  {
3324  wxCommandEvent dummy;
3325  OnAlign(dummy);
3326  }
3327  else
3328  {
3329  std::vector<PanoCommand::PanoCommand*> cmds;
3330  cmds.push_back(cmd);
3331  if(distributeImages)
3332  {
3333  cmds.push_back(new PanoCommand::DistributeImagesCmd(m_pano));
3334  cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
3335  };
3337  combinedCmd->setName("add and distribute images");
3339  if(m_pano.getImage(0).isCircularCrop())
3340  {
3341  // show hint about crop for fisheye images
3342  // skip display if we read the information from our lens database
3343  HuginBase::FileMetaData metaData=m_pano.getImage(0).getFileMetadata();
3344  HuginBase::FileMetaData::const_iterator pos = metaData.find("readProjectionFromDB");
3345  if(!(pos != metaData.end() && pos->second == "true"))
3346  {
3348  };
3349  };
3350  };
3351 }
3352 
3353 void GLPreviewFrame::OnAlign( wxCommandEvent & e )
3354 {
3355  // run default assisant
3356  MainFrame::Get()->RunAssistant(this);
3357 }
3358 
3359 void GLPreviewFrame::OnCreate( wxCommandEvent & e )
3360 {
3361  PanoOutputDialog dlg(this, m_pano, m_guiLevel);
3362  if(dlg.ShowModal()==wxID_OK)
3363  {
3366  );
3367  wxCommandEvent dummy;
3368  MainFrame::Get()->OnDoStitch(dummy);
3369  };
3370 }
3371 
3372 // remove cp, relatively easy, we get the selected cp from the edit cp tool
3373 void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
3374 {
3377  // ask user, if pano should be optimized
3378  long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
3379  bool optimize = false;
3380  if (afterEditCPAction == 0)
3381  {
3382  wxDialog dlg;
3383  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("edit_cp_optimize_dialog"));
3384  XRCCTRL(dlg, "edit_cp_text1", wxStaticText)->SetLabel(wxString::Format(_("%lu control points were removed from the panorama.\n\nShould the panorama now be re-optimized?"), static_cast<unsigned long int>(edit_cp_tool->GetFoundCPs().size())));
3385  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3386  dlg.Fit();
3387  optimize = (dlg.ShowModal() == wxID_OK);
3388  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3389  {
3390  if (optimize)
3391  {
3392  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
3393  }
3394  else
3395  {
3396  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
3397  };
3398  };
3399  }
3400  else
3401  {
3402  optimize = (afterEditCPAction == 1);
3403  }
3404  if (optimize)
3405  {
3406  // invoke optimization routine
3407  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3408  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3409  };
3410 };
3411 
3412 // some helper for cp generation
3413 // maximal width for remapping for cp generating
3414 #define MAX_DIMENSION 1600
3416 {
3417  size_t imgNr;
3418  vigra::BRGBImage image;
3419  vigra::BImage mask;
3420 };
3421 
3422 typedef std::vector<FindStruct> FindVector;
3423 typedef std::multimap<double, vigra::Diff2D> MapPoints;
3424 
3426 
3427 void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
3428 {
3430  vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
3432  // some checking of conditions
3433  if (imgs.empty())
3434  {
3435  wxMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
3436 #ifdef __WXMSW__
3437  _("Hugin"),
3438 #else
3439  wxT(""),
3440 #endif
3441  wxOK | wxICON_INFORMATION, this);
3442  return;
3443  };
3444  if (imgs.size() < 2)
3445  {
3446  wxMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
3447 #ifdef __WXMSW__
3448  _("Hugin"),
3449 #else
3450  wxT(""),
3451 #endif
3452  wxOK | wxICON_INFORMATION, this);
3453  return;
3454  };
3455  if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
3456  {
3457  if(wxMessageBox(_("The selected rectangle is very big.\nThis function is only intended for smaller areas. Otherwise unwanted side effect can appear.\n\nProceed anyway?"),
3458 #ifdef __WXMSW__
3459  _("Hugin"),
3460 #else
3461  wxT(""),
3462 #endif
3463  wxYES_NO | wxICON_INFORMATION, this) == wxNO)
3464  {
3465  return;
3466  };
3467  }
3469  opts.setROI(roi);
3470  // don't correct exposure
3471  opts.outputExposureValue = 0;
3472  // don't use GPU for remapping, this interfere with the fast preview window
3473  opts.remapUsingGPU = false;
3474  // rescale if size is too big
3475  if (roi.width() > MAX_DIMENSION)
3476  {
3477  opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
3478  roi = opts.getROI();
3479  };
3480  HuginBase::CPVector cps;
3481  {
3482  ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
3483  // remap all images to panorama projection
3484  FindVector cpInfos;
3485  HuginBase::CPVector tempCps;
3486  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
3487  {
3488  const size_t imgNr = *it;
3489  if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
3490  {
3491  return;
3492  };
3493  FindStruct findStruct;
3494  findStruct.imgNr = imgNr;
3495  // remap image to panorama projection
3496  ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
3497 
3499  HuginBase::SrcPanoImage srcImg = m_pano.getSrcImage(imgNr);
3500  // don't correct exposure
3501  srcImg.setExposureValue(0);
3502  remapped->setPanoImage(srcImg, opts, roi);
3503  remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
3504  if (!progress.updateDisplay())
3505  {
3506  delete remapped;
3507  return;
3508  };
3509  findStruct.image = remapped->m_image;
3510  findStruct.mask = remapped->m_mask;
3511  delete remapped;
3512  cpInfos.push_back(findStruct);
3513  };
3514  if (cpInfos.size() > 1)
3515  {
3516  // match keypoints in all image pairs
3517  // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
3518  unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
3519  if (gridx < 1)
3520  {
3521  gridx = 1;
3522  }
3523  unsigned gridy = hugin_utils::roundi(25 / gridx);
3524  if (gridy < 1)
3525  {
3526  gridy = 1;
3527  }
3528  while (roi.width() / gridx < 20 && gridx > 1)
3529  {
3530  --gridx;
3531  };
3532  while (roi.height() / gridy < 20 && gridy > 1)
3533  {
3534  --gridy;
3535  };
3536  // template width
3537  const long templWidth = 20;
3538  // search width
3539  const long sWidth = 100;
3540  // match all images with all
3541  for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
3542  {
3543  if (!progress.updateDisplayValue(_("Matching interest points...")))
3544  {
3545  return;
3546  };
3547  vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
3548  // create a number of sub-regions
3549  std::vector<vigra::Rect2D> rects;
3550  for (unsigned party = 0; party < gridy; party++)
3551  {
3552  for (unsigned partx = 0; partx < gridx; partx++)
3553  {
3554  vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
3555  (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
3556  rect &= vigra::Rect2D(size);
3557  if (rect.width()>0 && rect.height()>0)
3558  {
3559  rects.push_back(rect);
3560  };
3561  };
3562  };
3563 
3564  if (!progress.updateDisplay())
3565  {
3566  return;
3567  };
3568 
3569 #pragma omp parallel for schedule(dynamic)
3570  for (int i = 0; i < rects.size(); ++i)
3571  {
3572  MapPoints points;
3573  vigra::Rect2D rect(rects[i]);
3574  // run interest point detection in sub-region
3575  vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
3576  //check if all points are inside the given image
3577  MapPoints validPoints;
3578  for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
3579  {
3580  if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
3581  {
3582  validPoints.insert(*it);
3583  };
3584  };
3585 
3586  if (!validPoints.empty())
3587  {
3588  // now fine-tune the interest points with all other images
3589  for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
3590  {
3591  unsigned nGood = 0;
3592  // loop over all points, starting with the highest corner score
3593  for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
3594  {
3595  if (nGood >= 2)
3596  {
3597  // we have enough points, stop
3598  break;
3599  }
3600  //check if point is covered by second image
3601  if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
3602  {
3603  continue;
3604  };
3605  // finally fine-tune point
3606  vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
3607  cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
3608  if (res.maxi < 0.9)
3609  {
3610  continue;
3611  }
3612  nGood++;
3613  // add control point
3614  {
3615  hugin_omp::ScopedLock sl(cpLock);
3616  tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
3617  cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
3618  };
3619  };
3620  };
3621  };
3622  };
3623  // free memory
3624  cpInfos[img1].image.resize(0, 0);
3625  cpInfos[img1].mask.resize(0, 0);
3626  };
3627 
3628  // transform coordinates back to image space
3629  for (size_t i = 0; i < tempCps.size(); ++i)
3630  {
3631  HuginBase::ControlPoint cp = tempCps[i];
3632  hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
3633  hugin_utils::FDiff2D p1Img;
3634  HuginBase::PTools::Transform transform;
3635  transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
3636  if (transform.transformImgCoord(p1Img, p1))
3637  {
3638  hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
3639  hugin_utils::FDiff2D p2Img;
3640  transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
3641  if (transform.transformImgCoord(p2Img, p2))
3642  {
3643  cp.x1 = p1Img.x;
3644  cp.y1 = p1Img.y;
3645  cp.x2 = p2Img.x;
3646  cp.y2 = p2Img.y;
3647  cps.push_back(cp);
3648  };
3649  };
3650  };
3651 
3652  if (!cps.empty())
3653  {
3654  // check newly found control points
3655  // create copy
3657  // remove all cps and set only the new found cp
3658  copyPano.setCtrlPoints(cps);
3659  // now create a subpano with only the selected images
3660  HuginBase::Panorama subPano = copyPano.getSubset(imgs);
3661  // clean control points
3662  if (!progress.updateDisplayValue(_("Checking results...")))
3663  {
3664  return;
3665  };
3667  HuginBase::UIntSet invalidCP = HuginBase::getCPoutsideLimit(subPano);
3669  if (!invalidCP.empty())
3670  {
3671  for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
3672  {
3673  cps.erase(cps.begin() + *it);
3674  };
3675  }
3676  // force closing progress dialog
3677  if (!progress.updateDisplayValue())
3678  {
3679  return;
3680  };
3682  // ask user, if pano should be optimized
3683  long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
3684  bool optimize = false;
3685  if (afterEditCPAction == 0)
3686  {
3687  // close progress window, otherwise the dialog don't autoamtically get the focus
3688  wxYield();
3689  wxDialog dlg;
3690  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("edit_cp_optimize_dialog"));
3691  XRCCTRL(dlg, "edit_cp_text1", wxStaticText)->SetLabel(wxString::Format(_("%lu control points were added to the panorama.\n\nShould the panorama now be re-optimized?"), static_cast<unsigned long int>(cps.size())));
3692  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3693  dlg.Fit();
3694  optimize = (dlg.ShowModal() == wxID_OK);
3695  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3696  {
3697  if (optimize)
3698  {
3699  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
3700  }
3701  else
3702  {
3703  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
3704  };
3705  };
3706  }
3707  else
3708  {
3709  optimize = (afterEditCPAction == 1);
3710  }
3711  if (optimize)
3712  {
3713  // invoke optimization routine
3714  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3715  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3716  };
3717  };
3718  };
3719  };
3720  // finally redraw
3721  m_GLPreview->Update();
3722  m_GLPreview->Refresh();
3723 };
3724 
3725 // handle menu close event to redraw preview, so that selection rectangle is hidden
3726 void GLPreviewFrame::OnMenuClose(wxMenuEvent & e)
3727 {
3728  m_GLPreview->Refresh();
3729  e.Skip();
3730 };
3731 
3732 void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
3733 {
3734  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
3736 };
3737 
3738 void GLPreviewFrame::OnSelectMedianMenu(wxCommandEvent& e)
3739 {
3740  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 1l);
3742 };
3743 
3745 {
3746  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 2l);
3748 };
3749 
3751 {
3752  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 3l);
3754 };
3755 
3757 {
3758  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), true);
3759  m_selectKeepSelection = true;
3760 };
3761 
3763 {
3764  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), false);
3765  m_selectKeepSelection = false;
3766 };
HuginBase::UIntSet GetDragGroupImages()
AlphaImage m_mask
corresponding alpha channel
Definition: ROIImage.h:274
#define DEBUG_INFO(msg)
Definition: utils.h:69
int floori(double x)
Definition: hugin_math.h:65
void setConstantOn(bool constant_on_in)
tool for the manipulation of the opengl &#39;camera&#39; properties It handles rotation of the camera positio...
wxSlider * m_HFOVSlider
Base class for all panorama commands.
Definition: Command.h:38
wxTextCtrl * m_ROITopTxt
wxTextCtrl * m_rangeCompressionTextCtrl
PlaneOverviewCameraTool * plane_overview_camera_tool
SelectAllMode m_selectAllMode
HuginBase::Panorama & m_pano
Definition: PreviewFrame.h:93
Allow the user to change the cropping region by dragging it in the fast preview.
int gcd(int a, int b)
function to calculate greated common divisor using Euclidean algorithm both arguments should be &gt;=0 ...
Definition: hugin_math.cpp:35
PanoramaOptions::ProjectionFormat getProjection() const
#define HUGIN_SHOW_PROJECTION_HINTS
void OnRangeCompressionDecrease(wxSpinEvent &e)
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks
Definition: LayerStacks.cpp:35
void AddDragTool(DragTool **drag_tool_in)
wxSpinButton * m_exposureSpinBut
implementation of huginApp Class
update variables of a group of images
Definition: PanoCommand.h:174
declaration of functions to handle stacks and layers
std::vector< wxToggleButton * > m_ToggleButtons
void OnRemoveCP(wxCommandEvent &e)
handler to remove cp
PreviewCropTool * crop_tool
void OnControlPoint(wxCommandEvent &e)
PreviewDifferenceTool * panosphere_difference_tool
std::set< Tool * > ActivateTool(Tool *tool)
Definition: ToolHelper.cpp:53
void OnCreate(wxCommandEvent &e)
wxGLContext * GetContext()
Definition: GLViewer.h:78
PreviewIdentifyTool * identify_tool
void SetStatusMessage(wxString message)
The OpenGL preview frame.
void AddIdentifyTool(PreviewIdentifyTool **identify_tool_in)
virtual PanoCommand::PanoCommand * GetCommand(wxWindow *parent, HuginBase::Panorama &pano, HuginBase::UIntSet images, GuiLevel guiLevel)
returns the appropriate PanoCommand::PanoCommand to be inserted into GlobalCmdHistory, checks if operation is enabled
void setHeight(unsigned int h)
set panorama height
void OnIdentify(wxCommandEvent &e)
pano_projection_features m_projFeatures
int roundi(T x)
Definition: hugin_math.h:73
wxChoice * m_DragModeChoice
wxColour GetPreviewBackgroundColor()
void OnShowAll(wxCommandEvent &e)
void StorePositionAndSize()
store position and size of window in wxConfig
#define HUGIN_PREVIEW_BACKGROUND
void setPanoImage(const SrcPanoImage &src, const PanoramaOptions &dest, vigra::Rect2D roi)
static double calcMeanExposure(const PanoramaData &pano)
vigra::BImage mask
wxBoxSizer * m_topsizer
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
void AddUserDefinedAssistant(int id, const wxString &desc, const wxString &help)
adds the given user defined assistant to SplitButton menu
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
PreviewDragTool * drag_tool
GLwxAuiFloatingFrame * CreateFloatingFrame(wxWindow *parent, const wxAuiPaneInfo &p)
std::vector< ImageToogleButtonEventHandler * > toogle_button_event_handlers
PanosphereOverviewCameraTool * panosphere_overview_camera_tool
void OnColorPicker(wxCommandEvent &e)
event handler when starting color picker
tool for the manipulation of the opengl &#39;camera&#39; properties It handles zooming in/out of the main pre...
center panorama horizontically
Definition: PanoCommand.h:250
void ClearDragGroupImages(bool update_check_box=true)
bool isCircularCrop() const
returns true, if projection requires cicular crop
bool fovCalcSupported(ProjectionFormat f) const
true, if FOV calcuations are supported for projection f
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
void ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box=true)
void OnVFOVChanged(wxCommandEvent &e)
GuiLevel m_guiLevel
virtual void SetLayoutScale(double scale)
Definition: GLViewer.cpp:300
ImageToogleButtonEventHandler(unsigned int image_number, wxToggleButton *identify_button_in, HuginBase::Panorama *m_pano)
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
wxPanel * m_overviewCommandPanel
void OnOverviewToggle(wxCommandEvent &e)
wxTextCtrl * m_ROIRightTxt
void SetPhotometricCorrect(bool state)
Definition: GLViewer.cpp:288
SplitButton * m_createButton
CorrelationResult PointFineTune(const IMAGET &templImg, ACCESSORT access_t, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, ACCESSORS access_s, vigra::Diff2D searchPos, int sWidth)
fine tune a point with normalized cross correlation
Definition: Correlation.h:504
#define DEBUG_TRACE(msg)
Definition: utils.h:67
void OnDecreaseExposure(wxSpinEvent &e)
wxBitmapButton * m_defaultExposureBut
void OnEnter(wxMouseEvent &e)
void RunAssistant(wxWindow *mainWin, const wxString &userdefinedAssistant=wxEmptyString)
Definition: MainFrame.cpp:2443
void registerPTWXDlgFcn()
Definition: PTWXDlg.cpp:173
void OnSwitchPreviewGrid(wxCommandEvent &e)
event handler for switch on/off grid on preview
unsigned int getHeight() const
get panorama height
void SetActive(bool active)
Definition: GLViewer.h:75
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI
void OnShowMainFrame(wxCommandEvent &e)
event handler to show main frame
some helper classes for graphes
GLPreview * m_GLPreview
void Resized(wxSizeEvent &e)
Definition: GLViewer.cpp:355
double getMaxHFOV() const
get maximum possible hfov with current projection
wxColour m_preview_background_color
virtual void setName(const std::string &newName)
sets the name for the command
Definition: Command.cpp:88
PreviewLayoutLinesTool * m_plane_layoutLinesTool
std::vector< wxCheckBox * > m_GroupToggleButtons
void AddImageToDragGroup(unsigned int image_nr, bool update_check_box=true)
void deregisterPTWXDlgFcn()
Definition: PTWXDlg.cpp:180
virtual void DeactivateTool(Tool *tool)
Definition: ToolHelper.cpp:60
Dialog for setting output parameters for simple user interface.
wxChoice * m_ProjectionChoice
Definition: PreviewFrame.h:100
std::size_t getNrOfCtrlPoints() const
number of control points
Definition: Panorama.h:306
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
wxMenu * GetSplitButtonMenu()
returns a pointer to the drop down menu
Definition: SplitButton.cpp:64
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
PreviewIdentifyTool * plane_overview_identify_tool
void OnSelectDarkestMenu(wxCommandEvent &e)
HuginBase::ImageCache::ImageCacheRGB8Ptr ImageCacheRGB8Ptr
Definition: wxImageCache.h:33
Translate the panorama.
Definition: PanoCommand.h:462
void setProjectionParameters(const std::vector< double > &params)
set the optional parameters (they need to be of the correct size)
PreviewPanoMaskTool * pano_mask_tool
simple class that forward the drop to the mainframe
Definition: MainFrame.h:65
END_EVENT_TABLE()
include file for the hugin project
#define MAX_DIMENSION
void SetMenuProcessed()
reset popup menu status
void ForceRequireRedraw()
Definition: ViewState.cpp:439
wxNotebook * m_tool_notebook
void InitPreviews()
init previews
virtual void run()
runs the algorithm.
Panorama getSubset(const UIntSet &imgs) const
get a subset of the panorama
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
PreviewControlPointTool * preview_control_point_tool
std::vector< wxPanel * > m_ToggleButtonPanel
std::vector< PreviewIdentifyTool ** > identify_tools
void UpdateRoiDisplay(const HuginBase::PanoramaOptions opts)
update display of ROI
void OnPhotometric(wxCommandEvent &e)
wxTextCtrl * m_ROILeftTxt
remove several control points
Definition: PanoCommand.h:307
represents a control point
Definition: ControlPoint.h:38
PreviewDifferenceTool * plane_difference_tool
std::vector< PreviewIdentifyTool ** > identify_tools
Definition of PanoOperation class.
void findInterestPointsPartial(vigra::triple< ImageIter, ImageIter, ImageAcc > img, const vigra::Rect2D &rect, double scale, unsigned nPoints, std::multimap< double, vigra::Diff2D > &points)
void OnChange(wxCommandEvent &e)
void RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box=true)
wxChoice * m_GuideChoiceCrop
PanosphereOverviewOutlinesTool * overview_outlines_tool
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
Definition: ImageGraph.h:50
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
Definition: utils.cpp:228
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:649
PanosphereSphereTool * panosphere_sphere_tool
void DeactivateTool(Tool *tool)
Definition: ToolHelper.cpp:703
void FillBlendChoice()
fills the blend wxChoice with all valid blend modes and restore the last used one ...
void OnActivate(wxActivateEvent &evt)
wxChoice * m_GuideChoiceDrag
PanoCommand to combine other PanoCommands.
Definition: PanoCommand.h:39
Panorama duplicate() const
duplicate the panorama
Definition: Panorama.cpp:1653
wxStaticBoxSizer * m_ToggleButtonSizer
void OnLeave(wxMouseEvent &e)
void OnSetCropAspect(wxCommandEvent &e)
event handler to set fixed aspect ratio of crop
void OnAutocropOutside(wxCommandEvent &e)
static hugin_omp::Lock cpLock
std::vector< LensInfo > LensInfoVector
vector of LensInfo to hold all available lens types
Definition: LensTools.h:48
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
helper for OpenMP
set the panorama options
Definition: PanoCommand.h:418
void OnDefaultExposure(wxCommandEvent &e)
wxSlider * m_VFOVSlider
void OnOverviewModeChoice(wxCommandEvent &e)
algorithms for remove control points by statistic method
void OnProjParameterChanged(wxCommandEvent &e)
#define DEBUG_WARN(msg)
Definition: utils.h:74
HuginBase::PanoramaOptions GetNewPanoramaOptions()
Draws guide lines over the panorama in fast preview window.
void LoadOpenGLLayout()
loads the layout of the OpenGL windows and restores it
wxChoice * m_ProjectionChoice
Finds the topmost image underneath the mouse pontier, cancel it&#39;s normal drawing, and then subtract i...
const vigra::Rect2D & getROI() const
void SetMode(OverviewMode mode)
Definition: GLViewer.cpp:491
Model for a panorama.
Definition: Panorama.h:152
wxSpinButton * m_rangeCompressionSpinBut
void OnHFOVChanged(wxCommandEvent &e)
void OnExposureChanged(wxCommandEvent &e)
wxMenu * m_filemenuSimple
wxBoxSizer * m_ButtonSizer
virtual ~GLPreviewFrame()
dtor.
PreviewLayoutLinesTool * m_panosphere_layoutLinesTool
void OnStackAutocrop(wxCommandEvent &e)
#define PF_STYLE
GLwxAuiManager * m_mgr
The dock manager.
void MakePreviewTools(PreviewToolHelper *helper)
void SetMode(int newMode)
virtual void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
notifies about changes to images
VariableMapVector getVariables() const
get variables of this panorama
Definition: Panorama.cpp:118
void OnFullScreen(wxCommandEvent &e)
event handler for full screen
void OnSelectMedianMenu(wxCommandEvent &e)
std::vector< wxSlider * > m_projParamSlider
wxScrolledWindow * m_ButtonPanel
void resetProjectionParameters()
sets the optional parameters to their default values
void SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box=true)
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2181
wxTextCtrl * m_VFOVText
Definition of PanoOutputDialog class.
The PreviewCropTool shows lines between the ends of control points in the fast preview.
WXIMPEX HuginLensTools::LensInfoVector GetLensProjectionList()
return a vector with all available projections
Definition: LensTools.cpp:45
interface to ToolHelper for drawing guide lines over pano
void AddUserDefinedSequence(int id, const wxString &desc, const wxString &help)
adds the given user defined output sequence to SplitButton menu
void SetGuiLevel(GuiLevel newLevel)
sets the gui level
void OnEnter(wxMouseEvent &e)
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be &#39;add&#39; method?)
Definition: Panorama.cpp:449
SplitButton * m_selectAllButton
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Store window size and position in configfile/registry.
Definition: LensCalApp.cpp:212
float pow(float a, double b)
Definition: utils.h:181
void AddIdentifyTool(PreviewIdentifyTool **identify_tool_in)
void redrawPreview()
Display an updated version of the preview images.
wxMenu * LoadMenu(const wxString &name)
loads the drop down menu from the XRC ressource
void remapImage(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra_ext::Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
remap a image without alpha channel
PreviewIdentifyTool * panosphere_overview_identify_tool
virtual vigra::Rect2D getResultOptimalROI()
return the ROI structure?, for now area
void OnSelectKeepSelection(wxCommandEvent &e)
wxMenu * m_filemenuAdvanced
double getMaxVFOV() const
get maximum possible vfov with current projection
Definition of dialog for selecting and editing aspect ratios of crop.
virtual double getResultHeight()
Definition: FitPanorama.h:75
std::vector< FindStruct > FindVector
PanoOperation to add several user selected images to the panorama.
Definition: PanoOperation.h:73
PlaneOverviewOutlinesTool * plane_overview_outlines_tool
std::vector< wxTextCtrl * > m_projParamTextCtrl
Maximum of correlation, position and value.
Definition: Correlation.h:56
HuginBase::Panorama * m_pano
std::string getLastCommandName() const
returns the name of the last command
wxInfoBar * m_infoBar
Bar for context sensitive projection information.
void OnToolModeChanging(wxNotebookEvent &e)
event handler for blocking changing mode when panorama contains no images
wxToggleButton * m_editCP_togglebutton
OverviewMode GetMode()
Definition: GLViewer.h:153
wxwindows specific panorama commands
std::map< std::string, std::string > FileMetaData
typedef for general map for storing metadata in files
Definition: SrcPanoImage.h:55
SplitButton * m_loadImagesButton
std::vector< HuginBase::UIntVector > getSortedStacks(const HuginBase::Panorama *pano)
returns vector of UIntVector with image numbers of each stack sorted by exposure
PreviewControlPointTool * plane_control_point_tool
distributes all images above the sphere, for the assistant
Definition: PanoCommand.h:649
wxPanel * m_projection_panel
void OnRangeCompressionChanged(wxCommandEvent &e)
void SetShowProjectionHints(bool new_value)
set status if projection hints should be shown or not
void UpdateIdentifyTools(std::set< unsigned int > new_image_set)
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Restore window size and position from configfile/registry.
Definition: LensCalApp.cpp:158
static GlobalCmdHist & getInstance()
PanosphereOverviewToolHelper * panosphere_overview_helper
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:294
std::multimap< double, vigra::Diff2D > MapPoints
implementation of PanosphereSphereTool Class
void MakePanosphereOverviewTools(PanosphereOverviewToolHelper *helper)
void ShowMaskEditor(size_t imgNr, bool switchToCropMode=false)
opens the mask/crop editor with the given image selected
Definition: MainFrame.cpp:2052
void SetGuideStyle(const Guides newGuideStyle)
sets the guide style to the given style
std::vector< ImageGroupButtonEventHandler * > toggle_group_button_event_handlers
wxToggleButton * m_identify_togglebutton
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
void OnProjectionChoice(wxCommandEvent &e)
PreviewControlPointTool * panosphere_control_point_tool
PanosphereOverviewProjectionGridTool * overview_projection_grid
Tool to delete all cp in a selected rectangle.
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
Definition: utils.h:114
double GetSelectedAspectRatio() const
returns the selected aspect ratio
VisualizationState * m_visualization_state
Definition: GLViewer.h:71
void EnableGroupCheckboxes(bool isShown)
changes the visibility of the group check boxes
void OnSelectMode(wxNotebookEvent &e)
event handler for selection of new mode
void setROI(const vigra::Rect2D &val)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
Definition: ROIImage.h:287
void ShowFisheyeCropHint()
void KeypressEvent(int keycode, int modifiers, bool pressed)
Definition: ToolHelper.cpp:165
void DragChoiceLayout(int index)
void OnSelectBrightestMenu(wxCommandEvent &e)
void SetBitmap(const wxBitmap &bitmap)
sets bitmap and direction
straighten panorama horizontically
Definition: PanoCommand.h:259
void OnTrackChangeFOV(wxScrollEvent &e)
compute interest points
The PreviewLayoutLinesTool handles the lines connecting images in the layout view of the fast preview...
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
void MakePlaneOverviewTools(PlaneOverviewToolHelper *helper)
#define HUGIN_ASS_AUTO_ALIGN
void OnLayoutScaleChange(wxScrollEvent &e)
event handler for change scale of layout mode
OverviewDragTool * overview_drag_tool
GLOverview * m_GLOverview
bool m_selectKeepSelection
GLPreviewFrame(wxFrame *frame, HuginBase::Panorama &pano)
ctor.
void OnCenterHorizontally(wxCommandEvent &e)
virtual void SetLayoutScale(double scale)
Definition: GLViewer.cpp:313
void OnROIChanged(wxCommandEvent &e)
event handler for changed roi
wxChoice * m_BlendModeChoice
std::vector< DragTool ** > drag_tools
wxBoxSizer * m_projParamSizer
tool to draw a whiteish transparent sphere for the panosphere
void OnLoadImages(wxCommandEvent &e)
void ShowProjectionWarnings()
Tell the user anything suspicious about the projection choice.
void OnUserExit(wxCommandEvent &e)
user wants to quit program
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void OnGuideChanged(wxCommandEvent &e)
event handler when user selects different guide
void UpdateWithNewImageSet(std::set< unsigned int > new_image_set)
void OnShowNone(wxCommandEvent &e)
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
void OnDoStitch(wxCommandEvent &e)
Definition: MainFrame.cpp:1703
void setDragMode(DragMode drag_mode)
Definition: DragTool.cpp:47
unsigned int getWidth() const
include file for the hugin project
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:306
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 OnMenuClose(wxMenuEvent &e)
handle menu close event
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
void OnSelectAllMenu(wxCommandEvent &e)
handle all options of select all context menu
void OnSelectResetSelection(wxCommandEvent &e)
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
virtual double getResultHorizontalFOV()
Definition: FitPanorama.h:68
virtual vigra::Rect2D getResultOptimalROI()
returns the found crop rect
void OnResetCrop(wxCommandEvent &e)
event handler to reset crop area
UIntSet getCPoutsideLimit(Panorama pano, double n, bool skipOptimisation, bool includeLineCp)
optimises the whole panorama and removes all control points with error &gt; mean+n*sigma ...
Definition: CleanCP.cpp:123
PreviewToolHelper * preview_helper
wxTextCtrl * m_ROIBottomTxt
bool Enable(bool enable=true) override
enable or disable the control
Components GetComponents()
find all connected components
Definition: ImageGraph.cpp:101
subclass for a floating frame of the dock manager
void Redraw()
Definition: GLViewer.cpp:384
SplitButton * m_alignButton
wxToggleButton * m_identify_button
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
void OnChange(wxCommandEvent &e)
void OnIncreaseExposure(wxSpinEvent &e)
bool UpdateOverviewMode(int newMode)
updates the mode of the overview window
wxToggleButton * m_colorpicker_togglebutton
void OnRangeCompressionIncrease(wxSpinEvent &e)
static T max(T x, T y)
Definition: svm.cpp:65
bool m_showProjectionHints
Holds transformations for Image -&gt; Pano and the other way.
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
Definition: ViewState.cpp:120
void OnCreateCP(wxCommandEvent &e)
handler for creating cp in pano space
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
DragMode getDragMode()
Definition: DragTool.cpp:52
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
void OnPreviewBackgroundColorChanged(wxColourPickerEvent &e)
event handler when user changes background color
void SetViewerBackground(wxColour col)
Definition: GLViewer.cpp:484
tool for manipulation of the opengl &#39;camera&#39; properties It handles the position of the camera in 3 di...
void OnDragChoice(wxCommandEvent &e)
hugin_utils::FDiff2D maxpos
Definition: Correlation.h:64
PreviewColorPickerTool * color_picker_tool
void OnChangeFOV(wxScrollEvent &e)
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
interface of ToolHelper for deleting control points in the pano space
wxFileHistory * GetFileHistory()
Definition: MainFrame.h:191
platform/compiler specific stuff.
void SetPreviewBackgroundColor(wxColour c)
sets the sphere background color
void updateBlendMode()
Update tools and GUI elements according to blend mode choice.
bool HasNonZeroTranslationPlaneParameters()
check, if panorama has non-zero translation plane parameters
void OnEditCPTool(wxCommandEvent &e)
event handler when starting edit cp tool
PlaneOverviewToolHelper * plane_overview_helper
HuginBase::UIntSet GetFoundCPs()
return set of found control points
PreviewEditCPTool * edit_cp_tool
The PreviewColorPickerTool allows to select a region in the panorama which should be grey...
For projections where the output range is limited, but the approximatly remaped images can extend thi...
void OnBlendChoice(wxCommandEvent &e)
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
wxTextCtrl * m_exposureTextCtrl
void OnShowEvent(wxShowEvent &e)
GuiLevel
Definition: GuiLevel.h:31
void OnAutocrop(wxCommandEvent &e)
vigra::BRGBImage image
bool needsOptimization()
true if control points or lens variables have been changed after the last optimisation ...
Definition: Panorama.h:614
std::vector< wxStaticText * > m_projParamNamesLabel
PreviewProjectionGridTool * preview_projection_grid
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition: stl_utils.h:81
update global white balance
Definition: PanoCommand.h:626
customized subclass of the dock manager, created just for the purpose to create a workaround for the ...
void KeyDown(wxKeyEvent &e)
ProjectionFormat
Projection of final panorama.
HuginBase::Panorama & m_pano
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
PreviewGuideTool * preview_guide_tool
void SetLabel(const wxString &label)
set the label string
Allows the user to change the yaw, pitch and roll of a connected component of images by dragging them...
Definition: DragTool.h:50
void ResetTranslationPlaneParameters()
resets all translation plane parameters to zero
virtual void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
add multiple control points
Definition: PanoCommand.h:281
wxChoice * m_GuideChoiceProj
PreviewCameraTool * camera_tool
ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame *frame_in, HuginBase::Panorama *m_pano)
void OnStraighten(wxCommandEvent &e)
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
void SetDirtyViewport()
Definition: ViewState.h:249
static ViewState * m_view_state
Definition: GLViewer.h:72
Panorama image options.
PreviewLayoutLinesTool * m_preview_layoutLinesTool
void SetZoomLevel(const float new_zoom)
Definition: ViewState.cpp:483
vigra::Size2D getSize() const
get size of output image
static bool CheckOpenGLCanDifference()
check, if graphic card supports the necessary modes for difference tool call this procedure first...
Rotate the panorama.
Definition: PanoCommand.h:448
void UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
updates the global white balance
void SetImageButtonColour(unsigned int image_nr, unsigned char red, unsigned char green, unsigned char blue)
void ResetPreviewZoom()
reset zoom level for preview window
vigra::Rect2D GetSelectedROI()
returns selected ROI
void OnClose(wxCloseEvent &e)
void SetUpContext()
Definition: GLViewer.cpp:121
struct to hold a image state for stitching
wxString Components2Str(const HuginGraph::ImageGraph::Components &comp)
Definition: huginApp.cpp:86
static T min(T x, T y)
Definition: svm.cpp:62
HuginBase::UIntSet imageDragGroup
void OnNumTransform(wxCommandEvent &e)
void OnAlign(wxCommandEvent &e)
Visually connect the image numbers with the image on the preview.
wxTextCtrl * m_HFOVText
wxChoice * m_OverviewModeChoice
PreviewDifferenceTool * difference_tool
void OnHideProjectionHints(wxCommandEvent &e)
event handler when user hides the infobar
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
void OnProjParameterReset(wxCommandEvent &e)
event handler for reset projection parameters
void TurnOffTools(std::set< Tool * > tools)
void LoadImages(int preferredLensType)
HuginBase::Panorama * m_pano
void KeyUp(wxKeyEvent &e)
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
GLPreviewFrame * frame
void OnLeave(wxMouseEvent &e)
void OnFitPano(wxCommandEvent &e)
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition: ImageGraph.h:44