00001
00002
00027 #include <config.h>
00028
00029
00030 #ifdef __APPLE__
00031 #include "panoinc_WX.h"
00032 #endif
00033
00034 #include "panoinc.h"
00035
00036
00037
00038 #include "hugin/huginApp.h"
00039 #include "hugin/config_defaults.h"
00040 #include "hugin/CommandHistory.h"
00041 #include "base_wx/wxImageCache.h"
00042 #include "hugin/CPImageCtrl.h"
00043 #include "hugin/TextKillFocusHandler.h"
00044 #include "hugin/CPEditorPanel.h"
00045 #include "hugin/wxPanoCommand.h"
00046 #include "base_wx/MyProgressDialog.h"
00047
00048
00049 #include <algorithm>
00050 #include <float.h>
00051 #include <vector>
00052
00053
00054 #include "vigra/cornerdetection.hxx"
00055 #include "vigra/localminmax.hxx"
00056 #include "vigra_ext/Correlation.h"
00057
00058
00059 #include "Celeste.h"
00060
00061 using namespace std;
00062 using namespace PT;
00063 using namespace vigra;
00064 using namespace vigra_ext;
00065 using namespace vigra::functor;
00066 using namespace hugin_utils;
00067
00068 BEGIN_EVENT_TABLE(CPEditorPanel, wxPanel)
00069 EVT_CPEVENT(CPEditorPanel::OnCPEvent)
00070 EVT_COMBOBOX(XRCID("cp_editor_left_choice"), CPEditorPanel::OnLeftChoiceChange )
00071 EVT_COMBOBOX(XRCID("cp_editor_right_choice"), CPEditorPanel::OnRightChoiceChange )
00072 EVT_LIST_ITEM_SELECTED(XRCID("cp_editor_cp_list"), CPEditorPanel::OnCPListSelect)
00073 EVT_LIST_ITEM_DESELECTED(XRCID("cp_editor_cp_list"), CPEditorPanel::OnCPListDeselect)
00074 EVT_LIST_COL_END_DRAG(XRCID("cp_editor_cp_list"), CPEditorPanel::OnColumnWidthChange)
00075 EVT_CHOICE(XRCID("cp_editor_choice_zoom"), CPEditorPanel::OnZoom)
00076 EVT_TEXT_ENTER(XRCID("cp_editor_x1"), CPEditorPanel::OnTextPointChange )
00077 EVT_TEXT_ENTER(XRCID("cp_editor_y1"), CPEditorPanel::OnTextPointChange )
00078 EVT_TEXT_ENTER(XRCID("cp_editor_x2"), CPEditorPanel::OnTextPointChange )
00079 EVT_TEXT_ENTER(XRCID("cp_editor_y2"), CPEditorPanel::OnTextPointChange )
00080 EVT_CHOICE(XRCID("cp_editor_mode"), CPEditorPanel::OnTextPointChange )
00081 EVT_CHAR(CPEditorPanel::OnKey)
00082 EVT_BUTTON(XRCID("cp_editor_delete"), CPEditorPanel::OnDeleteButton)
00083 EVT_BUTTON(XRCID("cp_editor_add"), CPEditorPanel::OnAddButton)
00084 EVT_BUTTON(XRCID("cp_editor_previous_img"), CPEditorPanel::OnPrevImg)
00085 EVT_BUTTON(XRCID("cp_editor_next_img"), CPEditorPanel::OnNextImg)
00086 EVT_BUTTON(XRCID("cp_editor_finetune_button"), CPEditorPanel::OnFineTuneButton)
00087 EVT_BUTTON(XRCID("cp_editor_celeste_button"), CPEditorPanel::OnCelesteButton)
00088 END_EVENT_TABLE()
00089
00090 CPEditorPanel::CPEditorPanel()
00091 {
00092 DEBUG_TRACE("**********************");
00093 m_pano = 0;
00094 }
00095
00096 bool CPEditorPanel::Create(wxWindow* parent, wxWindowID id,
00097 const wxPoint& pos,
00098 const wxSize& size,
00099 long style,
00100 const wxString& name)
00101 {
00102 DEBUG_TRACE(" Create called *************");
00103 if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
00104 return false;
00105 }
00106
00107 cpCreationState = NO_POINT;
00108 m_leftImageNr=UINT_MAX;
00109 m_rightImageNr=UINT_MAX;
00110 m_listenToPageChange=true;
00111 m_detailZoomFactor=1;
00112 m_selectedPoint=UINT_MAX;
00113 m_leftRot=CPImageCtrl::ROT0;
00114 m_rightRot=CPImageCtrl::ROT0;
00115
00116 DEBUG_TRACE("");
00117 wxXmlResource::Get()->LoadPanel(this, wxT("cp_editor_panel"));
00118 wxPanel * panel = XRCCTRL(*this, "cp_editor_panel", wxPanel);
00119
00120 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
00121 topsizer->Add(panel, 1, wxEXPAND, 0);
00122
00123 m_leftChoice = XRCCTRL(*this, "cp_editor_left_choice", CPImagesComboBox);
00124 m_leftImg = XRCCTRL(*this, "cp_editor_left_img", CPImageCtrl);
00125 assert(m_leftImg);
00126 m_leftImg->Init(this);
00127 m_leftImg->setTransforms(&m_leftTransform, &m_leftInvTransform, &m_rightInvTransform);
00128
00129
00130 m_rightChoice = XRCCTRL(*this, "cp_editor_right_choice", CPImagesComboBox);
00131 m_rightImg = XRCCTRL(*this, "cp_editor_right_img", CPImageCtrl);
00132 assert(m_rightImg);
00133 m_rightImg->Init(this);
00134 m_rightImg->setTransforms(&m_rightTransform, &m_rightInvTransform, &m_leftInvTransform);
00135
00136
00137 m_cpList = XRCCTRL(*this, "cp_editor_cp_list", wxListCtrl);
00138 m_cpList->Connect(wxEVT_CHAR,wxKeyEventHandler(CPEditorPanel::OnKey),NULL,this);
00139 m_cpList->InsertColumn( 0, _("#"), wxLIST_FORMAT_RIGHT, 35);
00140 m_cpList->InsertColumn( 1, _("left x"), wxLIST_FORMAT_RIGHT, 65);
00141 m_cpList->InsertColumn( 2, _("left y"), wxLIST_FORMAT_RIGHT, 65);
00142 m_cpList->InsertColumn( 3, _("right x"), wxLIST_FORMAT_RIGHT, 65);
00143 m_cpList->InsertColumn( 4, _("right y"), wxLIST_FORMAT_RIGHT, 65);
00144 m_cpList->InsertColumn( 5, _("Alignment"), wxLIST_FORMAT_LEFT,110 );
00145 m_cpList->InsertColumn( 6, _("Distance"), wxLIST_FORMAT_RIGHT, 110);
00146
00147
00148 for ( int j=0; j < m_cpList->GetColumnCount() ; j++ )
00149 {
00150
00151 int width = wxConfigBase::Get()->Read(wxString::Format( wxT("/CPEditorPanel/ColumnWidth%d"), j ), -1);
00152 if(width != -1)
00153 m_cpList->SetColumnWidth(j, width);
00154 }
00155
00156
00157 m_x1Text = XRCCTRL(*this,"cp_editor_x1", wxTextCtrl);
00158 m_x1Text->PushEventHandler(new TextKillFocusHandler(this));
00159 m_y1Text = XRCCTRL(*this,"cp_editor_y1", wxTextCtrl);
00160 m_y1Text->PushEventHandler(new TextKillFocusHandler(this));
00161 m_x2Text = XRCCTRL(*this,"cp_editor_x2", wxTextCtrl);
00162 m_x2Text->PushEventHandler(new TextKillFocusHandler(this));
00163 m_y2Text = XRCCTRL(*this,"cp_editor_y2", wxTextCtrl);
00164 m_y2Text->PushEventHandler(new TextKillFocusHandler(this));
00165
00166 m_cpModeChoice = XRCCTRL(*this, "cp_editor_mode", wxChoice);
00167 m_addButton = XRCCTRL(*this, "cp_editor_add", wxButton);
00168 m_delButton = XRCCTRL(*this, "cp_editor_delete", wxButton);
00169
00170 m_autoAddCB = XRCCTRL(*this,"cp_editor_auto_add", wxCheckBox);
00171 DEBUG_ASSERT(m_autoAddCB);
00172 m_fineTuneCB = XRCCTRL(*this,"cp_editor_fine_tune_check",wxCheckBox);
00173 DEBUG_ASSERT(m_fineTuneCB);
00174
00175 m_estimateCB = XRCCTRL(*this,"cp_editor_auto_estimate", wxCheckBox);
00176 DEBUG_ASSERT(m_estimateCB);
00177
00178
00179 m_cp_ctrls = XRCCTRL(*this, "cp_controls_panel", wxPanel);
00180 DEBUG_ASSERT(m_cp_ctrls);
00181
00182 wxConfigBase *config = wxConfigBase::Get();
00183
00184 m_autoAddCB->SetValue(config->Read(wxT("/CPEditorPanel/autoAdd"),0l) != 0 );
00185 m_fineTuneCB->SetValue(config->Read(wxT("/CPEditorPanel/autoFineTune"),1l) != 0 );
00186 m_estimateCB->SetValue(config->Read(wxT("/CPEditorPanel/autoEstimate"),1l) != 0 );
00187
00188
00189 m_cpModeChoice->Disable();
00190 m_addButton->Disable();
00191 m_delButton->Disable();
00192 m_autoAddCB->Disable();
00193 m_fineTuneCB->Disable();
00194 m_estimateCB->Disable();
00195 XRCCTRL(*this, "cp_editor_finetune_button", wxButton)->Disable();
00196 XRCCTRL(*this, "cp_editor_celeste_button", wxButton)->Disable();
00197 XRCCTRL(*this, "cp_editor_choice_zoom", wxChoice)->Disable();
00198 XRCCTRL(*this, "cp_editor_previous_img", wxButton)->Disable();
00199 XRCCTRL(*this, "cp_editor_next_img", wxButton)->Disable();
00200 m_leftChoice->Disable();
00201 m_rightChoice->Disable();
00202
00203
00204 wxCommandEvent dummy;
00205 dummy.SetInt(XRCCTRL(*this,"cp_editor_choice_zoom",wxChoice)->GetSelection());
00206 OnZoom(dummy);
00207
00208 SetSizer( topsizer );
00209
00210 return true;
00211 }
00212
00213 void CPEditorPanel::Init(PT::Panorama * pano)
00214 {
00215 m_pano=pano;
00216
00217 m_pano->addObserver(this);
00218 }
00219
00220 CPEditorPanel::~CPEditorPanel()
00221 {
00222 DEBUG_TRACE("dtor");
00223
00224 m_x1Text->PopEventHandler(true);
00225 m_y1Text->PopEventHandler(true);
00226 m_x2Text->PopEventHandler(true);
00227 m_y2Text->PopEventHandler(true);
00228
00229 wxConfigBase::Get()->Write(wxT("/CPEditorPanel/autoAdd"), m_autoAddCB->IsChecked() ? 1 : 0);
00230 wxConfigBase::Get()->Write(wxT("/CPEditorPanel/autoFineTune"), m_fineTuneCB->IsChecked() ? 1 : 0);
00231 wxConfigBase::Get()->Write(wxT("/CPEditorPanel/autoEstimate"), m_estimateCB->IsChecked() ? 1 : 0);
00232
00233 m_pano->removeObserver(this);
00234 DEBUG_TRACE("dtor end");
00235 }
00236
00237 void CPEditorPanel::setLeftImage(unsigned int imgNr)
00238 {
00239 DEBUG_TRACE("image " << imgNr);
00240 if (imgNr == UINT_MAX) {
00241 m_leftImg->setImage("", CPImageCtrl::ROT0);
00242 m_leftImageNr = imgNr;
00243 m_leftFile = "";
00244 changeState(NO_POINT);
00245 UpdateDisplay(true);
00246 } else if (m_leftImageNr != imgNr) {
00247 double yaw = const_map_get(m_pano->getImageVariables(imgNr),"y").getValue();
00248 double pitch = const_map_get(m_pano->getImageVariables(imgNr),"p").getValue();
00249 double roll = const_map_get(m_pano->getImageVariables(imgNr),"r").getValue();
00250 m_leftRot = GetRot(yaw, pitch, roll);
00251 m_leftImg->setImage(m_pano->getImage(imgNr).getFilename(), m_leftRot);
00252 m_leftImageNr = imgNr;
00253 if (m_leftChoice->GetSelection() != (int) imgNr) {
00254 m_leftChoice->SetSelection(imgNr);
00255 }
00256 m_rightChoice->SetRefImage(m_pano,m_leftImageNr);
00257 m_rightChoice->Refresh();
00258 m_leftFile = m_pano->getImage(imgNr).getFilename();
00259 changeState(NO_POINT);
00260 UpdateDisplay(true);
00261 }
00262 m_selectedPoint = UINT_MAX;
00263
00264 ImageCache::getInstance().softFlush();
00265 UpdateTransforms();
00266 }
00267
00268
00269 void CPEditorPanel::setRightImage(unsigned int imgNr)
00270 {
00271 DEBUG_TRACE("image " << imgNr);
00272 if (imgNr == UINT_MAX) {
00273 m_rightImg->setImage("", CPImageCtrl::ROT0);
00274 m_rightImageNr = imgNr;
00275 m_rightFile = "";
00276 m_rightRot = CPImageCtrl::ROT0;
00277 changeState(NO_POINT);
00278 UpdateDisplay(true);
00279 } else if (m_rightImageNr != imgNr) {
00280
00281 double yaw = const_map_get(m_pano->getImageVariables(imgNr),"y").getValue();
00282 double pitch = const_map_get(m_pano->getImageVariables(imgNr),"p").getValue();
00283 double roll = const_map_get(m_pano->getImageVariables(imgNr),"r").getValue();
00284 m_rightRot = GetRot(yaw, pitch, roll);
00285 m_rightImg->setImage(m_pano->getImage(imgNr).getFilename(), m_rightRot);
00286
00287 m_rightImageNr = imgNr;
00288 if (m_rightChoice->GetSelection() != (int) imgNr) {
00289 m_rightChoice->SetSelection(imgNr);
00290 }
00291 m_leftChoice->SetRefImage(m_pano,m_rightImageNr);
00292 m_leftChoice->Refresh();
00293 m_rightFile = m_pano->getImage(imgNr).getFilename();
00294
00295 changeState(NO_POINT);
00296 UpdateDisplay(true);
00297 }
00298 m_selectedPoint = UINT_MAX;
00299
00300
00301 ImageCache::getInstance().softFlush();
00302 UpdateTransforms();
00303 }
00304
00305 void CPEditorPanel::UpdateTransforms()
00306 {
00307 if(m_leftImageNr<m_pano->getNrOfImages())
00308 {
00309 m_leftTransform.createTransform(m_pano->getImage(m_leftImageNr), m_pano->getOptions());
00310 m_leftInvTransform.createInvTransform(m_pano->getImage(m_leftImageNr), m_pano->getOptions());
00311 };
00312 if(m_rightImageNr<m_pano->getNrOfImages())
00313 {
00314 m_rightTransform.createTransform(m_pano->getImage(m_rightImageNr), m_pano->getOptions());
00315 m_rightInvTransform.createInvTransform(m_pano->getImage(m_rightImageNr), m_pano->getOptions());
00316 };
00317 };
00318
00319 void CPEditorPanel::OnCPEvent( CPEvent& ev)
00320 {
00321 DEBUG_TRACE("");
00322 wxString text;
00323 unsigned int nr = ev.getPointNr();
00324 FDiff2D point = ev.getPoint();
00325 bool left (TRUE);
00326 if (ev.GetEventObject() == m_leftImg) {
00327 left = true;
00328 } else if (ev.GetEventObject() == m_rightImg){
00329 left = false;
00330 } else {
00331 DEBUG_FATAL("UNKNOWN SOURCE OF CPEvent");
00332 }
00333
00334 switch (ev.getMode()) {
00335 case CPEvent::NONE:
00336 text = wxT("NONE");
00337 break;
00338 case CPEvent::NEW_POINT_CHANGED:
00339 NewPointChange(ev.getPoint(),left);
00340 break;
00341 case CPEvent::POINT_SELECTED:
00342
00343 DEBUG_DEBUG("selected point " << nr);
00344 SelectLocalPoint(nr);
00345 changeState(NO_POINT);
00346 break;
00347 case CPEvent::NEW_LINE_ADDED:
00348 {
00349 float vertBias = getVerticalCPBias();
00350 ControlPoint cp=ev.getControlPoint();
00351 cp.image1Nr=m_leftImageNr;
00352 cp.image2Nr=m_rightImageNr;
00353 bool hor = abs(cp.x1 - cp.x2) > (abs(cp.y1 - cp.y2) * vertBias);
00354 switch (m_leftRot)
00355 {
00356 case CPImageCtrl::ROT0:
00357 case CPImageCtrl::ROT180:
00358 if (hor)
00359 cp.mode = PT::ControlPoint::Y;
00360 else
00361 cp.mode = PT::ControlPoint::X;
00362 break;
00363 default:
00364 if (hor)
00365 cp.mode = PT::ControlPoint::X;
00366 else
00367 cp.mode = PT::ControlPoint::Y;
00368 break;
00369 }
00370 changeState(NO_POINT);
00371
00372 GlobalCmdHist::getInstance().addCommand(new PT::AddCtrlPointCmd(*m_pano, cp));
00373
00374 unsigned int lPoint = m_pano->getNrOfCtrlPoints()-1;
00375 SelectGlobalPoint(lPoint);
00376 changeState(NO_POINT);
00377 MainFrame::Get()->SetStatusText(_("new control point added"));
00378 m_leftChoice->CalcCPDistance(m_pano);
00379 m_rightChoice->CalcCPDistance(m_pano);
00380 break;
00381 };
00382 case CPEvent::POINT_CHANGED:
00383 {
00384 DEBUG_DEBUG("move point("<< nr << ")");
00385 if (nr >= currentPoints.size()) {
00386 DEBUG_ERROR("invalid point number while moving point")
00387 return;
00388 }
00389 ControlPoint cp = ev.getControlPoint();
00390 changeState(NO_POINT);
00391 DEBUG_DEBUG("changing point to: " << cp.x1 << "," << cp.y1
00392 << " " << cp.x2 << "," << cp.y2);
00393
00394 GlobalCmdHist::getInstance().addCommand(
00395 new PT::ChangeCtrlPointCmd(*m_pano, currentPoints[nr].first, cp)
00396 );
00397
00398 break;
00399 }
00400 case CPEvent::RIGHT_CLICK:
00401 {
00402 if (cpCreationState == BOTH_POINTS_SELECTED) {
00403 DEBUG_DEBUG("right click -> adding point");
00404 CreateNewPoint();
00405 } else {
00406 DEBUG_DEBUG("right click without two points..");
00407 changeState(NO_POINT);
00408 }
00409 break;
00410 }
00411 case CPEvent::SCROLLED:
00412 {
00413 wxPoint d(roundi(point.x), roundi(point.y));
00414 d = m_rightImg->MaxScrollDelta(d);
00415 d = m_leftImg->MaxScrollDelta(d);
00416 m_rightImg->ScrollDelta(d);
00417 m_leftImg->ScrollDelta(d);
00418 }
00419 break;
00420 case CPEvent::DELETE_REGION_SELECTED:
00421 {
00422 UIntSet cpToRemove;
00423 if(currentPoints.size()>0)
00424 {
00425 wxRect rect=ev.getRect();
00426 for(unsigned int i=0;i<currentPoints.size();i++)
00427 {
00428 ControlPoint cp=currentPoints[i].second;
00429 if(cp.mode==ControlPoint::X_Y)
00430 {
00431
00432 if(left)
00433 {
00434 if(rect.Contains(roundi(cp.x1),roundi(cp.y1)))
00435 {
00436 cpToRemove.insert(localPNr2GlobalPNr(i));
00437 };
00438 }
00439 else
00440 {
00441 if(rect.Contains(roundi(cp.x2),roundi(cp.y2)))
00442 {
00443 cpToRemove.insert(localPNr2GlobalPNr(i));
00444 };
00445 };
00446 };
00447 };
00448 };
00449 changeState(NO_POINT);
00450 if(cpToRemove.size()>0)
00451 {
00452 GlobalCmdHist::getInstance().addCommand(new PT::RemoveCtrlPointsCmd(*m_pano,cpToRemove));
00453 };
00454 break;
00455 }
00456 }
00457 m_leftImg->update();
00458 m_rightImg->update();
00459 }
00460
00461
00462 void CPEditorPanel::CreateNewPoint()
00463 {
00464 DEBUG_TRACE("");
00465 FDiff2D p1 = m_leftImg->getNewPoint();
00466 FDiff2D p2 = m_rightImg->getNewPoint();
00467 ControlPoint point;
00468 point.image1Nr = m_leftImageNr;
00469 point.x1 = p1.x;
00470 point.y1 = p1.y;
00471 point.image2Nr = m_rightImageNr;
00472 point.x2 = p2.x;
00473 point.y2 = p2.y;
00474 if (point.image1Nr == point.image2Nr) {
00475 if (m_cpModeChoice->GetSelection()>=3) {
00476
00477 point.mode = m_cpModeChoice->GetSelection();
00478 } else {
00479
00480
00481 float vertBias = getVerticalCPBias();
00482 bool hor = abs(p1.x - p2.x) > (abs(p1.y - p2.y) * vertBias);
00483 switch (m_leftRot) {
00484 case CPImageCtrl::ROT0:
00485 case CPImageCtrl::ROT180:
00486 if (hor)
00487 point.mode = PT::ControlPoint::Y;
00488 else
00489 point.mode = PT::ControlPoint::X;
00490 break;
00491 default:
00492 if (hor)
00493 point.mode = PT::ControlPoint::X;
00494 else
00495 point.mode = PT::ControlPoint::Y;
00496 break;
00497 }
00498 }
00499 } else {
00500 point.mode = PT::ControlPoint::X_Y;
00501 }
00502
00503 changeState(NO_POINT);
00504
00505
00506 GlobalCmdHist::getInstance().addCommand(
00507 new PT::AddCtrlPointCmd(*m_pano, point)
00508 );
00509
00510
00511
00512 unsigned int lPoint = m_pano->getNrOfCtrlPoints() -1;
00513 SelectGlobalPoint(lPoint);
00514 changeState(NO_POINT);
00515 MainFrame::Get()->SetStatusText(_("new control point added"));
00516 m_leftChoice->CalcCPDistance(m_pano);
00517 m_rightChoice->CalcCPDistance(m_pano);
00518 }
00519
00520
00521 const float CPEditorPanel::getVerticalCPBias()
00522 {
00523 PanoramaOptions opts = m_pano->getOptions();
00524 PanoramaOptions::ProjectionFormat projFormat = opts.getProjection();
00525 float bias;
00526 switch (projFormat)
00527 {
00528 case PanoramaOptions::RECTILINEAR:
00529 bias = 1.0;
00530 break;
00531 default:
00532 bias = 2.0;
00533 break;
00534 }
00535 return bias;
00536 }
00537
00538
00539 void CPEditorPanel::ClearSelection()
00540 {
00541 if (m_selectedPoint == UINT_MAX) {
00542
00543 return;
00544 }
00545 m_cpList->SetItemState(m_selectedPoint, 0, wxLIST_STATE_SELECTED);
00546
00547 m_selectedPoint=UINT_MAX;
00548 changeState(NO_POINT);
00549 m_leftImg->deselect();
00550 m_rightImg->deselect();
00551 UpdateDisplay(false);
00552 }
00553
00554 void CPEditorPanel::SelectLocalPoint(unsigned int LVpointNr)
00555 {
00556 DEBUG_TRACE("selectLocalPoint(" << LVpointNr << ")");
00557
00558 if ( m_selectedPoint == LVpointNr) {
00559 DEBUG_DEBUG("already selected");
00560 m_leftImg->selectPoint(LVpointNr);
00561 m_rightImg->selectPoint(LVpointNr);
00562 return;
00563 }
00564 m_selectedPoint = LVpointNr;
00565
00566 const ControlPoint & p = currentPoints[LVpointNr].second;
00567 m_x1Text->SetValue(wxString::Format(wxT("%.2f"),p.x1));
00568 m_y1Text->SetValue(wxString::Format(wxT("%.2f"),p.y1));
00569 m_x2Text->SetValue(wxString::Format(wxT("%.2f"),p.x2));
00570 m_y2Text->SetValue(wxString::Format(wxT("%.2f"),p.y2));
00571 m_cpModeChoice->SetSelection(p.mode);
00572 m_leftImg->selectPoint(LVpointNr);
00573 m_rightImg->selectPoint(LVpointNr);
00574 m_cpList->SetItemState(LVpointNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00575 m_cpList->EnsureVisible(LVpointNr);
00576
00577 EnablePointEdit(true);
00578 }
00579
00580 void CPEditorPanel::SelectGlobalPoint(unsigned int globalNr)
00581 {
00582 unsigned int localNr;
00583 if (globalPNr2LocalPNr(localNr,globalNr)) {
00584 DEBUG_DEBUG("CPEditor::setGlobalPoint(" << globalNr << ") found local point " << localNr);
00585 SelectLocalPoint(localNr);
00586 } else {
00587 DEBUG_ERROR("CPEditor::setGlobalPoint: point " << globalNr << " not found in currentPoints");
00588 }
00589 }
00590
00591 bool CPEditorPanel::globalPNr2LocalPNr(unsigned int & localNr, unsigned int globalNr) const
00592 {
00593 HuginBase::CPointVector::const_iterator it = currentPoints.begin();
00594
00595 while(it != currentPoints.end() && (*it).first != globalNr) {
00596 it++;
00597 }
00598
00599 if (it != currentPoints.end()) {
00600 localNr = it - currentPoints.begin();
00601 return true;
00602 } else {
00603 return false;
00604 }
00605 }
00606
00607 unsigned int CPEditorPanel::localPNr2GlobalPNr(unsigned int localNr) const
00608 {
00609 assert(localNr < currentPoints.size());
00610 return currentPoints[localNr].first;
00611 }
00612
00613
00614 void CPEditorPanel::estimateAndAddOtherPoint(const FDiff2D & p,
00615 bool left,
00616 CPImageCtrl * thisImg,
00617 unsigned int thisImgNr,
00618 CPCreationState THIS_POINT,
00619 CPCreationState THIS_POINT_RETRY,
00620 CPImageCtrl * otherImg,
00621 unsigned int otherImgNr,
00622 CPCreationState OTHER_POINT,
00623 CPCreationState OTHER_POINT_RETRY)
00624 {
00625 FDiff2D op;
00626 op = EstimatePoint(FDiff2D(p.x, p.y), left);
00627
00628 const SrcPanoImage & pImg = m_pano->getImage(otherImgNr);
00629 if (p.x < (int) pImg.getSize().width() && p.x >= 0
00630 && p.y < (int) pImg.getSize().height() && p.y >= 0)
00631 {
00632 otherImg->setNewPoint(op);
00633
00634
00635 if (m_fineTuneCB->IsChecked()) {
00636 MainFrame::Get()->SetStatusText(_("searching similar points..."),0);
00637 FDiff2D newPoint = otherImg->getNewPoint();
00638
00639 long templWidth = wxConfigBase::Get()->Read(wxT("/Finetune/TemplateSize"), HUGIN_FT_TEMPLATE_SIZE);
00640 const SrcPanoImage & img = m_pano->getImage(thisImgNr);
00641 double sAreaPercent = wxConfigBase::Get()->Read(wxT("/Finetune/SearchAreaPercent"),HUGIN_FT_SEARCH_AREA_PERCENT);
00642 int sWidth = (int) (img.getWidth() * sAreaPercent / 100.0);
00643 CorrelationResult corrPoint;
00644 double corrOk=false;
00645 Diff2D roundp(p.toDiff2D());
00646 try {
00647 corrOk = PointFineTune(thisImgNr,
00648 roundp,
00649 templWidth,
00650 otherImgNr,
00651 newPoint,
00652 sWidth,
00653 corrPoint);
00654 } catch (std::exception & e) {
00655 wxMessageBox(wxString (e.what(), wxConvLocal), _("Error during Fine-tune"));
00656 }
00657 if (! corrOk) {
00658
00659 otherImg->setScale(m_detailZoomFactor);
00660 otherImg->setNewPoint(corrPoint.maxpos);
00661 changeState(BOTH_POINTS_SELECTED);
00662 } else {
00663
00664 if (!m_autoAddCB->IsChecked()) {
00665 otherImg->setScale(m_detailZoomFactor);
00666 otherImg->setNewPoint(corrPoint.maxpos);
00667 changeState(BOTH_POINTS_SELECTED);
00668 wxString s1;
00669 s1.Printf(_("Point fine-tuned, angle: %.0f deg, correlation coefficient: %0.3f, curvature: %0.3f %0.3f "),
00670 corrPoint.maxAngle, corrPoint.maxi, corrPoint.curv.x, corrPoint.curv.y );
00671
00672 wxString s2 = s1 + wxT(" -- ") + wxString(_("change points, or press right mouse button to add the pair"));
00673 MainFrame::Get()->SetStatusText(s2,0);
00674 } else {
00675
00676 otherImg->setNewPoint(corrPoint.maxpos);
00677 changeState(BOTH_POINTS_SELECTED);
00678 CreateNewPoint();
00679 }
00680 }
00681 } else {
00682
00683 otherImg->setScale(m_detailZoomFactor);
00684 otherImg->showPosition(op);
00685 changeState(BOTH_POINTS_SELECTED);
00686 }
00687
00688 } else {
00689
00690
00691 wxBell();
00692 MainFrame::Get()->SetStatusText(_("Estimated point outside image"),0);
00693 }
00694 }
00695
00696 void CPEditorPanel::NewPointChange(FDiff2D p, bool left)
00697 {
00698 DEBUG_TRACE("");
00699
00700 wxString corrMsg;
00701
00702 CPImageCtrl * thisImg = m_leftImg;
00703 unsigned int thisImgNr = m_leftImageNr;
00704 CPImageCtrl * otherImg = m_rightImg;
00705 unsigned int otherImgNr = m_rightImageNr;
00706 CPCreationState THIS_POINT = LEFT_POINT;
00707 CPCreationState THIS_POINT_RETRY = LEFT_POINT_RETRY;
00708 CPCreationState OTHER_POINT = RIGHT_POINT;
00709 CPCreationState OTHER_POINT_RETRY = RIGHT_POINT_RETRY;
00710
00711 bool estimate = m_estimateCB->IsChecked();
00712
00713 if (!left) {
00714 thisImg = m_rightImg;
00715 thisImgNr = m_rightImageNr;
00716 otherImg = m_leftImg;
00717 otherImgNr = m_leftImageNr;
00718 THIS_POINT = RIGHT_POINT;
00719 THIS_POINT_RETRY = RIGHT_POINT_RETRY;
00720 OTHER_POINT = LEFT_POINT;
00721 OTHER_POINT_RETRY = LEFT_POINT_RETRY;
00722 }
00723
00724
00725 if (cpCreationState == NO_POINT) {
00726
00727 changeState(THIS_POINT);
00728
00729 if (thisImg->getScale() < 1) {
00730 thisImg->setScale(m_detailZoomFactor);
00731 thisImg->showPosition(p);
00732 } else {
00733
00734 if (estimate && (thisImgNr != otherImgNr) && currentPoints.size() > 0) {
00735 estimateAndAddOtherPoint(p, left,
00736 thisImg, thisImgNr, THIS_POINT, THIS_POINT_RETRY,
00737 otherImg, otherImgNr, OTHER_POINT, OTHER_POINT_RETRY);
00738 };
00739 }
00740
00741 } else if (cpCreationState == OTHER_POINT_RETRY) {
00742 thisImg->showPosition(p);
00743 } else if (cpCreationState == THIS_POINT) {
00744 thisImg->showPosition(p);
00745
00746 if (estimate && (thisImgNr != otherImgNr) && currentPoints.size() > 0) {
00747 estimateAndAddOtherPoint(p, left,
00748 thisImg, thisImgNr, THIS_POINT, THIS_POINT_RETRY,
00749 otherImg, otherImgNr, OTHER_POINT, OTHER_POINT_RETRY);
00750 }
00751 } else if (cpCreationState == OTHER_POINT || cpCreationState == THIS_POINT_RETRY) {
00752
00753 if (cpCreationState == OTHER_POINT) {
00754
00755
00756
00757 if (m_fineTuneCB->IsChecked() ) {
00758 CorrelationResult corrRes;
00759
00760 FDiff2D newPoint = otherImg->getNewPoint();
00761
00762 long templWidth = wxConfigBase::Get()->Read(wxT("/Finetune/TemplateSize"),HUGIN_FT_TEMPLATE_SIZE);
00763 const SrcPanoImage & img = m_pano->getImage(thisImgNr);
00764 double sAreaPercent = wxConfigBase::Get()->Read(wxT("/Finetune/SearchAreaPercent"),
00765 HUGIN_FT_SEARCH_AREA_PERCENT);
00766 int sWidth = (int) (img.getWidth() * sAreaPercent / 100.0);
00767 bool corrOk = false;
00768
00769 Diff2D newPoint_round = newPoint.toDiff2D();
00770 try {
00771 corrOk = PointFineTune(otherImgNr,
00772 newPoint_round,
00773 templWidth,
00774 thisImgNr,
00775 p,
00776 sWidth,
00777 corrRes);
00778 } catch (std::exception & e) {
00779 wxMessageBox(wxString (e.what(), wxConvLocal), _("Error during Fine-tune"));
00780 }
00781
00782 if (! corrOk) {
00783
00784
00785
00786 thisImg->setScale(m_detailZoomFactor);
00787 thisImg->setNewPoint(corrRes.maxpos);
00788 thisImg->update();
00789 otherImg->setNewPoint(FDiff2D(newPoint_round.x, newPoint_round.y));
00790 changeState(BOTH_POINTS_SELECTED);
00791 } else {
00792
00793 changeState(BOTH_POINTS_SELECTED);
00794 if (!m_autoAddCB->IsChecked()) {
00795 thisImg->setScale(m_detailZoomFactor);
00796 }
00797 thisImg->setNewPoint(corrRes.maxpos);
00798 wxString s1;
00799 s1.Printf(_("Point fine-tuned, angle: %.0f deg, correlation coefficient: %0.3f, curvature: %0.3f %0.3f "),
00800 corrRes.maxAngle, corrRes.maxi, corrRes.curv.x, corrRes.curv.y );
00801
00802 corrMsg = s1 + wxT(" -- ") + wxString(_("change points, or press right mouse button to add the pair"));
00803 MainFrame::Get()->SetStatusText(corrMsg,0);
00804
00805 }
00806 } else {
00807
00808 if (thisImg->getScale() < 1) {
00809
00810
00811 thisImg->setScale(m_detailZoomFactor);
00812 thisImg->clearNewPoint();
00813 thisImg->showPosition(p);
00814
00815 changeState(THIS_POINT_RETRY);
00816 return;
00817 } else {
00818
00819
00820 changeState(BOTH_POINTS_SELECTED);
00821 }
00822 }
00823 } else {
00824
00825
00826 }
00827
00828
00829 if (m_autoAddCB->IsChecked()) {
00830 CreateNewPoint();
00831 } else {
00832
00833
00834 changeState(BOTH_POINTS_SELECTED);
00835 if (corrMsg != wxT("")) {
00836 MainFrame::Get()->SetStatusText(corrMsg,0);
00837 }
00838 }
00839
00840 } else if (cpCreationState == BOTH_POINTS_SELECTED) {
00841
00842
00843
00844 } else {
00845
00846 DEBUG_ASSERT(0);
00847 }
00848 }
00849
00850 bool CPEditorPanel::PointFineTune(unsigned int tmplImgNr,
00851 const Diff2D & tmplPoint,
00852 int templSize,
00853 unsigned int subjImgNr,
00854 const FDiff2D & o_subjPoint,
00855 int sWidth,
00856 CorrelationResult & res)
00857 {
00858 DEBUG_TRACE("tmpl img nr: " << tmplImgNr << " corr src: "
00859 << subjImgNr);
00860
00861 MainFrame::Get()->SetStatusText(_("searching similar points..."),0);
00862
00863 double corrThresh=HUGIN_FT_CORR_THRESHOLD;
00864 wxConfigBase::Get()->Read(wxT("/Finetune/CorrThreshold"),&corrThresh,
00865 HUGIN_FT_CORR_THRESHOLD);
00866
00867 double curvThresh = HUGIN_FT_CURV_THRESHOLD;
00868 wxConfigBase::Get()->Read(wxT("/Finetune/CurvThreshold"),&curvThresh,
00869 HUGIN_FT_CURV_THRESHOLD);
00870
00871 const SrcPanoImage & img = m_pano->getImage(subjImgNr);
00872
00873
00874 ImageCache::EntryPtr subjImg = ImageCache::getInstance().getImage(img.getFilename());
00875 ImageCache::EntryPtr tmplImg = ImageCache::getInstance().getImage( m_pano->getImage(tmplImgNr).getFilename());
00876
00877 wxConfigBase *cfg = wxConfigBase::Get();
00878 bool rotatingFinetune = cfg->Read(wxT("/Finetune/RotationSearch"), HUGIN_FT_ROTATION_SEARCH) == 1;
00879
00880 if (rotatingFinetune) {
00881 double startAngle=HUGIN_FT_ROTATION_START_ANGLE;
00882 cfg->Read(wxT("/Finetune/RotationStartAngle"),&startAngle,HUGIN_FT_ROTATION_START_ANGLE);
00883 startAngle=DEG_TO_RAD(startAngle);
00884 double stopAngle=HUGIN_FT_ROTATION_STOP_ANGLE;
00885 cfg->Read(wxT("/Finetune/RotationStopAngle"),&stopAngle,HUGIN_FT_ROTATION_STOP_ANGLE);
00886 stopAngle=DEG_TO_RAD(stopAngle);
00887 int nSteps = cfg->Read(wxT("/Finetune/RotationSteps"), HUGIN_FT_ROTATION_STEPS);
00888 {
00889 wxBusyCursor busy;
00890 if (subjImg->image8 && tmplImg->image8) {
00891 res = vigra_ext::PointFineTuneRotSearch(*(tmplImg->image8),
00892 tmplPoint, templSize,
00893 *(subjImg->image8),
00894 o_subjPoint.toDiff2D(),
00895 sWidth,
00896 startAngle, stopAngle, nSteps);
00897 } else if (subjImg->imageFloat && tmplImg->imageFloat) {
00898 res = vigra_ext::PointFineTuneRotSearch(*(tmplImg->imageFloat),
00899 tmplPoint, templSize,
00900 *(subjImg->imageFloat),
00901 o_subjPoint.toDiff2D(),
00902 sWidth,
00903 startAngle, stopAngle, nSteps);
00904 } else if (subjImg->image8 && tmplImg->imageFloat) {
00905 res = vigra_ext::PointFineTuneRotSearch(*(tmplImg->imageFloat),
00906 tmplPoint, templSize,
00907 *(subjImg->image8),
00908 o_subjPoint.toDiff2D(),
00909 sWidth,
00910 startAngle, stopAngle, nSteps);
00911 } else {
00912 res = vigra_ext::PointFineTuneRotSearch(*(tmplImg->image8),
00913 tmplPoint, templSize,
00914 *(subjImg->imageFloat),
00915 o_subjPoint.toDiff2D(),
00916 sWidth,
00917 startAngle, stopAngle, nSteps);
00918
00919 }
00920 }
00921 } else {
00922 wxBusyCursor busy;
00923 res = vigra_ext::PointFineTune(*(tmplImg->image8), tmplPoint, templSize,
00924 *(subjImg->image8), o_subjPoint.toDiff2D(),
00925 sWidth);
00926 }
00927
00928
00929
00930 res.curv.x = - res.curv.x;
00931 res.curv.y = - res.curv.y;
00932
00933 MainFrame::Get()->SetStatusText(wxString::Format(_("Point fine-tuned, angle: %.0f deg, correlation coefficient: %0.3f, curvature: %0.3f %0.3f "),
00934 res.maxAngle, res.maxi, res.curv.x, res.curv.y ),0);
00935 if (res.maxi < corrThresh ||res.curv.x < curvThresh || res.curv.y < curvThresh )
00936 {
00937
00938 #if wxCHECK_VERSION(2, 9, 0)
00939 wxMessageDialog dlg(this,
00940 _("No similar point found."),
00941 #ifdef _WINDOWS
00942 _("Hugin"),
00943 #else
00944 wxT(""),
00945 #endif
00946 wxICON_ERROR | wxOK);
00947 dlg.SetExtendedMessage(wxString::Format(_("Check the similarity visually.\nCorrelation coefficient (%.3f) is lower than the threshold set in the preferences."),
00948 res.maxi));
00949 dlg.ShowModal();
00950 #else
00951 wxMessageBox(
00952 wxString::Format(_("No similar point found. Check the similarity visually.\nCorrelation coefficient (%.3f) is lower than the threshold set in the preferences."),
00953 res.maxi),
00954 #ifdef _WINDOWS
00955 _("Hugin"),
00956 #else
00957 wxT(""),
00958 #endif
00959 wxICON_ERROR | wxOK, this);
00960 #endif
00961 return false;
00962 }
00963
00964 return true;
00965 }
00966
00967 void CPEditorPanel::panoramaChanged(PT::Panorama &pano)
00968 {
00969 int nGui = m_cpModeChoice->GetCount();
00970 int nPano = pano.getNextCPTypeLineNumber()+1;
00971 DEBUG_DEBUG("mode choice: " << nGui << " entries, required: " << nPano);
00972
00973 if (nGui > nPano)
00974 {
00975 m_cpModeChoice->Freeze();
00976
00977 for (int i = nGui-1; i >=nPano-1; --i) {
00978 m_cpModeChoice->Delete(i);
00979 }
00980 if (nPano > 3) {
00981 m_cpModeChoice->SetString(nPano-1, _("Add new Line"));
00982 }
00983 m_cpModeChoice->Thaw();
00984 } else if (nGui < nPano) {
00985 m_cpModeChoice->Freeze();
00986 if (nGui > 3) {
00987 m_cpModeChoice->SetString(nGui-1, wxString::Format(_("Line %d"), nGui-1));
00988 }
00989 for (int i = nGui; i < nPano-1; i++) {
00990 m_cpModeChoice->Append(wxString::Format(_("Line %d"), i));
00991 }
00992 m_cpModeChoice->Append(_("Add new Line"));
00993 m_cpModeChoice->Thaw();
00994 }
00995 UpdateTransforms();
00996 DEBUG_TRACE("");
00997 }
00998
00999 void CPEditorPanel::panoramaImagesChanged(Panorama &pano, const UIntSet &changed)
01000 {
01001 unsigned int nrImages = pano.getNrOfImages();
01002 unsigned int nrTabs = m_leftChoice->GetCount();
01003 DEBUG_TRACE("nrImages:" << nrImages << " nrTabs:" << nrTabs);
01004
01005 #ifdef __WXMSW__
01006 int oldLeftSelection = m_leftChoice->GetSelection();
01007 int oldRightSelection = m_rightChoice->GetSelection();
01008 #endif
01009
01010 if (nrImages == 0)
01011 {
01012
01013 m_cpModeChoice->Disable();
01014 m_addButton->Disable();
01015 m_delButton->Disable();
01016 m_autoAddCB->Disable();
01017 m_fineTuneCB->Disable();
01018 m_estimateCB->Disable();
01019 XRCCTRL(*this, "cp_editor_finetune_button", wxButton)->Disable();
01020 XRCCTRL(*this, "cp_editor_celeste_button", wxButton)->Disable();
01021 XRCCTRL(*this, "cp_editor_choice_zoom", wxChoice)->Disable();
01022 XRCCTRL(*this, "cp_editor_previous_img", wxButton)->Disable();
01023 XRCCTRL(*this, "cp_editor_next_img", wxButton)->Disable();
01024 m_leftChoice->Disable();
01025 m_rightChoice->Disable();
01026 }
01027 else
01028 {
01029
01030 m_cpModeChoice->Enable();
01031 m_autoAddCB->Enable();
01032 m_fineTuneCB->Enable();
01033 m_estimateCB->Enable();
01034 XRCCTRL(*this, "cp_editor_finetune_button", wxButton)->Enable();
01035 XRCCTRL(*this, "cp_editor_celeste_button", wxButton)->Enable();
01036 XRCCTRL(*this, "cp_editor_choice_zoom", wxChoice)->Enable();
01037 XRCCTRL(*this, "cp_editor_previous_img", wxButton)->Enable();
01038 XRCCTRL(*this, "cp_editor_next_img", wxButton)->Enable();
01039 m_leftChoice->Enable();
01040 m_rightChoice->Enable();
01041
01042 ImageCache::getInstance().softFlush();
01043
01044 for (unsigned int i=0; i < ((nrTabs < nrImages)? nrTabs: nrImages); i++) {
01045 wxFileName fileName(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
01046 m_leftChoice->SetString(i, wxString::Format(wxT("%d"), i) + wxT(". - ") + fileName.GetFullName());
01047 m_rightChoice->SetString(i, wxString::Format(wxT("%d"), i) + wxT(". - ") + fileName.GetFullName());
01048 }
01049
01050 #ifdef __WXMSW__
01051 m_leftChoice->SetSelection(oldLeftSelection);
01052 m_rightChoice->SetSelection(oldRightSelection);
01053 #endif
01054
01055 if (nrTabs < nrImages)
01056 {
01057 for (unsigned int i=nrTabs; i < nrImages; i++)
01058 {
01059 wxFileName fileName(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
01060 m_leftChoice->Append(wxString::Format(wxT("%d"), i) + wxT(". - ") + fileName.GetFullName());
01061 m_rightChoice->Append(wxString::Format(wxT("%d"), i) + wxT(". - ") + fileName.GetFullName());
01062 }
01063 }
01064 }
01065 if (nrTabs > nrImages)
01066 {
01067
01068
01069
01070 m_listenToPageChange = false;
01071 for (int i=nrTabs-1; i >= (int)nrImages; i--) {
01072 m_leftChoice->Delete(i);
01073 m_rightChoice->Delete(i);
01074 }
01075 m_listenToPageChange = true;
01076 if (nrImages > 0) {
01077
01078 if (m_leftImageNr >= nrImages) {
01079 setLeftImage(nrImages -1);
01080 }
01081 if (m_rightImageNr >= nrImages) {
01082 setRightImage(nrImages -1);
01083 }
01084 } else {
01085 DEBUG_DEBUG("setting no images");
01086 m_leftImageNr = UINT_MAX;
01087 m_leftFile = "";
01088 m_rightImageNr = UINT_MAX;
01089 m_rightFile = "";
01090
01091 m_leftImg->setImage(m_leftFile, CPImageCtrl::ROT0);
01092 m_rightImg->setImage(m_rightFile, CPImageCtrl::ROT0);
01093 }
01094 }
01095
01096
01097 bool update(false);
01098 for(UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it) {
01099 unsigned int imgNr = *it;
01100
01101
01102
01103
01104
01105 DEBUG_DEBUG("image changed "<< imgNr);
01106 double yaw = const_map_get(m_pano->getImageVariables(imgNr), "y").getValue();
01107 double pitch = const_map_get(m_pano->getImageVariables(imgNr), "p").getValue();
01108 double roll = const_map_get(m_pano->getImageVariables(imgNr), "r").getValue();
01109 CPImageCtrl::ImageRotation rot = GetRot(yaw, pitch, roll);
01110 if (m_leftImageNr == imgNr) {
01111 DEBUG_DEBUG("left image dirty "<< imgNr);
01112 if (m_leftFile != pano.getImage(imgNr).getFilename()
01113 || m_leftRot != rot )
01114 {
01115 m_leftRot = rot;
01116 m_leftFile = pano.getImage(imgNr).getFilename();
01117 m_leftImg->setImage(m_leftFile, m_leftRot);
01118 }
01119 update=true;
01120 }
01121
01122 if (m_rightImageNr == imgNr) {
01123 DEBUG_DEBUG("right image dirty "<< imgNr);
01124 if (m_rightFile != pano.getImage(imgNr).getFilename()
01125 || m_rightRot != rot )
01126 {
01127 m_rightRot = rot;
01128 m_rightFile = pano.getImage(imgNr).getFilename();
01129 m_rightImg->setImage(m_rightFile, m_rightRot);
01130 }
01131 update=true;
01132 }
01133 }
01134
01135
01136 if (m_rightImageNr == UINT_MAX && nrImages > 0) {
01137 setRightImage(0);
01138 }
01139 if (m_leftImageNr == UINT_MAX && nrImages > 0) {
01140 setLeftImage(0);
01141 }
01142
01143 if (update || nrImages == 0) {
01144 UpdateDisplay(false);
01145 }
01146 m_leftChoice->CalcCPDistance(m_pano);
01147 m_rightChoice->CalcCPDistance(m_pano);
01148 }
01149
01150 void CPEditorPanel::UpdateDisplay(bool newPair)
01151 {
01152 DEBUG_DEBUG("")
01153 int fI = m_leftChoice->GetSelection();
01154 int sI = m_rightChoice->GetSelection();
01155
01156
01157 if (fI >= 0 && m_leftImageNr != UINT_MAX)
01158 {
01159
01160 m_leftImageNr = (unsigned int) fI;
01161 }
01162
01163 if (sI >= 0 && m_rightImageNr != UINT_MAX)
01164 {
01165
01166 m_rightImageNr = (unsigned int) sI;
01167 }
01168
01169 m_x1Text->Clear();
01170 m_y1Text->Clear();
01171 m_x2Text->Clear();
01172 m_y2Text->Clear();
01173 if (m_cpModeChoice->GetSelection() < 3) {
01174 m_cpModeChoice->SetSelection(0);
01175 }
01176
01177 m_leftImg->setSameImage(m_leftImageNr==m_rightImageNr);
01178 m_rightImg->setSameImage(m_leftImageNr==m_rightImageNr);
01179
01180
01181 const PT::CPVector & controlPoints = m_pano->getCtrlPoints();
01182 currentPoints.clear();
01183 mirroredPoints.clear();
01184
01185
01186 unsigned int i = 0;
01187 m_leftImg->clearCtrlPointList();
01188 m_rightImg->clearCtrlPointList();
01189 for (PT::CPVector::const_iterator it = controlPoints.begin(); it != controlPoints.end(); ++it) {
01190 PT::ControlPoint point = *it;
01191 if ((point.image1Nr == m_leftImageNr) && (point.image2Nr == m_rightImageNr)){
01192 m_leftImg->setCtrlPoint(point, false);
01193 m_rightImg->setCtrlPoint(point, true);
01194 currentPoints.push_back(make_pair(it - controlPoints.begin(), *it));
01195 i++;
01196 } else if ((point.image2Nr == m_leftImageNr) && (point.image1Nr == m_rightImageNr)){
01197 point.mirror();
01198 mirroredPoints.insert(i);
01199 m_leftImg->setCtrlPoint(point, true);
01200 m_rightImg->setCtrlPoint(point, false);
01201 currentPoints.push_back(std::make_pair(it - controlPoints.begin(), point));
01202 i++;
01203 }
01204 }
01205 m_leftImg->update();
01206 m_rightImg->update();
01207
01208
01209 unsigned int selectedCP = UINT_MAX;
01210 for ( int i=0; i < m_cpList->GetItemCount() ; i++ ) {
01211 if ( m_cpList->GetItemState( i, wxLIST_STATE_SELECTED ) ) {
01212 selectedCP = i;
01213 }
01214 }
01215 m_cpList->Freeze();
01216 m_cpList->DeleteAllItems();
01217
01218 for (unsigned int i=0; i < currentPoints.size(); ++i) {
01219 const ControlPoint & p = currentPoints[i].second;
01220 DEBUG_DEBUG("inserting LVItem " << i);
01221 m_cpList->InsertItem(i,wxString::Format(wxT("%d"),i));
01222 m_cpList->SetItem(i,1,wxString::Format(wxT("%.2f"),p.x1));
01223 m_cpList->SetItem(i,2,wxString::Format(wxT("%.2f"),p.y1));
01224 m_cpList->SetItem(i,3,wxString::Format(wxT("%.2f"),p.x2));
01225 m_cpList->SetItem(i,4,wxString::Format(wxT("%.2f"),p.y2));
01226 wxString mode;
01227 switch (p.mode) {
01228 case ControlPoint::X_Y:
01229 mode = _("normal");
01230 break;
01231 case ControlPoint::X:
01232 mode = _("vert. Line");
01233 break;
01234 case ControlPoint::Y:
01235 mode = _("horiz. Line");
01236 break;
01237 default:
01238 mode = wxString::Format(_("Line %d"), p.mode);
01239 break;
01240 }
01241 m_cpList->SetItem(i,5,mode);
01242 m_cpList->SetItem(i,6,wxString::Format(wxT("%.2f"),p.error));
01243 }
01244
01245 if ( selectedCP < (unsigned int) m_cpList->GetItemCount() && ! newPair) {
01246
01247 m_cpList->SetItemState( selectedCP,
01248 wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
01249 m_cpList->EnsureVisible(selectedCP);
01250 m_selectedPoint = selectedCP;
01251 EnablePointEdit(true);
01252
01253 const ControlPoint & p = currentPoints[m_selectedPoint].second;
01254 m_x1Text->SetValue(wxString::Format(wxT("%.2f"),p.x1));
01255 m_y1Text->SetValue(wxString::Format(wxT("%.2f"),p.y1));
01256 m_x2Text->SetValue(wxString::Format(wxT("%.2f"),p.x2));
01257 m_y2Text->SetValue(wxString::Format(wxT("%.2f"),p.y2));
01258 m_cpModeChoice->SetSelection(p.mode);
01259 m_leftImg->selectPoint(m_selectedPoint);
01260 m_rightImg->selectPoint(m_selectedPoint);
01261
01262 } else {
01263 m_selectedPoint = UINT_MAX;
01264 EnablePointEdit(false);
01265 }
01266
01267 for ( int j=0; j < m_cpList->GetColumnCount() ; j++ )
01268 {
01269
01270
01271 int width = wxConfigBase::Get()->Read(wxString::Format( wxT("/CPEditorPanel/ColumnWidth%d"), j ), -1);
01272 if(width != -1)
01273 m_cpList->SetColumnWidth(j, width);
01274 }
01275
01276 m_cpList->Thaw();
01277 }
01278
01279 void CPEditorPanel::EnablePointEdit(bool state)
01280 {
01281 m_delButton->Enable(state);
01282 XRCCTRL(*this, "cp_editor_finetune_button", wxButton)->Enable(state);
01283 m_x1Text->Enable(state);
01284 m_y1Text->Enable(state);
01285 m_x2Text->Enable(state);
01286 m_y2Text->Enable(state);
01287 m_cpModeChoice->Enable(state);
01288 }
01289
01290 void CPEditorPanel::OnTextPointChange(wxCommandEvent &e)
01291 {
01292 DEBUG_TRACE("");
01293
01294 long item = -1;
01295 item = m_cpList->GetNextItem(item,
01296 wxLIST_NEXT_ALL,
01297 wxLIST_STATE_SELECTED);
01298
01299 if (item == -1) {
01300 return;
01301 }
01302 unsigned int nr = (unsigned int) item;
01303 assert(nr < currentPoints.size());
01304 ControlPoint cp = currentPoints[nr].second;
01305
01306
01307 double oldValue=cp.x1;
01308 bool valid_input=str2double(m_x1Text->GetValue(), cp.x1);
01309 if(valid_input)
01310 valid_input=(cp.x1>=0) && (cp.x1<=m_pano->getSrcImage(cp.image1Nr).getWidth());
01311 if (!valid_input) {
01312 m_x1Text->Clear();
01313 *m_x1Text << oldValue;
01314 return;
01315 }
01316 oldValue=cp.y1;
01317 valid_input=str2double(m_y1Text->GetValue(), cp.y1);
01318 if(valid_input)
01319 valid_input=(cp.y1>=0) && (cp.y1<=m_pano->getSrcImage(cp.image1Nr).getHeight());
01320 if (!valid_input) {
01321 m_y1Text->Clear();
01322 *m_y1Text << oldValue;
01323 return;
01324 }
01325 oldValue=cp.x2;
01326 valid_input=str2double(m_x2Text->GetValue(), cp.x2);
01327 if(valid_input)
01328 valid_input=(cp.x2>=0) && (cp.x2<=m_pano->getSrcImage(cp.image2Nr).getWidth());
01329 if (!valid_input) {
01330 m_x2Text->Clear();
01331 *m_x2Text << oldValue;
01332 return;
01333 }
01334 oldValue=cp.y2;
01335 valid_input=str2double(m_y2Text->GetValue(), cp.y2);
01336 if(valid_input)
01337 valid_input=(cp.y2>=0) && (cp.y2<=m_pano->getSrcImage(cp.image1Nr).getHeight());
01338 if (!valid_input) {
01339 m_y2Text->Clear();
01340 *m_y2Text << oldValue;
01341 return;
01342 }
01343
01344 cp.mode = m_cpModeChoice->GetSelection();
01345
01346 if (set_contains(mirroredPoints, nr)) {
01347 cp.mirror();
01348 }
01349 GlobalCmdHist::getInstance().addCommand(
01350 new PT::ChangeCtrlPointCmd(*m_pano, currentPoints[nr].first, cp)
01351 );
01352
01353 }
01354
01355 void CPEditorPanel::OnLeftChoiceChange(wxCommandEvent & e)
01356 {
01357 DEBUG_TRACE("OnLeftChoiceChange() to " << e.GetSelection());
01358 if (m_listenToPageChange && e.GetSelection() >= 0) {
01359 setLeftImage((unsigned int) e.GetSelection());
01360 }
01361 }
01362
01363 void CPEditorPanel::OnRightChoiceChange(wxCommandEvent & e)
01364 {
01365 DEBUG_TRACE("OnRightChoiceChange() to " << e.GetSelection());
01366 if (m_listenToPageChange && e.GetSelection() >= 0) {
01367 setRightImage((unsigned int) e.GetSelection());
01368 }
01369 }
01370 void CPEditorPanel::OnCPListSelect(wxListEvent & ev)
01371 {
01372 int t = ev.GetIndex();
01373 DEBUG_TRACE("selected: " << t);
01374 if (t >=0) {
01375 SelectLocalPoint((unsigned int) t);
01376 changeState(NO_POINT);
01377 }
01378 EnablePointEdit(true);
01379 }
01380
01381 void CPEditorPanel::OnCPListDeselect(wxListEvent & ev)
01382 {
01383
01384
01385
01386
01387 changeState(NO_POINT);
01388 EnablePointEdit(false);
01389 m_leftImg->deselect();
01390 m_rightImg->deselect();
01391 }
01392
01393 void CPEditorPanel::OnZoom(wxCommandEvent & e)
01394 {
01395 double factor;
01396 switch (e.GetSelection()) {
01397 case 0:
01398 factor = 1;
01399 m_detailZoomFactor = factor;
01400 break;
01401 case 1:
01402
01403 factor = 0;
01404 break;
01405 case 2:
01406 factor = 2;
01407 m_detailZoomFactor = factor;
01408 break;
01409 case 3:
01410 factor = 1.5;
01411 m_detailZoomFactor = factor;
01412 break;
01413 case 4:
01414 factor = 0.75;
01415 break;
01416 case 5:
01417 factor = 0.5;
01418 break;
01419 case 6:
01420 factor = 0.25;
01421 break;
01422 default:
01423 DEBUG_ERROR("unknown scale factor");
01424 factor = 1;
01425 }
01426 m_leftImg->setScale(factor);
01427 m_rightImg->setScale(factor);
01428
01429 if (m_selectedPoint < UINT_MAX) {
01430 SelectLocalPoint(m_selectedPoint);
01431 }
01432 }
01433
01434 void CPEditorPanel::OnKey(wxKeyEvent & e)
01435 {
01436 DEBUG_DEBUG("key " << e.GetKeyCode()
01437 << " origin: id:" << e.GetId() << " obj: "
01438 << e.GetEventObject());
01439
01440 if (e.m_keyCode == WXK_DELETE){
01441 DEBUG_DEBUG("Delete pressed");
01442
01443 if (cpCreationState != NO_POINT) {
01444 changeState(NO_POINT);
01445 } else {
01446
01447
01448 long item = -1;
01449 item = m_cpList->GetNextItem(item,
01450 wxLIST_NEXT_ALL,
01451 wxLIST_STATE_SELECTED);
01452
01453 if (item == -1) {
01454 wxBell();
01455 return;
01456 }
01457 unsigned int pNr = localPNr2GlobalPNr((unsigned int) item);
01458 DEBUG_DEBUG("about to delete point " << pNr);
01459 GlobalCmdHist::getInstance().addCommand(
01460 new PT::RemoveCtrlPointCmd(*m_pano,pNr)
01461 );
01462 }
01463 } else if (e.m_keyCode == '0') {
01464 wxCommandEvent dummy;
01465 dummy.SetInt(1);
01466 OnZoom(dummy);
01467 XRCCTRL(*this,"cp_editor_choice_zoom",wxChoice)->SetSelection(1);
01468 } else if (e.m_keyCode == '1') {
01469 wxCommandEvent dummy;
01470 dummy.SetInt(0);
01471 OnZoom(dummy);
01472 XRCCTRL(*this,"cp_editor_choice_zoom",wxChoice)->SetSelection(0);
01473 } else if (e.m_keyCode == '2') {
01474 wxCommandEvent dummy;
01475 dummy.SetInt(2);
01476 OnZoom(dummy);
01477 XRCCTRL(*this,"cp_editor_choice_zoom",wxChoice)->SetSelection(2);
01478 } else if (e.CmdDown() && e.GetKeyCode() == WXK_LEFT) {
01479
01480 wxCommandEvent dummy;
01481 OnPrevImg(dummy);
01482 } else if (e.CmdDown() && e.GetKeyCode() == WXK_RIGHT) {
01483
01484 wxCommandEvent dummy;
01485 OnNextImg(dummy);
01486 } else if (e.GetKeyCode() == 'f') {
01487 bool left = e.GetEventObject() == m_leftImg;
01488 if (cpCreationState == NO_POINT) {
01489 FineTuneSelectedPoint(left);
01490 } else if (cpCreationState == BOTH_POINTS_SELECTED) {
01491 FineTuneNewPoint(left);
01492 }
01493 } else if (e.GetKeyCode() == 'g') {
01494
01495 long th = wxGetNumberFromUser(_("Create control points.\nTo create less points,\nenter a higher number."), _("Corner Detection threshold"), _("Create control points"), 400, 0, 32000);
01496 if (th == -1) {
01497 return;
01498 }
01499 long scale = wxGetNumberFromUser(_("Create control points"), _("Corner Detection scale"), _("Create control points"), 2);
01500 if (scale == -1) {
01501 return;
01502 }
01503
01504 try {
01505 wxBusyCursor busy;
01506 DEBUG_DEBUG("corner threshold: " << th << " scale: " << scale);
01507 GlobalCmdHist::getInstance().addCommand(
01508 new wxAddCtrlPointGridCmd(*m_pano, m_leftImageNr, m_rightImageNr, scale, th)
01509 );
01510 } catch (std::exception & e) {
01511 wxLogError(_("Error during control point creation:\n") + wxString(e.what(), wxConvLocal));
01512 }
01513 } else {
01514 e.Skip();
01515 }
01516 }
01517
01518 void CPEditorPanel::OnAddButton(wxCommandEvent & e)
01519 {
01520
01521 if (cpCreationState == BOTH_POINTS_SELECTED) {
01522 CreateNewPoint();
01523 }
01524 }
01525
01526 void CPEditorPanel::OnDeleteButton(wxCommandEvent & e)
01527 {
01528 DEBUG_TRACE("");
01529
01530 if (cpCreationState != NO_POINT) {
01531 changeState(NO_POINT);
01532 } else {
01533
01534 long item = -1;
01535 item = m_cpList->GetNextItem(item,
01536 wxLIST_NEXT_ALL,
01537 wxLIST_STATE_SELECTED);
01538
01539 if (item == -1) {
01540 wxBell();
01541 return;
01542 }
01543
01544 unsigned int pNr = localPNr2GlobalPNr((unsigned int) item);
01545
01546 GlobalCmdHist::getInstance().addCommand(
01547 new PT::RemoveCtrlPointCmd(*m_pano,pNr )
01548 );
01549 m_leftChoice->CalcCPDistance(m_pano);
01550 m_rightChoice->CalcCPDistance(m_pano);
01551 }
01552 }
01553
01554
01555 void CPEditorPanel::ShowControlPoint(unsigned int cpNr)
01556 {
01557 const ControlPoint & p = m_pano->getCtrlPoint(cpNr);
01558 setLeftImage(p.image1Nr);
01559 setRightImage(p.image2Nr);
01560
01561 changeState(NO_POINT);
01562
01563 SelectGlobalPoint(cpNr);
01564 }
01565
01566 void CPEditorPanel::changeState(CPCreationState newState)
01567 {
01568 DEBUG_TRACE(cpCreationState << " --> " << newState);
01569
01570 bool fineTune = m_fineTuneCB->IsChecked() && (m_leftImageNr != m_rightImageNr);
01571 switch(newState) {
01572 case NO_POINT:
01573
01574 m_leftImg->showSearchArea(false);
01575 m_rightImg->showSearchArea(false);
01576
01577 m_leftImg->showTemplateArea(fineTune);
01578 m_rightImg->showTemplateArea(fineTune);
01579 m_addButton->Enable(false);
01580 if (m_selectedPoint < UINT_MAX) {
01581 m_delButton->Enable(true);
01582 } else {
01583 m_delButton->Enable(false);
01584 }
01585 if (cpCreationState != NO_POINT) {
01586
01587 wxCommandEvent tmpEvt;
01588 tmpEvt.SetInt(XRCCTRL(*this,"cp_editor_choice_zoom",wxChoice)->GetSelection());
01589 OnZoom(tmpEvt);
01590 m_leftImg->clearNewPoint();
01591 m_rightImg->clearNewPoint();
01592 }
01593 break;
01594 case LEFT_POINT:
01595
01596 m_leftImg->showSearchArea(false);
01597
01598 m_rightImg->showSearchArea(fineTune);
01599
01600
01601 m_leftImg->showTemplateArea(fineTune);
01602 m_rightImg->showTemplateArea(false);
01603
01604
01605 ClearSelection();
01606 m_addButton->Enable(false);
01607 m_delButton->Enable(false);
01608 MainFrame::Get()->SetStatusText(_("Select point in right image"),0);
01609 break;
01610 case RIGHT_POINT:
01611 m_leftImg->showSearchArea(fineTune);
01612 m_rightImg->showSearchArea(false);
01613
01614 m_leftImg->showTemplateArea(false);
01615 m_rightImg->showTemplateArea(fineTune);
01616
01617 ClearSelection();
01618 m_addButton->Enable(false);
01619 m_delButton->Enable(false);
01620 MainFrame::Get()->SetStatusText(_("Select point in left image"),0);
01621 break;
01622 case LEFT_POINT_RETRY:
01623 case RIGHT_POINT_RETRY:
01624 m_leftImg->showSearchArea(false);
01625 m_rightImg->showSearchArea(false);
01626
01627 m_leftImg->showTemplateArea(false);
01628 m_rightImg->showTemplateArea(false);
01629 m_addButton->Enable(false);
01630 m_delButton->Enable(false);
01631 break;
01632 case BOTH_POINTS_SELECTED:
01633 m_leftImg->showTemplateArea(false);
01634 m_rightImg->showTemplateArea(false);
01635 m_leftImg->showSearchArea(false);
01636 m_rightImg->showSearchArea(false);
01637 m_addButton->Enable(true);
01638 m_delButton->Enable(false);
01639 }
01640
01641 cpCreationState = newState;
01642 }
01643
01644 void CPEditorPanel::OnPrevImg(wxCommandEvent & e)
01645 {
01646 if (m_pano->getNrOfImages() < 2) return;
01647 int nImgs = m_pano->getNrOfImages();
01648 int left = m_leftImageNr -1;
01649 int right = m_rightImageNr -1;
01650 if (left < 0) {
01651 left += nImgs;
01652 } else if (left >= nImgs) {
01653 left -= nImgs;
01654 }
01655
01656 if (right < 0) {
01657 right += nImgs;
01658 } else if (right >= nImgs) {
01659 right -= nImgs;
01660 }
01661 setLeftImage((unsigned int) left);
01662 setRightImage((unsigned int) right);
01663 }
01664
01665 void CPEditorPanel::OnNextImg(wxCommandEvent & e)
01666 {
01667 if (m_pano->getNrOfImages() < 2) return;
01668 int nImgs = m_pano->getNrOfImages();
01669 int left = m_leftImageNr + 1;
01670 int right = m_rightImageNr + 1;
01671 if (left < 0) {
01672 left += nImgs;
01673 } else if (left >= nImgs) {
01674 left -= nImgs;
01675 }
01676
01677 if (right < 0) {
01678 right += nImgs;
01679 } else if (right >= nImgs) {
01680 right -= nImgs;
01681 }
01682 setLeftImage((unsigned int) left);
01683 setRightImage((unsigned int) right);
01684 }
01685
01686 void CPEditorPanel::OnFineTuneButton(wxCommandEvent & e)
01687 {
01688 if (cpCreationState == NO_POINT) {
01689 FineTuneSelectedPoint(false);
01690 } else if (cpCreationState == BOTH_POINTS_SELECTED) {
01691 FineTuneNewPoint(false);
01692 }
01693 }
01694
01695 void CPEditorPanel::OnCelesteButton(wxCommandEvent & e)
01696 {
01697 if (currentPoints.size() == 0)
01698 {
01699 wxMessageBox(_("Cannot run celeste without at least one control point connecting the two images"),_("Error"));
01700 cout << "Cannot run celeste without at least one control point connecting the two images" << endl;
01701 }
01702 else
01703 {
01704 ProgressReporterDialog progress(4, _("Running Celeste"), _("Running Celeste"),this);
01705 MainFrame::Get()->SetStatusText(_("searching for cloud-like control points..."),0);
01706 progress.increaseProgress(1.0, std::wstring(wxString(_("Loading model file")).wc_str(wxConvLocal)));
01707
01708 struct celeste::svm_model* model=MainFrame::Get()->GetSVMModel();
01709 if(model==NULL)
01710 {
01711 MainFrame::Get()->SetStatusText(wxT(""),0);
01712 return;
01713 };
01714
01715
01716 wxConfigBase *cfg = wxConfigBase::Get();
01717
01718 double threshold = HUGIN_CELESTE_THRESHOLD;
01719 cfg->Read(wxT("/Celeste/Threshold"), &threshold, HUGIN_CELESTE_THRESHOLD);
01720
01721
01722 bool t = (cfg->Read(wxT("/Celeste/Filter"), HUGIN_CELESTE_FILTER) == 0);
01723 int radius=(t)?10:20;
01724 DEBUG_TRACE("Running Celeste");
01725
01726 progress.increaseProgress(1.0, std::wstring(wxString(_("Running Celeste")).wc_str(wxConvLocal)));
01727
01728 ImageCache::EntryPtr img=ImageCache::getInstance().getImage(m_pano->getImage(m_leftImageNr).getFilename());
01729 vigra::UInt16RGBImage in;
01730 if(img->image16->width()>0)
01731 {
01732 in.resize(img->image16->size());
01733 vigra::copyImage(srcImageRange(*(img->image16)),destImage(in));
01734 }
01735 else
01736 {
01737 ImageCache::ImageCacheRGB8Ptr im8=img->get8BitImage();
01738 in.resize(im8->size());
01739 vigra::transformImage(srcImageRange(*im8),destImage(in),vigra::functor::Arg1()*vigra::functor::Param(65535/255));
01740 };
01741 UIntSet cloudCP=celeste::getCelesteControlPoints(model,in,currentPoints,radius,threshold,800);
01742 in.resize(0,0);
01743 progress.increaseProgress(1.0, std::wstring(wxString(_("Running Celeste")).wc_str(wxConvLocal)));
01744
01745 if(cloudCP.size()>0)
01746 {
01747 GlobalCmdHist::getInstance().addCommand(
01748 new PT::RemoveCtrlPointsCmd(*m_pano,cloudCP)
01749 );
01750 };
01751
01752 progress.increaseProgress(1.0, std::wstring(wxString(_("Running Celeste")).wc_str(wxConvLocal)));
01753 wxMessageBox(wxString::Format(_("Removed %d control points"), cloudCP.size()), _("Celeste result"),wxOK|wxICON_INFORMATION,this);
01754 DEBUG_TRACE("Finished running Celeste");
01755 MainFrame::Get()->SetStatusText(wxT(""),0);
01756 }
01757 }
01758
01759 FDiff2D CPEditorPanel::LocalFineTunePoint(unsigned int srcNr,
01760 const Diff2D & srcPnt,
01761 unsigned int moveNr,
01762 const FDiff2D & movePnt)
01763 {
01764 long templWidth = wxConfigBase::Get()->Read(wxT("/Finetune/TemplateSize"),HUGIN_FT_TEMPLATE_SIZE);
01765 long sWidth = templWidth + wxConfigBase::Get()->Read(wxT("/Finetune/LocalSearchWidth"),HUGIN_FT_LOCAL_SEARCH_WIDTH);
01766 CorrelationResult result;
01767 PointFineTune(srcNr,
01768 srcPnt,
01769 templWidth,
01770 moveNr,
01771 movePnt,
01772 sWidth,
01773 result);
01774 return result.maxpos;
01775 }
01776
01777 void CPEditorPanel::FineTuneSelectedPoint(bool left)
01778 {
01779 DEBUG_DEBUG(" selected Point: " << m_selectedPoint);
01780 if (m_selectedPoint == UINT_MAX) return;
01781 DEBUG_ASSERT(m_selectedPoint < currentPoints.size());
01782
01783 ControlPoint cp = currentPoints[m_selectedPoint].second;
01784
01785 unsigned int srcNr = cp.image1Nr;
01786 unsigned int moveNr = cp.image2Nr;
01787 Diff2D srcPnt(roundi(cp.x1), roundi(cp.y1));
01788 Diff2D movePnt(roundi(cp.x2), roundi(cp.y2));
01789 if (left) {
01790 srcNr = cp.image2Nr;
01791 moveNr = cp.image1Nr;
01792 srcPnt = Diff2D(roundi(cp.x2), roundi(cp.y2));
01793 movePnt = Diff2D(roundi(cp.x1), roundi(cp.y1));
01794 }
01795
01796 FDiff2D result = LocalFineTunePoint(srcNr, srcPnt, moveNr, movePnt);
01797
01798 if (left) {
01799 cp.x1 = result.x;
01800 cp.y1 = result.y;
01801 cp.x2 = srcPnt.x;
01802 cp.y2 = srcPnt.y;
01803 } else {
01804 cp.x2 = result.x;
01805 cp.y2 = result.y;
01806 cp.x1 = srcPnt.x;
01807 cp.y1 = srcPnt.y;
01808 }
01809
01810
01811 if (set_contains(mirroredPoints, m_selectedPoint)) {
01812 cp.mirror();
01813 }
01814 GlobalCmdHist::getInstance().addCommand(
01815 new PT::ChangeCtrlPointCmd(*m_pano, currentPoints[m_selectedPoint].first, cp)
01816 );
01817 }
01818
01819
01820 void CPEditorPanel::FineTuneNewPoint(bool left)
01821 {
01822 if (!(cpCreationState == RIGHT_POINT_RETRY ||
01823 cpCreationState == LEFT_POINT_RETRY ||
01824 cpCreationState == BOTH_POINTS_SELECTED))
01825 {
01826 return;
01827 }
01828
01829 FDiff2D leftP = m_leftImg->getNewPoint();
01830 FDiff2D rightP = m_rightImg->getNewPoint();
01831
01832 unsigned int srcNr = m_leftImageNr;
01833 Diff2D srcPnt(leftP.toDiff2D());
01834 unsigned int moveNr = m_rightImageNr;
01835 Diff2D movePnt(rightP.toDiff2D());
01836 if (left) {
01837 srcNr = m_rightImageNr;
01838 srcPnt = rightP.toDiff2D();
01839 moveNr = m_leftImageNr;
01840 movePnt = leftP.toDiff2D();
01841 }
01842
01843 FDiff2D result = LocalFineTunePoint(srcNr, srcPnt, moveNr, movePnt);
01844
01845 if (left) {
01846 m_leftImg->setNewPoint(result);
01847 m_leftImg->update();
01848 m_rightImg->setNewPoint(srcPnt);
01849 m_rightImg->update();
01850
01851 } else {
01852 m_rightImg->setNewPoint(result);
01853 m_rightImg->update();
01854 m_leftImg->setNewPoint(srcPnt);
01855 m_leftImg->update();
01856 }
01857 }
01858
01859 FDiff2D CPEditorPanel::EstimatePoint(const FDiff2D & p, bool left)
01860 {
01861 int imgNr = left? m_rightImageNr : m_leftImageNr;
01862 const SrcPanoImage & img = m_pano->getImage(imgNr);
01863 FDiff2D t;
01864 if (currentPoints.size() == 0) {
01865 DEBUG_WARN("Cannot estimate position without at least one point");
01866 return FDiff2D(0,0);
01867 }
01868
01869 for (HuginBase::CPointVector::const_iterator it = currentPoints.begin(); it != currentPoints.end(); ++it) {
01870 t.x += it->second.x2 - it->second.x1;
01871 t.y += it->second.y2 - it->second.y1;
01872 }
01873 t.x /= currentPoints.size();
01874 t.y /= currentPoints.size();
01875 DEBUG_DEBUG("estimated translation: x: " << t.x << " y: " << t.y);
01876
01877 if (left) {
01878 t.x += p.x;
01879 t.y += p.y;
01880 } else {
01881 t.x = p.x - t.x;
01882 t.y = p.y - t.y;
01883 }
01884
01885
01886 if (t.x < 0) t.x=0;
01887 if (t.y < 0) t.y=0;
01888 if (t.x > img.getWidth()) t.x = img.getWidth();
01889 if (t.y > img.getHeight()) t.y = img.getHeight();
01890 DEBUG_DEBUG("estimated point " << t.x << "," << t.y);
01891 return t;
01892 }
01893
01894 void CPEditorPanel::OnColumnWidthChange( wxListEvent & e )
01895 {
01896 int colNum = e.GetColumn();
01897 wxConfigBase::Get()->Write( wxString::Format(wxT("/CPEditorPanel/ColumnWidth%d"),colNum), m_cpList->GetColumnWidth(colNum) );
01898 }
01899
01900 CPImageCtrl::ImageRotation CPEditorPanel::GetRot(double yaw, double pitch, double roll)
01901 {
01902 CPImageCtrl::ImageRotation rot = CPImageCtrl::ROT0;
01903
01904 while (roll > 360) roll-= 360;
01905 while (roll < 0) roll += 360;
01906
01907 while (pitch > 180) pitch -= 360;
01908 while (pitch < -180) pitch += 360;
01909 bool headOver = (pitch > 90 || pitch < -90);
01910
01911 if (wxConfig::Get()->Read(wxT("/CPEditorPanel/AutoRot"),1L)) {
01912 if (roll >= 315 || roll < 45) {
01913 rot = headOver ? CPImageCtrl::ROT180 : CPImageCtrl::ROT0;
01914 } else if (roll >= 45 && roll < 135) {
01915 rot = headOver ? CPImageCtrl::ROT270 : CPImageCtrl::ROT90;
01916 } else if (roll >= 135 && roll < 225) {
01917 rot = headOver ? CPImageCtrl::ROT0 : CPImageCtrl::ROT180;
01918 } else {
01919 rot = headOver ? CPImageCtrl::ROT90 : CPImageCtrl::ROT270;
01920 }
01921 }
01922 return rot;
01923 }
01924
01925 IMPLEMENT_DYNAMIC_CLASS(CPEditorPanel, wxPanel)
01926
01927 CPEditorPanelXmlHandler::CPEditorPanelXmlHandler()
01928 : wxXmlResourceHandler()
01929 {
01930 AddWindowStyles();
01931 }
01932
01933 wxObject *CPEditorPanelXmlHandler::DoCreateResource()
01934 {
01935 XRC_MAKE_INSTANCE(cp, CPEditorPanel)
01936
01937 cp->Create(m_parentAsWindow,
01938 GetID(),
01939 GetPosition(), GetSize(),
01940 GetStyle(wxT("style")),
01941 GetName());
01942
01943 SetupWindow( cp);
01944
01945 return cp;
01946 }
01947
01948 bool CPEditorPanelXmlHandler::CanHandle(wxXmlNode *node)
01949 {
01950 return IsOfClass(node, wxT("CPEditorPanel"));
01951 }
01952
01953 IMPLEMENT_DYNAMIC_CLASS(CPEditorPanelXmlHandler, wxXmlResourceHandler)
01954