MaskImageCtrl.cpp

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

Generated on 26 Jun 2016 for Hugintrunk by  doxygen 1.4.7