00001
00002
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "panoinc_WX.h"
00030 #include "panoinc.h"
00031 #include "base_wx/platform.h"
00032 #include "hugin/MainFrame.h"
00033 #include "hugin/config_defaults.h"
00034 #include "hugin/MaskImageCtrl.h"
00035 #include "hugin/MaskEditorPanel.h"
00036 #include "base_wx/wxImageCache.h"
00037 #ifndef SUPPORTS_WXINVERT
00038 #include <vigra/inspectimage.hxx>
00039 #endif
00040
00041 using namespace hugin_utils;
00042
00044 const int polygonPointSize=3;
00046 const int maxSelectionDistance=20;
00047
00048
00049
00050 BEGIN_EVENT_TABLE(MaskImageCtrl, wxScrolledWindow)
00051 EVT_SIZE(MaskImageCtrl::OnSize)
00052 EVT_MOTION(MaskImageCtrl::OnMouseMove)
00053 EVT_LEFT_DOWN(MaskImageCtrl::OnLeftMouseDown)
00054 EVT_LEFT_UP(MaskImageCtrl::OnLeftMouseUp)
00055 EVT_LEFT_DCLICK(MaskImageCtrl::OnLeftMouseDblClick)
00056 EVT_RIGHT_DOWN(MaskImageCtrl::OnRightMouseDown)
00057 EVT_RIGHT_UP(MaskImageCtrl::OnRightMouseUp)
00058 EVT_KEY_UP(MaskImageCtrl::OnKeyUp)
00059 EVT_MOUSE_CAPTURE_LOST(MaskImageCtrl::OnCaptureLost)
00060 EVT_KILL_FOCUS(MaskImageCtrl::OnKillFocus)
00061 END_EVENT_TABLE()
00062
00063 bool MaskImageCtrl::Create(wxWindow * parent, wxWindowID id,
00064 const wxPoint& pos,
00065 const wxSize& size,
00066 long style,
00067 const wxString& name)
00068 {
00069 wxScrolledWindow::Create(parent, id, pos, size, style, name);
00070 m_maskEditState = NO_IMAGE;
00071 m_imgRotation = ROT0;
00072 m_scaleFactor = 1;
00073 m_fitToWindow = false;
00074 m_previewOnly = false;
00075 m_activeMask = UINT_MAX;
00076 m_showActiveMasks = false;
00077 m_maskMode = true;
00078
00079 return true;
00080 }
00081
00082 void MaskImageCtrl::Init(MaskEditorPanel * parent)
00083 {
00084 m_editPanel = parent;
00085 }
00086
00087 void MaskImageCtrl::SetMaskMode(bool newMaskMode)
00088 {
00089 m_maskMode=newMaskMode;
00090 if(m_maskMode)
00091 {
00092 SetCursor(wxNullCursor);
00093 if(m_maskEditState!=NO_IMAGE)
00094 {
00095 m_maskEditState=NO_SELECTION;
00096 setActiveMask(UINT_MAX,false);
00097 };
00098 }
00099 else
00100 {
00101 if(m_maskEditState!=NO_IMAGE)
00102 {
00103 m_maskEditState=CROP_SHOWING;
00104 };
00105 };
00106 };
00107
00108 void MaskImageCtrl::setImage(const std::string & file, HuginBase::MaskPolygonVector newMask, HuginBase::MaskPolygonVector masksToDraw, ImageRotation rot)
00109 {
00110 DEBUG_TRACE("setting Image " << file);
00111 m_imageFilename = file;
00112 wxString fn(m_imageFilename.c_str(),HUGIN_CONV_FILENAME);
00113 if (wxFileName::FileExists(fn))
00114 {
00115 m_img = ImageCache::getInstance().getImage(m_imageFilename);
00116 if(m_maskMode)
00117 {
00118 m_maskEditState = NO_MASK;
00119 }
00120 else
00121 {
00122 m_maskEditState = CROP_SHOWING;
00123 };
00124 m_imageMask=newMask;
00125 m_masksToDraw=masksToDraw;
00126 m_imgRotation=rot;
00127 setActiveMask(UINT_MAX,false);
00128 rescaleImage();
00129 }
00130 else
00131 {
00132 m_maskEditState = NO_IMAGE;
00133 m_bitmap = wxBitmap();
00134
00135
00136 m_img = ImageCache::EntryPtr(new ImageCache::Entry);
00137 HuginBase::MaskPolygonVector mask;
00138 m_imageMask=mask;
00139 m_masksToDraw=mask;
00140 m_imgRotation=ROT0;
00141 setActiveMask(UINT_MAX,false);
00142 SetVirtualSize(100,100);
00143 Refresh(true);
00144 }
00145 }
00146
00147 void MaskImageCtrl::setNewMasks(HuginBase::MaskPolygonVector newMasks, HuginBase::MaskPolygonVector masksToDraw)
00148 {
00149 m_imageMask=newMasks;
00150 m_masksToDraw=masksToDraw;
00151 if(m_activeMask>=m_imageMask.size())
00152 setActiveMask(UINT_MAX);
00153 Refresh(false);
00154 };
00155
00156 void MaskImageCtrl::setCrop(HuginBase::SrcPanoImage::CropMode newCropMode, vigra::Rect2D newCropRect, bool isCentered, hugin_utils::FDiff2D center, bool isCircleCrop)
00157 {
00158 m_cropMode=newCropMode;
00159 m_cropRect=newCropRect;
00160 m_cropCentered=isCentered;
00161 m_cropCenter=center;
00162 m_cropCircle=isCircleCrop;
00163 };
00164
00165 void MaskImageCtrl::setActiveMask(unsigned int newMask, bool doUpdate)
00166 {
00167 if(m_activeMask!=newMask)
00168 {
00169 m_activeMask=newMask;
00170 m_selectedPoints.clear();
00171 };
00172 if(newMask<UINT_MAX)
00173 {
00174 if(m_maskMode)
00175 {
00176 if(m_selectedPoints.empty())
00177 {
00178 m_maskEditState=NO_SELECTION;
00179 }
00180 else
00181 {
00182 m_maskEditState=POINTS_SELECTED;
00183 };
00184 }
00185 else
00186 {
00187 m_selectedPoints.clear();
00188 m_maskEditState=CROP_SHOWING;
00189 };
00190 m_editingMask=m_imageMask[m_activeMask];
00191 }
00192 else
00193 {
00194 if(!m_imageFilename.empty())
00195 {
00196 if(m_maskMode)
00197 {
00198 m_maskEditState=NO_MASK;
00199 }
00200 else
00201 {
00202 m_maskEditState=CROP_SHOWING;
00203 };
00204 };
00205 HuginBase::MaskPolygon mask;
00206 m_editingMask=mask;
00207 };
00208 if(doUpdate)
00209 Refresh(true);
00210 };
00211
00212 void MaskImageCtrl::selectAllMarkers()
00213 {
00214 m_selectedPoints.clear();
00215 if(m_activeMask<UINT_MAX)
00216 fill_set(m_selectedPoints,0,m_imageMask[m_activeMask].getMaskPolygon().size()-1);
00217 };
00218
00219
00220 MaskImageCtrl::ClickPos MaskImageCtrl::GetClickPos(vigra::Point2D pos)
00221 {
00222 vigra::Rect2D testRect(pos.x-maxSelectionDistance, pos.y-maxSelectionDistance, pos.x+maxSelectionDistance, pos.y+maxSelectionDistance);
00223 if(m_cropMode==SrcPanoImage::CROP_CIRCLE)
00224 {
00225 double radius=std::min<int>(m_cropRect.width(), m_cropRect.height())/2.0;
00226 vigra::Point2D pos_center((m_cropRect.left()+m_cropRect.right())/2, (m_cropRect.top()+m_cropRect.bottom())/2);
00227 double dist=sqrt(double((pos-pos_center).squaredMagnitude()));
00228 if(dist-maxSelectionDistance<radius && radius<dist+maxSelectionDistance)
00229 {
00230 return CLICK_CIRCLE;
00231 };
00232 };
00233 if(m_cropRect.intersects(testRect))
00234 {
00235 if(abs(pos.x-m_cropRect.left())<maxSelectionDistance)
00236 {
00237 return CLICK_LEFT;
00238 };
00239 if(abs(pos.x-m_cropRect.right())<maxSelectionDistance)
00240 {
00241 return CLICK_RIGHT;
00242 };
00243 if(abs(pos.y-m_cropRect.top())<maxSelectionDistance)
00244 {
00245 return CLICK_TOP;
00246 };
00247 if(abs(pos.y-m_cropRect.bottom())<maxSelectionDistance)
00248 {
00249 return CLICK_BOTTOM;
00250 };
00251 };
00252 if(m_cropRect.contains(pos))
00253 {
00254 return CLICK_INSIDE;
00255 };
00256 return CLICK_OUTSIDE;
00257 };
00258
00259 void MaskImageCtrl::UpdateCrop(hugin_utils::FDiff2D pos)
00260 {
00261 FDiff2D delta=pos-applyRotInv(invtransform(m_currentPos));
00262 int newLeft, newRight, newTop, newBottom;
00263 bool needsUpdate=false;
00264 switch (m_maskEditState)
00265 {
00266 case CROP_MOVING:
00267 m_cropRect.moveBy(delta.x,delta.y);
00268 break;
00269 case CROP_LEFT_MOVING:
00270 if(m_cropCentered)
00271 {
00272 double newHalfWidth=m_cropRect.width()/2.0-delta.x;
00273 newLeft=hugin_utils::roundi(m_cropCenter.x-newHalfWidth);
00274 newRight=hugin_utils::roundi(m_cropCenter.x+newHalfWidth);
00275 }
00276 else
00277 {
00278 newLeft=m_cropRect.left()+delta.x;
00279 newRight=m_cropRect.right();
00280 };
00281 newTop=m_cropRect.top();
00282 newBottom=m_cropRect.bottom();
00283 needsUpdate=true;
00284 break;
00285 case CROP_RIGHT_MOVING:
00286 if(m_cropCentered)
00287 {
00288 double newHalfWidth=m_cropRect.width()/2.0+delta.x;
00289 newLeft=hugin_utils::roundi(m_cropCenter.x-newHalfWidth);
00290 newRight=hugin_utils::roundi(m_cropCenter.x+newHalfWidth);
00291 }
00292 else
00293 {
00294 newLeft=m_cropRect.left();
00295 newRight=m_cropRect.right()+delta.x;
00296 };
00297 newTop=m_cropRect.top();
00298 newBottom=m_cropRect.bottom();
00299 needsUpdate=true;
00300 break;
00301 case CROP_TOP_MOVING:
00302 if(m_cropCentered)
00303 {
00304 double newHalfHeight=m_cropRect.height()/2.0-delta.y;
00305 newTop=hugin_utils::roundi(m_cropCenter.y-newHalfHeight);
00306 newBottom=hugin_utils::roundi(m_cropCenter.y+newHalfHeight);
00307 }
00308 else
00309 {
00310 newTop=m_cropRect.top()+delta.y;
00311 newBottom=m_cropRect.bottom();
00312 };
00313 newLeft=m_cropRect.left();
00314 newRight=m_cropRect.right();
00315 needsUpdate=true;
00316 break;
00317 case CROP_BOTTOM_MOVING:
00318 if(m_cropCentered)
00319 {
00320 double newHalfHeight=m_cropRect.height()/2.0+delta.y;
00321 newTop=hugin_utils::roundi(m_cropCenter.y-newHalfHeight);
00322 newBottom=hugin_utils::roundi(m_cropCenter.y+newHalfHeight);
00323 }
00324 else
00325 {
00326 newTop=m_cropRect.top();
00327 newBottom=m_cropRect.bottom()+delta.y;
00328 };
00329 newLeft=m_cropRect.left();
00330 newRight=m_cropRect.right();
00331 needsUpdate=true;
00332 break;
00333 case CROP_CIRCLE_SCALING:
00334 {
00335 double radius=sqrt(sqr(pos.x-m_dragStartPos.x)+sqr(pos.y-m_dragStartPos.y));
00336 newLeft=m_dragStartPos.x-radius;
00337 newRight=m_dragStartPos.x+radius;
00338 newTop=m_dragStartPos.y-radius;
00339 newBottom=m_dragStartPos.y+radius;
00340 needsUpdate=true;
00341 };
00342 break;
00343 };
00344 if(needsUpdate)
00345 {
00346
00347 if(newLeft>newRight)
00348 {
00349 int temp=newLeft;
00350 newLeft=newRight;
00351 newRight=temp;
00352 };
00353 if(newTop>newBottom)
00354 {
00355 int temp=newTop;
00356 newTop=newBottom;
00357 newBottom=temp;
00358 };
00359 m_cropRect.setUpperLeft(vigra::Point2D(newLeft, newTop));
00360 m_cropRect.setLowerRight(vigra::Point2D(newRight, newBottom));
00361 };
00362 };
00363
00364 void MaskImageCtrl::OnMouseMove(wxMouseEvent& mouse)
00365 {
00366 if(m_previewOnly)
00367 return;
00368 wxPoint mpos;
00369 CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
00370 &mpos.x, & mpos.y);
00371 FDiff2D currentPos=applyRotInv(invtransform(mpos));
00372 bool doUpdate = false;
00373 switch(m_maskEditState)
00374 {
00375 case NEW_POLYGON_CREATING:
00376 doUpdate=true;
00377 m_editingMask.movePointTo(m_editingMask.getMaskPolygon().size()-1,currentPos);
00378 break;
00379 case POLYGON_SELECTING:
00380 case REGION_SELECTING:
00381 case POINTS_DELETING:
00382 #if defined SUPPORTS_WXINVERT
00383 DrawSelectionRectangle();
00384 #endif
00385 m_currentPos=mpos;
00386 DrawSelectionRectangle();
00387 break;
00388 case POINTS_MOVING:
00389 doUpdate=true;
00390 m_editingMask=m_imageMask[m_activeMask];
00391 {
00392 FDiff2D delta=currentPos-applyRotInv(invtransform(m_dragStartPos));
00393 for(HuginBase::UIntSet::const_iterator it=m_selectedPoints.begin();it!=m_selectedPoints.end();it++)
00394 m_editingMask.movePointBy(*it,delta);
00395 };
00396 break;
00397 case POINTS_ADDING:
00398 doUpdate=true;
00399 for(HuginBase::UIntSet::const_iterator it=m_selectedPoints.begin();it!=m_selectedPoints.end();it++)
00400 m_editingMask.movePointTo(*it,currentPos);
00401 break;
00402 case CROP_SHOWING:
00403 switch(GetClickPos(vigra::Point2D(currentPos.x, currentPos.y)))
00404 {
00405 case CLICK_INSIDE:
00406 if(!m_cropCentered)
00407 {
00408 SetCursor(wxCURSOR_HAND);
00409 }
00410 else
00411 {
00412 SetCursor(wxNullCursor);
00413 };
00414 break;
00415 case CLICK_LEFT:
00416 case CLICK_RIGHT:
00417 switch (m_imgRotation)
00418 {
00419 case ROT90:
00420 case ROT270:
00421 SetCursor(wxCURSOR_SIZENS);
00422 break;
00423 default:
00424 SetCursor(wxCURSOR_SIZEWE);
00425 };
00426 break;
00427 case CLICK_TOP:
00428 case CLICK_BOTTOM:
00429 switch (m_imgRotation)
00430 {
00431 case ROT90:
00432 case ROT270:
00433 SetCursor(wxCURSOR_SIZEWE);
00434 break;
00435 default:
00436 SetCursor(wxCURSOR_SIZENS);
00437 };
00438 break;
00439 case CLICK_CIRCLE:
00440 SetCursor(wxCURSOR_SIZING);
00441 break;
00442 default:
00443 SetCursor(wxNullCursor);
00444 };
00445 break;
00446 case CROP_MOVING:
00447 case CROP_LEFT_MOVING:
00448 case CROP_RIGHT_MOVING:
00449 case CROP_TOP_MOVING:
00450 case CROP_BOTTOM_MOVING:
00451 case CROP_CIRCLE_SCALING:
00452 #if defined SUPPORTS_WXINVERT
00453 DrawCrop();
00454 #else
00455 doUpdate=true;
00456 #endif
00457 UpdateCrop(currentPos);
00458 m_currentPos=mpos;
00459 #if defined SUPPORTS_WXINVERT
00460 DrawCrop();
00461 #endif
00462 m_editPanel->UpdateCropFromImage();
00463 break;
00464 };
00465 if(doUpdate)
00466 update();
00467 }
00468
00469 void MaskImageCtrl::OnLeftMouseDown(wxMouseEvent& mouse)
00470 {
00471 if(m_previewOnly)
00472 return;
00473 DEBUG_DEBUG("LEFT MOUSE DOWN");
00474 CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
00475 &m_dragStartPos.x, & m_dragStartPos.y);
00476 FDiff2D currentPos=applyRotInv(invtransform(m_dragStartPos));
00477 m_currentPos=m_dragStartPos;
00478 if(!HasCapture())
00479 CaptureMouse();
00480 SetFocus();
00481 switch(m_maskEditState)
00482 {
00483 case NEW_POLYGON_STARTED:
00484
00485 m_editingMask.addPoint(currentPos);
00486 m_selectedPoints.insert(m_editingMask.getMaskPolygon().size()-1);
00487 break;
00488 case NO_MASK:
00489 if(m_maskMode)
00490 {
00491 m_maskEditState=POLYGON_SELECTING;
00492 DrawSelectionRectangle();
00493 };
00494 break;
00495 case NO_SELECTION:
00496 if(mouse.CmdDown())
00497 {
00498
00499 unsigned int index=m_editingMask.FindPointNearPos(currentPos,5*maxSelectionDistance);
00500 if(index<UINT_MAX)
00501 {
00502 m_selectedPoints.clear();
00503 m_editingMask.insertPoint(index,currentPos);
00504 m_selectedPoints.insert(index);
00505 m_maskEditState=POINTS_ADDING;
00506 };
00507 }
00508 else
00509 {
00510 HuginBase::UIntSet points;
00511 if(SelectPointsInsideMouseRect(points,false))
00512 {
00513 for(HuginBase::UIntSet::const_iterator it=points.begin();it!=points.end();it++)
00514 m_selectedPoints.insert(*it);
00515 m_maskEditState=POINTS_MOVING;
00516 }
00517 else
00518 {
00519 m_maskEditState=REGION_SELECTING;
00520 DrawSelectionRectangle();
00521 }
00522 };
00523 break;
00524 case POINTS_SELECTED:
00525 if(mouse.CmdDown())
00526 {
00527
00528 unsigned int index=m_editingMask.FindPointNearPos(currentPos, 5*maxSelectionDistance);
00529 if(index<UINT_MAX)
00530 {
00531 m_selectedPoints.clear();
00532 m_editingMask.insertPoint(index,currentPos);
00533 m_selectedPoints.insert(index);
00534 m_maskEditState=POINTS_ADDING;
00535 };
00536 }
00537 else
00538 {
00539 HuginBase::UIntSet points;
00540 if(SelectPointsInsideMouseRect(points,true))
00541 {
00542
00543 m_maskEditState=POINTS_MOVING;
00544 }
00545 else
00546 {
00547
00548 if(SelectPointsInsideMouseRect(points,false))
00549 {
00550
00551 if(!mouse.ShiftDown())
00552 m_selectedPoints.clear();
00553 for(HuginBase::UIntSet::const_iterator it=points.begin();it!=points.end();it++)
00554 m_selectedPoints.insert(*it);
00555 m_maskEditState=POINTS_MOVING;
00556 }
00557 else
00558 {
00559 m_maskEditState=REGION_SELECTING;
00560 DrawSelectionRectangle();
00561 };
00562 }
00563 };
00564 break;
00565 case CROP_SHOWING:
00566 switch(GetClickPos(vigra::Point2D(currentPos.x,currentPos.y)))
00567 {
00568 case CLICK_INSIDE:
00569 if(!m_cropCentered)
00570 {
00571 m_maskEditState=CROP_MOVING;
00572 };
00573 break;
00574 case CLICK_LEFT:
00575 m_maskEditState=CROP_LEFT_MOVING;
00576 break;
00577 case CLICK_RIGHT:
00578 m_maskEditState=CROP_RIGHT_MOVING;
00579 break;
00580 case CLICK_TOP:
00581 m_maskEditState=CROP_TOP_MOVING;
00582 break;
00583 case CLICK_BOTTOM:
00584 m_maskEditState=CROP_BOTTOM_MOVING;
00585 break;
00586 case CLICK_CIRCLE:
00587 m_dragStartPos.x=(m_cropRect.left()+m_cropRect.right())/2;
00588 m_dragStartPos.y=(m_cropRect.top()+m_cropRect.bottom())/2;
00589 m_maskEditState=CROP_CIRCLE_SCALING;
00590 break;
00591 };
00592 if(m_maskEditState!=CROP_SHOWING)
00593 {
00594 if(m_cropMode==SrcPanoImage::NO_CROP && m_cropCircle)
00595 {
00596 #if defined SUPPORTS_WXINVERT
00597 DrawCrop();
00598 m_cropMode=SrcPanoImage::CROP_CIRCLE;
00599 DrawCrop();
00600 #else
00601 m_cropMode=SrcPanoImage::CROP_CIRCLE;
00602 update();
00603 #endif
00604 };
00605 };
00606 break;
00607 };
00608 };
00609
00610 void MaskImageCtrl::OnLeftMouseUp(wxMouseEvent& mouse)
00611 {
00612 if(m_previewOnly)
00613 return;
00614 DEBUG_DEBUG("LEFT MOUSE UP");
00615 wxPoint mpos;
00616 CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
00617 &mpos.x, & mpos.y);
00618 FDiff2D currentPos=applyRotInv(invtransform(mpos));
00619 bool doUpdate=false;
00620 switch(m_maskEditState)
00621 {
00622 case NEW_POLYGON_STARTED:
00623 doUpdate=true;
00624 m_editingMask.addPoint(currentPos);
00625 m_selectedPoints.insert(m_editingMask.getMaskPolygon().size()-1);
00626 m_maskEditState=NEW_POLYGON_CREATING;
00627 break;
00628 case NEW_POLYGON_CREATING:
00629
00630 doUpdate=true;
00631 m_editingMask.addPoint(currentPos);
00632 m_selectedPoints.insert(m_editingMask.getMaskPolygon().size()-1);
00633 break;
00634 case POINTS_MOVING:
00635 if(HasCapture())
00636 ReleaseMouse();
00637 {
00638 FDiff2D delta=currentPos-applyRotInv(invtransform(m_dragStartPos));
00639 if(sqr(delta.x)+sqr(delta.y)>sqr(maxSelectionDistance))
00640 {
00641 for(HuginBase::UIntSet::const_iterator it=m_selectedPoints.begin();it!=m_selectedPoints.end();it++)
00642 m_imageMask[m_activeMask].movePointBy(*it,delta);
00643 m_maskEditState=POINTS_SELECTED;
00644 m_editPanel->UpdateMask();
00645 }
00646 else
00647 {
00648 m_editingMask=m_imageMask[m_activeMask];
00649 m_maskEditState=POINTS_SELECTED;
00650 doUpdate=true;
00651 };
00652 };
00653 break;
00654 case POLYGON_SELECTING:
00655 if(HasCapture())
00656 ReleaseMouse();
00657 #if defined SUPPORTS_WXINVERT
00658 DrawSelectionRectangle();
00659 #else
00660 doUpdate=true;
00661 #endif
00662 m_currentPos=mpos;
00663 m_maskEditState=NO_SELECTION;
00664 {
00665 hugin_utils::FDiff2D p;
00666 p.x=invtransform(m_dragStartPos.x+(m_currentPos.x-m_dragStartPos.x)/2);
00667 p.y=invtransform(m_dragStartPos.y+(m_currentPos.y-m_dragStartPos.y)/2);
00668 p=applyRotInv(p);
00669 FindPolygon(p);
00670 };
00671 break;
00672 case REGION_SELECTING:
00673 {
00674 if(HasCapture())
00675 ReleaseMouse();
00676 DrawSelectionRectangle();
00677 m_currentPos=mpos;
00678 bool selectedPoints=!m_selectedPoints.empty();
00679 if(!mouse.ShiftDown())
00680 m_selectedPoints.clear();
00681 if(SelectPointsInsideMouseRect(m_selectedPoints,false))
00682 {
00683
00684 if(m_selectedPoints.empty())
00685 m_maskEditState=NO_SELECTION;
00686 else
00687 m_maskEditState=POINTS_SELECTED;
00688 }
00689 else
00690 {
00691
00692 if(!selectedPoints)
00693 {
00694
00695 hugin_utils::FDiff2D p;
00696 p.x=invtransform(m_dragStartPos.x+(m_currentPos.x-m_dragStartPos.x)/2);
00697 p.y=invtransform(m_dragStartPos.y+(m_currentPos.y-m_dragStartPos.y)/2);
00698 p=applyRotInv(p);
00699 FindPolygon(p);
00700 };
00701 m_maskEditState=NO_SELECTION;
00702 };
00703 doUpdate=true;
00704 break;
00705 };
00706 case POINTS_ADDING:
00707 if(HasCapture())
00708 ReleaseMouse();
00709 for(HuginBase::UIntSet::const_iterator it=m_selectedPoints.begin();it!=m_selectedPoints.end();it++)
00710 m_editingMask.movePointTo(*it,currentPos);
00711 m_imageMask[m_activeMask]=m_editingMask;
00712 m_editPanel->UpdateMask();
00713 m_maskEditState=POINTS_SELECTED;
00714 break;
00715 case CROP_MOVING:
00716 case CROP_LEFT_MOVING:
00717 case CROP_RIGHT_MOVING:
00718 case CROP_TOP_MOVING:
00719 case CROP_BOTTOM_MOVING:
00720 case CROP_CIRCLE_SCALING:
00721 if(HasCapture())
00722 ReleaseMouse();
00723 #if defined SUPPORTS_WXINVERT
00724 DrawCrop();
00725 #else
00726 doUpdate=true;
00727 #endif
00728 UpdateCrop(currentPos);
00729 #if defined SUPPORTS_WXINVERT
00730 DrawCrop();
00731 #endif
00732 m_maskEditState=CROP_SHOWING;
00733 SetCursor(wxNullCursor);
00734 m_editPanel->UpdateCrop(true);
00735 break;
00736 default:
00737 if(HasCapture())
00738 ReleaseMouse();
00739 };
00740 if(doUpdate)
00741 update();
00742 }
00743
00744 void MaskImageCtrl::OnLeftMouseDblClick(wxMouseEvent &mouse)
00745 {
00746 if(m_previewOnly)
00747 return;
00748 wxPoint mpos;
00749 CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
00750 &mpos.x, & mpos.y);
00751 FDiff2D currentPos=applyRotInv(invtransform(mpos));
00752 switch(m_maskEditState)
00753 {
00754 case NEW_POLYGON_STARTED:
00755 {
00756 m_maskEditState=NO_SELECTION;
00757 HuginBase::MaskPolygon mask;
00758 m_editingMask=mask;
00759 m_selectedPoints.clear();
00760 MainFrame::Get()->SetStatusText(wxT(""),0);
00761 break;
00762 };
00763 case NEW_POLYGON_CREATING:
00764 {
00765
00766 m_maskEditState=NO_SELECTION;
00767
00768
00769 m_editingMask.removePoint(m_editingMask.getMaskPolygon().size()-1);
00770 if(m_editingMask.getMaskPolygon().size()>2)
00771 {
00772 m_imageMask.push_back(m_editingMask);
00773 m_activeMask=m_imageMask.size()-1;
00774 m_editPanel->AddMask();
00775 }
00776 else
00777 {
00778 HuginBase::MaskPolygon mask;
00779 m_editingMask=mask;
00780 m_selectedPoints.clear();
00781 update();
00782 };
00783 MainFrame::Get()->SetStatusText(wxT(""),0);
00784 break;
00785 };
00786 };
00787 };
00788
00789 void MaskImageCtrl::OnRightMouseDown(wxMouseEvent& mouse)
00790 {
00791 if(m_previewOnly)
00792 return;
00793 wxPoint mpos;
00794 CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
00795 &m_dragStartPos.x, & m_dragStartPos.y);
00796 FDiff2D currentPos=applyRotInv(invtransform(m_dragStartPos));
00797 m_currentPos=m_dragStartPos;
00798 if(!HasCapture())
00799 CaptureMouse();
00800 SetFocus();
00801 switch(m_maskEditState)
00802 {
00803 case NO_SELECTION:
00804 case POINTS_SELECTED:
00805 if(mouse.CmdDown())
00806 {
00807 m_maskEditState=POINTS_DELETING;
00808 DrawSelectionRectangle();
00809 }
00810 else
00811 {
00812 if (m_editingMask.isInside(currentPos))
00813 {
00814 fill_set(m_selectedPoints,0,m_editingMask.getMaskPolygon().size()-1);
00815 m_maskEditState=POINTS_MOVING;
00816 update();
00817 };
00818 };
00819 break;
00820 };
00821 };
00822
00823 void MaskImageCtrl::OnRightMouseUp(wxMouseEvent& mouse)
00824 {
00825 if(m_previewOnly)
00826 return;
00827 wxPoint mpos;
00828 CalcUnscrolledPosition(mouse.GetPosition().x, mouse.GetPosition().y,
00829 &mpos.x, & mpos.y);
00830 FDiff2D currentPos=applyRotInv(invtransform(mpos));
00831 if(HasCapture())
00832 ReleaseMouse();
00833 switch(m_maskEditState)
00834 {
00835 case NEW_POLYGON_STARTED:
00836 {
00837 m_maskEditState=NO_SELECTION;
00838 HuginBase::MaskPolygon mask;
00839 m_editingMask=mask;
00840 m_selectedPoints.clear();
00841 MainFrame::Get()->SetStatusText(wxT(""),0);
00842 break;
00843 };
00844 case NEW_POLYGON_CREATING:
00845 {
00846
00847 m_maskEditState=NO_SELECTION;
00848 m_editingMask.movePointTo(m_editingMask.getMaskPolygon().size()-1,currentPos);
00849 if(m_editingMask.getMaskPolygon().size()>2)
00850 {
00851 m_imageMask.push_back(m_editingMask);
00852 m_activeMask=m_imageMask.size()-1;
00853 m_editPanel->AddMask();
00854 }
00855 else
00856 {
00857 HuginBase::MaskPolygon mask;
00858 m_editingMask=mask;
00859 m_selectedPoints.clear();
00860 update();
00861 };
00862 MainFrame::Get()->SetStatusText(wxT(""),0);
00863 break;
00864 };
00865 case POINTS_DELETING:
00866 {
00867 DrawSelectionRectangle();
00868 HuginBase::UIntSet points;
00869 m_currentPos=mpos;
00870 if(SelectPointsInsideMouseRect(points,false))
00871 {
00872 if(m_editingMask.getMaskPolygon().size()-points.size()>2)
00873 {
00874
00875 for(HuginBase::UIntSet::const_reverse_iterator it=points.rbegin();it!=points.rend();it++)
00876 m_editingMask.removePoint(*it);
00877
00878 if(m_selectedPoints.size()>0)
00879 {
00880 std::vector<unsigned int> mappedSelectedPoints(m_imageMask[m_activeMask].getMaskPolygon().size());
00881 for(unsigned int i=0;i<mappedSelectedPoints.size();i++)
00882 mappedSelectedPoints[i]=i;
00883 HuginBase::UIntSet temp=m_selectedPoints;
00884 m_selectedPoints.clear();
00885 for(HuginBase::UIntSet::const_iterator it=points.begin();it!=points.end();it++)
00886 {
00887 if((*it)<mappedSelectedPoints.size()-1)
00888 for(unsigned int i=(*it)+1;i<mappedSelectedPoints.size();i++)
00889 mappedSelectedPoints[i]--;
00890 };
00891 for(HuginBase::UIntSet::const_iterator it=temp.begin();it!=temp.end();it++)
00892 if(!set_contains(points,*it))
00893 m_selectedPoints.insert(mappedSelectedPoints[*it]);
00894 };
00895
00896 m_imageMask[m_activeMask]=m_editingMask;
00897 m_editPanel->UpdateMask();
00898 }
00899 else
00900 wxBell();
00901 };
00902 if(m_selectedPoints.size()==0)
00903 m_maskEditState=NO_SELECTION;
00904 else
00905 m_maskEditState=POINTS_SELECTED;
00906 break;
00907 };
00908 case POINTS_MOVING:
00909 {
00910 FDiff2D delta=currentPos-applyRotInv(invtransform(m_dragStartPos));
00911 if(sqr(delta.x)+sqr(delta.y)>sqr(maxSelectionDistance))
00912 {
00913 for(HuginBase::UIntSet::const_iterator it=m_selectedPoints.begin();it!=m_selectedPoints.end();it++)
00914 m_imageMask[m_activeMask].movePointBy(*it,delta);
00915 m_maskEditState=POINTS_SELECTED;
00916 m_editPanel->UpdateMask();
00917 }
00918 else
00919 {
00920 m_editingMask=m_imageMask[m_activeMask];
00921 m_maskEditState=POINTS_SELECTED;
00922 };
00923 break;
00924 };
00925 };
00926 };
00927
00928 void MaskImageCtrl::OnKeyUp(wxKeyEvent &e)
00929 {
00930 int key=e.GetKeyCode();
00931 bool processed=false;
00932 if((key==WXK_DELETE) || (key==WXK_NUMPAD_DELETE))
00933 {
00934 if(m_activeMask<UINT_MAX)
00935 {
00936 switch(m_maskEditState)
00937 {
00938 case POINTS_SELECTED:
00939 if((m_selectedPoints.size()>0) && (m_editingMask.getMaskPolygon().size()-m_selectedPoints.size()>2))
00940 {
00941 for(HuginBase::UIntSet::const_reverse_iterator it=m_selectedPoints.rbegin();it!=m_selectedPoints.rend();it++)
00942 m_editingMask.removePoint(*it);
00943 m_imageMask[m_activeMask]=m_editingMask;
00944 processed=true;
00945 m_editPanel->UpdateMask();
00946 }
00947 else
00948 {
00949 if(m_editingMask.getMaskPolygon().size()==m_selectedPoints.size())
00950 {
00951 wxCommandEvent dummy;
00952 processed=true;
00953 m_editPanel->OnMaskDelete(dummy);
00954 }
00955 else
00956 wxBell();
00957 };
00958 break;
00959 case NO_SELECTION:
00960 {
00961 wxCommandEvent dummy;
00962 processed=true;
00963 m_editPanel->OnMaskDelete(dummy);
00964 };
00965 break;
00966 };
00967 };
00968 };
00969 if(!processed)
00970 e.Skip();
00971 };
00972
00973 void MaskImageCtrl::OnCaptureLost(wxMouseCaptureLostEvent &e)
00974 {
00975 wxFocusEvent dummy;
00976 OnKillFocus(dummy);
00977 };
00978
00979 void MaskImageCtrl::OnKillFocus(wxFocusEvent &e)
00980 {
00981 if(HasCapture())
00982 ReleaseMouse();
00983 switch(m_maskEditState)
00984 {
00985 case NEW_POLYGON_CREATING:
00986 case NEW_POLYGON_STARTED:
00987 {
00988 wxBell();
00989 m_maskEditState=NO_SELECTION;
00990 HuginBase::MaskPolygon mask;
00991 m_editingMask=mask;
00992 m_selectedPoints.clear();
00993 update();
00994 break;
00995 };
00996 };
00997 };
00998
00999 void MaskImageCtrl::startNewPolygon()
01000 {
01001 m_maskEditState=NEW_POLYGON_STARTED;
01002 HuginBase::MaskPolygon newMask;
01003 m_editingMask=newMask;
01004 m_selectedPoints.clear();
01005 };
01006
01007 wxSize MaskImageCtrl::DoGetBestSize() const
01008 {
01009 return wxSize(m_imageSize.GetWidth(),m_imageSize.GetHeight());
01010 };
01011
01012 void MaskImageCtrl::update()
01013 {
01014 wxClientDC dc(this);
01015 PrepareDC(dc);
01016 OnDraw(dc);
01017 };
01018
01019 void MaskImageCtrl::DrawPolygon(wxDC &dc, HuginBase::MaskPolygon poly, bool isSelected, bool drawMarker)
01020 {
01021 unsigned int nrOfPoints=poly.getMaskPolygon().size();
01022 if (nrOfPoints<2)
01023 return;
01024 wxPoint *polygonPoints=new wxPoint[nrOfPoints];
01025 for(unsigned int j=0;j<nrOfPoints;j++)
01026 {
01027 polygonPoints[j]=transform(applyRot(poly.getMaskPolygon()[j]));
01028 };
01029 if(isSelected)
01030 dc.SetPen(wxPen(m_colour_point_unselected,1,wxSOLID));
01031 else
01032 switch(poly.getMaskType())
01033 {
01034 case HuginBase::MaskPolygon::Mask_negative:
01035 dc.SetPen(wxPen(m_colour_polygon_negative,1,wxSOLID));
01036 break;
01037 case HuginBase::MaskPolygon::Mask_positive:
01038 dc.SetPen(wxPen(m_colour_polygon_positive,1,wxSOLID));
01039 break;
01040 };
01041 dc.SetBrush(*wxTRANSPARENT_BRUSH);
01042 if(nrOfPoints>2)
01043 dc.DrawPolygon(nrOfPoints,polygonPoints);
01044 else
01045 dc.DrawLine(polygonPoints[0],polygonPoints[1]);
01046 if(drawMarker)
01047 {
01048 wxPen penSelected(m_colour_point_selected);
01049 wxPen penUnselected(m_colour_point_unselected);
01050 wxBrush brushSelected(m_colour_point_selected);
01051 wxBrush brushUnselected(m_colour_point_unselected);
01052 for(unsigned int j=0;j<nrOfPoints;j++)
01053 {
01054 if(set_contains(m_selectedPoints,j))
01055 {
01056 dc.SetPen(penSelected);
01057 dc.SetBrush(brushSelected);
01058 }
01059 else
01060 {
01061 dc.SetPen(penUnselected);
01062 dc.SetBrush(brushUnselected);
01063 };
01064 dc.DrawRectangle(polygonPoints[j].x-polygonPointSize,polygonPoints[j].y-polygonPointSize,
01065 2*polygonPointSize,2*polygonPointSize);
01066 };
01067 };
01068 delete []polygonPoints;
01069 };
01070
01071 void MaskImageCtrl::DrawCrop()
01072 {
01073 wxClientDC dc(this);
01074 PrepareDC(dc);
01075 DrawCrop(dc);
01076 };
01077
01078 void MaskImageCtrl::DrawCrop(wxDC & dc)
01079 {
01080
01081 if(!m_maskMode)
01082 {
01083
01084 dc.SetBrush(*wxTRANSPARENT_BRUSH);
01085 #if defined SUPPORTS_WXINVERT
01086 dc.SetLogicalFunction (wxINVERT);
01087 #else
01088 dc.SetPen(wxPen(m_color_selection, 1, wxPENSTYLE_SOLID));
01089 #endif
01090 wxPoint middle=transform(applyRot((m_cropRect.lowerRight()+m_cropRect.upperLeft())/2));
01091
01092 int c = 8;
01093 dc.DrawLine( middle.x + c, middle.y + c, middle.x - c, middle.y - c);
01094 dc.DrawLine( middle.x - c, middle.y + c, middle.x + c, middle.y - c);
01095 dc.DrawRectangle(wxRect(transform(applyRot(hugin_utils::FDiff2D(m_cropRect.left(), m_cropRect.top()))),
01096 transform(applyRot(hugin_utils::FDiff2D(m_cropRect.right(), m_cropRect.bottom())))));
01097
01098
01099 if (m_cropMode==HuginBase::BaseSrcPanoImage::CROP_CIRCLE)
01100 {
01101 double radius=std::min<int>(m_cropRect.width(),m_cropRect.height())/2.0;
01102 dc.DrawCircle(middle.x, middle.y, scale(radius));
01103 }
01104 };
01105 };
01106
01107 void MaskImageCtrl::OnDraw(wxDC & dc)
01108 {
01109 if(m_maskEditState!=NO_IMAGE)
01110 {
01111 int offset=scale(HuginBase::maskOffset);
01112
01113
01114 dc.SetPen(wxPen(GetBackgroundColour(), 1, wxSOLID));
01115 dc.SetBrush(wxBrush(GetBackgroundColour(),wxSOLID));
01116 dc.DrawRectangle(0,0,offset,m_bitmap.GetHeight()+2*offset);
01117 dc.DrawRectangle(0,0,m_bitmap.GetWidth()+2*offset,offset);
01118 dc.DrawRectangle(m_bitmap.GetWidth()+offset,0,m_bitmap.GetWidth()+2*offset,m_bitmap.GetHeight()+2*offset);
01119 dc.DrawRectangle(0,m_bitmap.GetHeight()+offset,m_bitmap.GetWidth()+2*offset,m_bitmap.GetHeight()+2*offset);
01120 dc.DrawBitmap(m_bitmap,offset,offset);
01121 if(m_fitToWindow)
01122 {
01123
01124 wxSize clientSize=GetClientSize();
01125 if(m_bitmap.GetWidth()+2*offset<clientSize.GetWidth())
01126 {
01127 dc.DrawRectangle(m_bitmap.GetWidth()+2*offset,0,clientSize.GetWidth()-m_bitmap.GetWidth()+2*offset,clientSize.GetHeight());
01128 };
01129 if(m_bitmap.GetHeight()+2*offset<clientSize.GetHeight())
01130 {
01131 dc.DrawRectangle(0,m_bitmap.GetHeight()+2*offset,clientSize.GetWidth(),clientSize.GetHeight()-m_bitmap.GetHeight()+2*offset);
01132 };
01133 };
01134 if(m_maskMode && m_showActiveMasks && (m_cropMode!=SrcPanoImage::NO_CROP || m_masksToDraw.size()>0))
01135 {
01136
01137 wxRegion wholeImage(transform(applyRot(hugin_utils::FDiff2D(0,0))),
01138 transform(applyRot(hugin_utils::FDiff2D(m_realSize.GetWidth(),m_realSize.GetHeight()))));
01139 wxRegion region;
01140 if(m_cropMode!=SrcPanoImage::NO_CROP)
01141 {
01142 region.Union(wholeImage);
01143
01144 switch(m_cropMode)
01145 {
01146 case HuginBase::SrcPanoImage::CROP_RECTANGLE:
01147 region.Subtract(wxRegion(transform(applyRot(m_cropRect.upperLeft())),
01148 transform(applyRot(m_cropRect.lowerRight()))));
01149 break;
01150 case HuginBase::SrcPanoImage::CROP_CIRCLE:
01151 unsigned int nrOfPoints=dc.GetSize().GetWidth()*2;
01152 wxPoint* circlePoints=new wxPoint[nrOfPoints];
01153 vigra::Point2D middle=(m_cropRect.lowerRight()+m_cropRect.upperLeft())/2;
01154 double radius=std::min<int>(m_cropRect.width(),m_cropRect.height())/2;
01155 double interval=2*PI/nrOfPoints;
01156 for(unsigned int i=0;i<nrOfPoints;i++)
01157 {
01158 circlePoints[i]=transform(applyRot(hugin_utils::FDiff2D(middle.x+radius*cos(i*interval),middle.y+radius*sin(i*interval))));
01159 };
01160 region.Subtract(wxRegion(nrOfPoints,circlePoints));
01161 delete []circlePoints;
01162 break;
01163 };
01164 };
01165 if(m_masksToDraw.size()>0)
01166 {
01167 for(unsigned int i=0;i<m_masksToDraw.size();i++)
01168 {
01169 HuginBase::VectorPolygon poly=m_masksToDraw[i].getMaskPolygon();
01170 wxPoint *polygonPoints=new wxPoint[poly.size()];
01171 for(unsigned int j=0;j<poly.size();j++)
01172 {
01173 polygonPoints[j]=transform(applyRot(poly[j]));
01174 };
01175 wxRegion singleRegion(poly.size(),polygonPoints,wxWINDING_RULE);
01176 if(m_masksToDraw[i].isInverted())
01177 {
01178 wxRegion newRegion(wholeImage);
01179 newRegion.Subtract(singleRegion);
01180 region.Union(newRegion);
01181 }
01182 else
01183 {
01184 region.Union(singleRegion);
01185 };
01186 delete []polygonPoints;
01187 };
01188 };
01189 #ifndef __WXMAC__
01190
01191
01192
01193 int x;
01194 int y;
01195 GetViewStart(&x,&y);
01196 region.Offset(-x,-y);
01197 #endif
01198 dc.SetDeviceClippingRegion(region);
01199 dc.DrawBitmap(m_disabledBitmap,offset,offset);
01200 dc.DestroyClippingRegion();
01201 };
01202 DrawCrop(dc);
01203 if(m_maskMode && m_imageMask.size()>0)
01204 {
01205
01206 HuginBase::MaskPolygonVector maskList=m_imageMask;
01207 bool drawSelected=(m_maskEditState!=POINTS_ADDING && m_maskEditState!=POINTS_MOVING);
01208 for(unsigned int i=0;i<maskList.size();i++)
01209 {
01210 if(i!=m_activeMask)
01211 DrawPolygon(dc,maskList[i],false,false);
01212 else
01213 if(drawSelected)
01214 DrawPolygon(dc,maskList[i],true,true);
01215 };
01216 };
01217
01218 if(m_maskEditState==POINTS_ADDING || m_maskEditState==POINTS_MOVING || m_maskEditState==NEW_POLYGON_CREATING)
01219 DrawPolygon(dc,m_editingMask,true,true);
01220 }
01221 else
01222 {
01223
01224 dc.SetPen(wxPen(GetBackgroundColour(), 1, wxSOLID));
01225 dc.SetBrush(wxBrush(GetBackgroundColour(),wxSOLID));
01226 dc.Clear();
01227 return;
01228 };
01229 }
01230
01231 void MaskImageCtrl::OnSize(wxSizeEvent &e)
01232 {
01233 DEBUG_TRACE("size: " << e.GetSize().GetWidth() << "x" << e.GetSize().GetHeight());
01234
01235 if (m_imageFilename != "") {
01236 if (m_fitToWindow) {
01237 setScale(0);
01238 }
01239 }
01240 };
01241
01242 void MaskImageCtrl::rescaleImage()
01243 {
01244 if (m_maskEditState == NO_IMAGE)
01245 {
01246 return;
01247 }
01248 #ifndef SUPPORTS_WXINVERT
01249
01250 vigra::FindAverage<vigra::RGBValue<vigra::UInt8> > average;
01251 vigra::inspectImage(vigra::srcImageRange(*(m_img->get8BitImage())), average);
01252 vigra::RGBValue<vigra::UInt8> RGBaverage=average.average();
01253 if(RGBaverage[0]<180 && RGBaverage[1]<180 && RGBaverage[2]<180)
01254 {
01255 m_color_selection=*wxWHITE;
01256 }
01257 else
01258 {
01259 m_color_selection=*wxBLACK;
01260 };
01261 #endif
01262 wxImage img = imageCacheEntry2wxImage(m_img);
01263 if (img.GetWidth() == 0)
01264 {
01265 return;
01266 }
01267 m_imageSize = wxSize(img.GetWidth(), img.GetHeight());
01268 m_realSize = m_imageSize;
01269 m_imageSize.IncBy(2*HuginBase::maskOffset);
01270 if (m_fitToWindow)
01271 m_scaleFactor = calcAutoScaleFactor(m_imageSize);
01272
01273
01274 if (getScaleFactor()!=1.0)
01275 {
01276 m_imageSize.SetWidth(scale(m_imageSize.GetWidth()));
01277 m_imageSize.SetHeight(scale(m_imageSize.GetHeight()));
01278 img=img.Scale(scale(m_realSize.GetWidth()), scale(m_realSize.GetHeight()));
01279 }
01280 else
01281 {
01282
01283
01284 img=img.Copy();
01285 };
01286
01287 switch(m_imgRotation)
01288 {
01289 case ROT90:
01290 img = img.Rotate90(true);
01291 break;
01292 case ROT180:
01293
01294 img = img.Rotate90(true);
01295 img = img.Rotate90(true);
01296 break;
01297 case ROT270:
01298 img = img.Rotate90(false);
01299 break;
01300 default:
01301 break;
01302 }
01303 m_bitmap=wxBitmap(img);
01304
01305
01306 #if wxCHECK_VERSION(2,9,0)
01307 img.ConvertToDisabled(192);
01308 #else
01309 {
01310 int width = img.GetWidth();
01311 int height = img.GetHeight();
01312 for (int y = height-1; y >= 0; --y)
01313 {
01314 for (int x = width-1; x >= 0; --x)
01315 {
01316 unsigned char* data = img.GetData() + (y*(width*3))+(x*3);
01317 unsigned char* r = data;
01318 unsigned char* g = data+1;
01319 unsigned char* b = data+2;
01320 *r=(unsigned char)wxMin(0.6*(*r)+77,255);
01321 *b=(unsigned char)wxMin(0.6*(*b)+77,255);
01322 *g=(unsigned char)wxMin(0.6*(*g)+77,255);
01323 }
01324 }
01325 }
01326 #endif
01327 m_disabledBitmap=wxBitmap(img);
01328 if (m_imgRotation == ROT90 || m_imgRotation == ROT270)
01329 {
01330 SetVirtualSize(m_imageSize.GetHeight(), m_imageSize.GetWidth());
01331 }
01332 else
01333 {
01334 SetVirtualSize(m_imageSize.GetWidth(), m_imageSize.GetHeight());
01335 };
01336 SetScrollRate(1,1);
01337 Refresh(true);
01338 };
01339
01340 void MaskImageCtrl::DrawSelectionRectangle()
01341 {
01342 wxClientDC dc(this);
01343 PrepareDC(dc);
01344 #if defined SUPPORTS_WXINVERT
01345 dc.SetLogicalFunction(wxINVERT);
01346 dc.SetPen(wxPen(*wxWHITE,1,wxDOT));
01347 #else
01348 OnDraw(dc);
01349 dc.SetPen(wxPen(m_color_selection, scale(1), wxDOT));
01350 #endif
01351 dc.SetBrush(*wxTRANSPARENT_BRUSH);
01352 dc.DrawRectangle(m_dragStartPos.x,m_dragStartPos.y,
01353 (m_currentPos.x-m_dragStartPos.x),(m_currentPos.y-m_dragStartPos.y));
01354 };
01355
01356 void MaskImageCtrl::FindPolygon(hugin_utils::FDiff2D p)
01357 {
01358 unsigned int selectedPolygon=UINT_MAX;
01359 unsigned int i=0;
01360 while(selectedPolygon==UINT_MAX && i<m_imageMask.size())
01361 {
01362 if(m_imageMask[i].isInside(p))
01363 selectedPolygon=i;
01364 i++;
01365 };
01366 if(selectedPolygon<UINT_MAX)
01367 m_editPanel->SelectMask(selectedPolygon);
01368 };
01369
01370 bool MaskImageCtrl::SelectPointsInsideMouseRect(HuginBase::UIntSet &points,const bool considerSelectedOnly)
01371 {
01372 bool found=false;
01373 hugin_utils::FDiff2D p1=applyRotInv(invtransform(m_dragStartPos));
01374 hugin_utils::FDiff2D p2=applyRotInv(invtransform(m_currentPos));
01375 double xmin=std::min(p1.x,p2.x)-maxSelectionDistance;
01376 double xmax=std::max(p1.x,p2.x)+maxSelectionDistance;
01377 double ymin=std::min(p1.y,p2.y)-maxSelectionDistance;
01378 double ymax=std::max(p1.y,p2.y)+maxSelectionDistance;
01379 const HuginBase::VectorPolygon poly=m_editingMask.getMaskPolygon();
01380 for(unsigned int i=0;i<poly.size();i++)
01381 {
01382 bool activePoints=true;
01383 if(considerSelectedOnly)
01384 activePoints=set_contains(m_selectedPoints,i);
01385 if(activePoints && xmin<=poly[i].x && poly[i].x<=xmax && ymin<=poly[i].y && poly[i].y<=ymax)
01386 {
01387 points.insert(i);
01388 found=true;
01389 };
01390 };
01391 return found;
01392 };
01393
01394 void MaskImageCtrl::setScale(double factor)
01395 {
01396 if (factor == 0)
01397 {
01398 m_fitToWindow = true;
01399 factor = calcAutoScaleFactor(m_imageSize);
01400 }
01401 else
01402 {
01403 m_fitToWindow = false;
01404 }
01405 DEBUG_DEBUG("new scale factor:" << factor);
01406
01407 if (factor != m_scaleFactor)
01408 {
01409 m_scaleFactor = factor;
01410
01411 rescaleImage();
01412 }
01413 };
01414
01415 double MaskImageCtrl::calcAutoScaleFactor(wxSize size)
01416 {
01417 int w = size.GetWidth();
01418 int h = size.GetHeight();
01419 if (m_imgRotation == ROT90 || m_imgRotation == ROT270)
01420 {
01421 int t = w;
01422 w = h;
01423 h = t;
01424 }
01425
01426 wxSize csize = GetSize();
01427 DEBUG_DEBUG("csize: " << csize.GetWidth() << "x" << csize.GetHeight() << "image: " << w << "x" << h);
01428 double s1 = (double)csize.GetWidth()/w;
01429 double s2 = (double)csize.GetHeight()/h;
01430 DEBUG_DEBUG("s1: " << s1 << " s2:" << s2);
01431 return s1 < s2 ? s1 : s2;
01432 };
01433
01434 double MaskImageCtrl::getScaleFactor() const
01435 {
01436 return m_scaleFactor;
01437 };
01438
01439 void MaskImageCtrl::setDrawingActiveMasks(bool newDrawActiveMasks)
01440 {
01441 m_showActiveMasks=newDrawActiveMasks;
01442 update();
01443 };
01444
01445 IMPLEMENT_DYNAMIC_CLASS(MaskImageCtrl, wxScrolledWindow)
01446
01447 MaskImageCtrlXmlHandler::MaskImageCtrlXmlHandler()
01448 : wxXmlResourceHandler()
01449 {
01450 AddWindowStyles();
01451 };
01452
01453 wxObject *MaskImageCtrlXmlHandler::DoCreateResource()
01454 {
01455 XRC_MAKE_INSTANCE(cp, MaskImageCtrl)
01456
01457 cp->Create(m_parentAsWindow,
01458 GetID(),
01459 GetPosition(), GetSize(),
01460 GetStyle(wxT("style")),
01461 GetName());
01462
01463 SetupWindow(cp);
01464
01465 return cp;
01466 };
01467
01468 bool MaskImageCtrlXmlHandler::CanHandle(wxXmlNode *node)
01469 {
01470 return IsOfClass(node, wxT("MaskImageCtrl"));
01471 };
01472
01473 IMPLEMENT_DYNAMIC_CLASS(MaskImageCtrlXmlHandler, wxXmlResourceHandler)