PreviewPanel.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00027 #include <config.h>
00028 
00029 #include "panoinc_WX.h"
00030 #include "panoinc.h"
00031 
00032 #include <vigra/basicimageview.hxx>
00033 #include "nona/Stitcher.h"
00034 
00035 #include "base_wx/wxImageCache.h"
00036 #include "hugin/PreviewPanel.h"
00037 #include "hugin/PreviewFrame.h"
00038 #include "hugin/MainFrame.h"
00039 #include "base_wx/CommandHistory.h"
00040 #include "base_wx/PanoCommand.h"
00041 #include "base_wx/wxcms.h"
00042 #include "hugin/config_defaults.h"
00043 #include "hugin/huginApp.h"
00044 
00045 #include <math.h>
00046 
00047 typedef vigra::RGBValue<unsigned char> BRGBValue;
00048 
00049 BEGIN_EVENT_TABLE(PreviewPanel, wxPanel)
00050     EVT_SIZE(PreviewPanel::OnResize)
00051     EVT_LEFT_DOWN(PreviewPanel::mousePressLMBEvent)
00052     EVT_RIGHT_DOWN(PreviewPanel::mousePressRMBEvent)
00053     EVT_MOUSE_EVENTS ( PreviewPanel::OnMouse )
00054     EVT_PAINT ( PreviewPanel::OnDraw )
00055 END_EVENT_TABLE()
00056 
00057 PreviewPanel::PreviewPanel()
00058     : pano(0), m_autoPreview(false),m_panoImgSize(1,1),
00059     m_panoBitmap(0), 
00060     m_pano2erect(0), m_blendMode(BLEND_COPY), 
00061     m_state_rendering(false), m_rerender(false), m_imgsDirty(true)
00062 {
00063 }
00064 
00065 bool PreviewPanel::Create(wxWindow* parent, wxWindowID id,
00066                            const wxPoint& pos,
00067                            const wxSize& size,
00068                            long style,
00069                            const wxString& name)
00070 {
00071     DEBUG_TRACE(" Create called *************");
00072     if (! wxPanel::Create(parent, id, pos, size, style, name) ) {
00073         return false;
00074     }
00075     DEBUG_TRACE("");
00076     DEBUG_DEBUG("m_state_rendering = " << m_state_rendering);
00077 
00078 #if defined(__WXMSW__) 
00079     wxString cursorPath = huginApp::Get()->GetXRCPath() + wxT("/data/cursor_cp_pick.cur");
00080     m_cursor = new wxCursor(cursorPath, wxBITMAP_TYPE_CUR);
00081 #else
00082     m_cursor = new wxCursor(wxCURSOR_CROSS);
00083 #endif
00084     SetCursor(*m_cursor);
00085     return true;
00086 }
00087 
00088 
00089 void PreviewPanel::Init(PreviewFrame *parent, HuginBase::Panorama * panorama )
00090 {
00091     pano = panorama;
00092     parentWindow = parent;
00093     pano->addObserver(this);
00094 }
00095 
00096 
00097 PreviewPanel::~PreviewPanel()
00098 {
00099     DEBUG_TRACE("dtor");
00100     delete m_cursor;
00101     pano->removeObserver(this);
00102     if (m_panoBitmap) {
00103         delete m_panoBitmap;
00104     }
00105     if (m_pano2erect) {
00106         delete m_pano2erect;
00107     }
00108     DEBUG_TRACE("dtor end");
00109 }
00110 
00111 void PreviewPanel::panoramaChanged(HuginBase::Panorama &pano)
00112 {
00113     // avoid recursive calls.. don't know if they can happen at all,
00114     // but they might lead to crashes.
00115     bool dirty = false;
00116 
00117     const HuginBase::PanoramaOptions & newOpts = pano.getOptions();
00118 
00119     // check if an important options has been changed
00120     if (newOpts.getHFOV() != opts.getHFOV()) {
00121         DEBUG_DEBUG("HFOV changed");
00122         dirty = true;
00123     }
00124     if (newOpts.getVFOV() != opts.getVFOV()) {
00125         DEBUG_DEBUG("VFOV changed");
00126         dirty = true;
00127     }
00128     if (newOpts.getProjection() != opts.getProjection()) {
00129         DEBUG_DEBUG("projection changed");
00130         dirty = true;
00131     }
00132 
00133     if (newOpts.getProjectionParameters() != opts.getProjectionParameters() ) {
00134         DEBUG_DEBUG("projection parameters changed");
00135         dirty = true;
00136     }
00137     if (newOpts.outputExposureValue != opts.outputExposureValue )
00138     {
00139         DEBUG_DEBUG("output exposure value changed");
00140         dirty = true;
00141     };
00142 
00143     opts = newOpts;
00144     if (dirty) {
00145         // have to remap all images
00146         m_remapCache.invalidate();
00147     }
00148 
00149     if (m_autoPreview && dirty) {
00150         DEBUG_DEBUG("forcing preview update");
00151         ForceUpdate();
00152         // resize
00153     } else if(m_autoPreview && m_imgsDirty ) {
00154         DEBUG_DEBUG("updating preview after image change");
00155         updatePreview();
00156         m_imgsDirty=false;
00157     }
00158 }
00159 
00160 void PreviewPanel::panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
00161 {
00162     DEBUG_TRACE("");
00163     m_imgsDirty = true;
00164 }
00165 
00166 void PreviewPanel::SetBlendMode(BlendMode b)
00167 {
00168     m_blendMode = b;
00169     updatePreview();
00170 }
00171 
00172 void PreviewPanel::ForceUpdate()
00173 {
00174     updatePreview();
00175 }
00176 
00177 void PreviewPanel::SetAutoUpdate(bool enabled)
00178 {
00179     m_autoPreview = enabled;
00180     if (enabled) {
00181         updatePreview();
00182     }
00183 }
00184 
00187 template <class OP>
00188 struct ExposureResponseFunctor2
00189 {
00190     ExposureResponseFunctor2(double exposure, const OP & operation)
00191     : op(operation), e(exposure)
00192     {
00193     }
00194     const OP & op;
00195     double e;
00196 
00197     template <class VT>
00198     typename vigra::NumericTraits<VT>::RealPromote
00199     operator()(VT v) const 
00200     {
00201         return op(v*e);
00202     }
00203 };
00204 
00205 
00206 void PreviewPanel::updatePreview()
00207 {
00208     DEBUG_TRACE("");
00209 
00210     // we can accidentally end up here recursively, because wxWidgets
00211     // allows user input during redraw of the progress in the bottom
00212     if (m_state_rendering) {
00213         DEBUG_DEBUG("m_state_rendering == true, aborting rendering");
00214         m_rerender = true;
00215         return;
00216     }
00217 
00218     DEBUG_DEBUG("m_state_rendering = true");
00219     m_state_rendering = true;
00220     m_rerender = false;
00221 
00222         {
00223           // Even though the frame is hidden, the panel is not
00224           // so check the parent instead
00225           if (parentWindow) {
00226                 if (parentWindow->IsShown() && (! parentWindow->IsIconized())) {
00227                   DEBUG_INFO("Parent window shown - updating");
00228                 } else {
00229                   DEBUG_INFO("Parent window hidden - not updating");
00230                   m_state_rendering = false;
00231                   return;
00232                 }
00233           }
00234         }
00235     wxBusyCursor wait;
00236     double finalWidth = pano->getOptions().getWidth();
00237     double finalHeight = pano->getOptions().getHeight();
00238 
00239     m_panoImgSize = vigra::Diff2D(GetClientSize().GetWidth(), GetClientSize().GetHeight());
00240 
00241     double ratioPano = finalWidth / finalHeight;
00242     double ratioPanel = (double)m_panoImgSize.x / (double)m_panoImgSize.y;
00243 
00244     DEBUG_DEBUG("panorama ratio: " << ratioPano << "  panel ratio: " << ratioPanel);
00245 
00246     if (ratioPano < ratioPanel) {
00247         // panel is wider than pano
00248         m_panoImgSize.x = hugin_utils::round(m_panoImgSize.y * ratioPano);
00249         DEBUG_DEBUG("portrait: " << m_panoImgSize);
00250     } else {
00251         // panel is taller than pano
00252         m_panoImgSize.y = hugin_utils::round(m_panoImgSize.x / ratioPano);
00253         DEBUG_DEBUG("landscape: " << m_panoImgSize);
00254     }
00255 
00256     HuginBase::PanoramaOptions opts = pano->getOptions();
00257     //don't use GPU for preview
00258     opts.remapUsingGPU = false;
00259     opts.setWidth(m_panoImgSize.x, false);
00260     opts.setHeight(m_panoImgSize.y);
00261     // always use bilinear for preview.
00262 
00263     // reset ROI. The preview needs to draw the parts outside the ROI, too!
00264     opts.setROI(vigra::Rect2D(opts.getSize()));
00265     opts.interpolator = vigra_ext::INTERP_BILINEAR;
00266 
00267     // create images
00268     wxImage panoImage(m_panoImgSize.x, m_panoImgSize.y);
00269     try {
00270         vigra::BasicImageView<vigra::RGBValue<unsigned char> > panoImg8((vigra::RGBValue<unsigned char> *)panoImage.GetData(), panoImage.GetWidth(), panoImage.GetHeight());
00271         vigra::FRGBImage panoImg(m_panoImgSize);
00272         vigra::BImage alpha(m_panoImgSize);
00273 
00274         DEBUG_DEBUG("about to stitch images, pano size: " << m_panoImgSize);
00275         HuginBase::UIntSet displayedImages = pano->getActiveImages();
00276         if (displayedImages.size() > 0) {
00277             if (opts.outputMode == HuginBase::PanoramaOptions::OUTPUT_HDR) {
00278                 DEBUG_DEBUG("HDR output merge");
00279 
00280                 vigra_ext::ReduceToHDRFunctor<vigra::RGBValue<float> > hdrmerge;
00281                 HuginBase::Nona::ReduceStitcher<vigra::FRGBImage, vigra::BImage> stitcher(*pano, parentWindow);
00282                 stitcher.stitch(opts, displayedImages,
00283                                 destImageRange(panoImg), destImage(alpha),
00284                                 m_remapCache,
00285                                 hdrmerge);
00286 #ifdef DEBUG_REMAP
00287 {
00288     vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_preview_HDR_Reduce.tif"); \
00289             vigra::exportImage(vigra::srcImageRange(panoImg), exi); \
00290 }
00291 {
00292     vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_preview_HDR_Reduce_Alpha.tif"); \
00293             vigra::exportImage(vigra::srcImageRange(alpha), exi); \
00294 }
00295 #endif
00296 
00297                 // find min and max
00298                 vigra::FindMinMax<float> minmax;   // init functor
00299                 vigra::inspectImageIf(vigra::srcImageRange(panoImg), vigra::srcImage(alpha),
00300                                     minmax);
00301                 double min = std::max(minmax.min, 1e-6f);
00302                 double max = minmax.max;
00303 
00304                 int mapping = wxConfigBase::Get()->Read(wxT("/ImageCache/MappingFloat"), HUGIN_IMGCACHE_MAPPING_FLOAT);
00305                 vigra_ext::applyMapping(vigra::srcImageRange(panoImg), vigra::destImage(panoImg8), min, max, mapping);
00306 
00307             } else {
00308                     // LDR output
00309                 vigra::ImageImportInfo::ICCProfile iccProfile;
00310                 switch (m_blendMode) {
00311                 case BLEND_COPY:
00312                 {
00313                     HuginBase::Nona::StackingBlender blender;
00314                     HuginBase::Nona::SimpleStitcher<vigra::FRGBImage, vigra::BImage> stitcher(*pano, parentWindow);
00315                     stitcher.stitch(opts, displayedImages,
00316                                     destImageRange(panoImg), destImage(alpha),
00317                                     m_remapCache,
00318                                     blender);
00319                     iccProfile = stitcher.iccProfile;
00320                     break;
00321                 }
00322                 case BLEND_DIFFERENCE:
00323                 {
00324                     HuginBase::Nona::ReduceToDifferenceFunctor<vigra::RGBValue<float> > func;
00325                     HuginBase::Nona::ReduceStitcher<vigra::FRGBImage, vigra::BImage> stitcher(*pano, parentWindow);
00326                     stitcher.stitch(opts, displayedImages,
00327                                     destImageRange(panoImg), destImage(alpha),
00328                                     m_remapCache,
00329                                     func);
00330                     iccProfile = stitcher.iccProfile;
00331                     break;
00332                 }
00333                 }
00334                 
00335 #ifdef DEBUG_REMAP
00336 {
00337     vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin04_preview_AfterRemap.tif"); \
00338             vigra::exportImage(vigra::srcImageRange(panoImg), exi); \
00339 }
00340 {
00341     vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX "hugin04_preview_AfterRemapAlpha.tif"); \
00342             vigra::exportImage(vigra::srcImageRange(alpha), exi); \
00343 }
00344 #endif
00345 
00346                 // apply default exposure and convert to 8 bit
00347                 HuginBase::SrcPanoImage src = pano->getSrcImage(0);
00348 
00349                 // apply the exposure
00350                 double scale = 1.0/pow(2.0,opts.outputExposureValue);
00351 
00352                 vigra::transformImage(srcImageRange(panoImg), destImage(panoImg),
00353                                       vigra::functor::Arg1()*vigra::functor::Param(scale));
00354 
00355                 DEBUG_DEBUG("LDR output, with response: " << src.getResponseType());
00356                 if (src.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_LINEAR) {
00357                     vigra::transformImage(srcImageRange(panoImg), destImage(panoImg8),
00358                                           vigra::functor::Arg1()*vigra::functor::Param(255));
00359                 } else {
00360                 // create suitable lut for response
00361                     typedef  std::vector<double> LUT;
00362                     LUT lut;
00363                     switch(src.getResponseType())
00364                     {
00365                         case HuginBase::SrcPanoImage::RESPONSE_EMOR:
00366                             vigra_ext::EMoR::createEMoRLUT(src.getEMoRParams(), lut);
00367                             break;
00368                         case HuginBase::SrcPanoImage::RESPONSE_GAMMA:
00369                             lut.resize(256);
00370                             vigra_ext::createGammaLUT(1/src.getGamma(), lut);
00371                             break;
00372                         default:
00373                             vigra_fail("Unknown or unsupported response function type");
00374                             break;
00375                     }
00376                     // scale lut
00377                     for (size_t i=0; i < lut.size(); i++) 
00378                         lut[i] = lut[i]*255;
00379                     typedef vigra::RGBValue<float> FRGB;
00380                     vigra_ext::LUTFunctor<FRGB, LUT> lutf(lut);
00381 
00382                     vigra::transformImage(srcImageRange(panoImg), destImage(panoImg8),
00383                                           lutf);
00384                 }
00385                 // apply color profiles
00386                 if (!iccProfile.empty() || huginApp::Get()->HasMonitorProfile())
00387                 {
00388                     HuginBase::Color::CorrectImage(panoImage, iccProfile, huginApp::Get()->GetMonitorProfile());
00389                 };
00390             }
00391         }
00392 
00393 #ifdef DEBUG_REMAP
00394 {
00395     vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX "hugin05_preview_final.tif"); \
00396             vigra::exportImage(vigra::srcImageRange(panoImg8), exi); \
00397 }
00398 #endif
00399 
00400 
00401     } catch (std::exception & e) {
00402         m_state_rendering = false;
00403         DEBUG_ERROR("error during stitching: " << e.what());
00404         wxMessageBox(wxString(e.what(), wxConvLocal), _("Error during Stitching"));
00405     }
00406 
00407 
00408     // update the transform for pano -> erect coordinates
00409     if (m_pano2erect) delete m_pano2erect;
00410     HuginBase::SrcPanoImage src;
00411     src.setProjection(HuginBase::SrcPanoImage::EQUIRECTANGULAR);
00412     src.setHFOV(360);
00413     src.setSize(vigra::Size2D(360,180));
00414     m_pano2erect = new HuginBase::PTools::Transform;
00415     m_pano2erect->createTransform(src, opts);
00416 
00417     if (m_panoBitmap) {
00418         delete m_panoBitmap;
00419     }
00420     m_panoBitmap = new wxBitmap(panoImage);
00421 
00422 
00423     // always redraw
00424     wxClientDC dc(this);
00425     DrawPreview(dc);
00426 
00427     m_state_rendering = false;
00428     DEBUG_DEBUG("m_state_rendering = false");
00429     m_rerender = false;
00430 }
00431 
00432 
00433 void PreviewPanel::DrawPreview(wxDC & dc)
00434 {
00435     if (!IsShown()){
00436         return;
00437     }
00438     DEBUG_TRACE("");
00439 
00440     int offsetX = 0;
00441     int offsetY = 0;
00442 
00443     wxSize sz = GetClientSize();
00444     if (sz.GetWidth() > m_panoImgSize.x) {
00445         offsetX = (sz.GetWidth() - m_panoImgSize.x) / 2;
00446     }
00447     if (sz.GetHeight() > m_panoImgSize.y) {
00448         offsetY = (sz.GetHeight() - m_panoImgSize.y) / 2;
00449     }
00450 
00451     dc.SetPen(wxPen(GetBackgroundColour(), 1, wxPENSTYLE_SOLID));
00452     dc.SetBrush(wxBrush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
00453     dc.DrawRectangle(0, 0, offsetX, sz.GetHeight());
00454     dc.DrawRectangle(offsetX, 0, sz.GetWidth(), offsetY);
00455     dc.DrawRectangle(offsetX, sz.GetHeight() - offsetY,
00456                      sz.GetWidth(), sz.GetHeight());
00457     dc.DrawRectangle(sz.GetWidth() - offsetX, offsetY,
00458                      sz.GetWidth(), sz.GetHeight() - offsetY);
00459 
00460     // set a clip region to draw stuff accordingly
00461     dc.DestroyClippingRegion();
00462     dc.SetClippingRegion(offsetX, offsetY,
00463                          m_panoImgSize.x, m_panoImgSize.y);
00464 
00465     dc.SetPen(wxPen(wxT("BLACK"), 1, wxPENSTYLE_SOLID));
00466     dc.SetBrush(wxBrush(wxT("BLACK"), wxBRUSHSTYLE_SOLID));
00467     dc.DrawRectangle(offsetX, offsetY, m_panoImgSize.x, m_panoImgSize.y);
00468 
00469 
00470     wxCoord w = m_panoImgSize.x;
00471     wxCoord h = m_panoImgSize.y;
00472 
00473 
00474     // draw panorama image
00475     if (m_panoBitmap) {
00476 
00477         dc.DrawBitmap(*m_panoBitmap, offsetX, offsetY);
00478 
00479         // draw ROI
00480         vigra::Size2D panoSize = pano->getOptions().getSize();
00481         vigra::Rect2D panoROI = pano->getOptions().getROI();
00482         if (panoROI != vigra::Rect2D(panoSize)) {
00483 
00484             double scale = std::min(w/(double)panoSize.x, h/(double)panoSize.y);
00485             vigra::Rect2D previewROI = vigra::Rect2D(panoROI.upperLeft()* scale, panoROI.lowerRight() * scale);
00486             vigra::Rect2D screenROI = previewROI;
00487             screenROI.moveBy(offsetX, offsetY);
00488 
00489 
00490             // TODO: make areas outside ROI darker than the rest of the image
00491             // overdraw areas outside the ROI with some black half transparent
00492             // bitmap
00493             // it seems to be quite complicated to create a half transparent black image...
00494             wxImage blackImg(w,h);
00495             // init alpha channel
00496             if (!blackImg.HasAlpha()) {
00497                 blackImg.InitAlpha();
00498             }
00499             unsigned char * aptr = blackImg.GetAlpha();
00500             unsigned char * aend = aptr + w*h;
00501             for (; aptr != aend; ++aptr)
00502                 *aptr = 128;
00503             wxBitmap blackBitmap(blackImg);
00504 
00505             // left
00506             if (screenROI.left() > offsetX) {
00507                 dc.DestroyClippingRegion();
00508                 dc.SetClippingRegion(offsetX, offsetY,
00509                                      previewROI.left(), h);
00510                 dc.DrawBitmap(blackBitmap, offsetX, offsetY);
00511             }
00512             // top
00513             if (screenROI.top() > offsetY ) {
00514                 dc.DestroyClippingRegion();
00515                 dc.SetClippingRegion(screenROI.left(), offsetY,
00516                                      previewROI.width(), previewROI.top());
00517                 dc.DrawBitmap(blackBitmap, offsetX, offsetY);
00518             }
00519             // right
00520             if (screenROI.right() < offsetX + w) {
00521                 dc.DestroyClippingRegion();
00522                 dc.SetClippingRegion(screenROI.right(), offsetY,
00523                                      w - previewROI.right(), h);
00524                 dc.DrawBitmap(blackBitmap, offsetX, offsetY);
00525             }
00526             // bottom
00527             if (screenROI.bottom() < offsetY + h ) {
00528                 dc.DestroyClippingRegion();
00529                 dc.SetClippingRegion(screenROI.left(), screenROI.bottom(),
00530                                      screenROI.width(), h - previewROI.bottom());
00531                 dc.DrawBitmap(blackBitmap, offsetX, offsetY);
00532             }
00533 
00534 
00535             // reset clipping region
00536             dc.DestroyClippingRegion();
00537             dc.SetClippingRegion(offsetX, offsetY,
00538                          m_panoImgSize.x, m_panoImgSize.y);
00539 
00540             // draw boundaries
00541             dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
00542             dc.SetLogicalFunction(wxINVERT);
00543 
00544             DEBUG_DEBUG("ROI scale factor: " << scale << " screen ROI: " << screenROI);
00545 
00546             dc.DrawLine(screenROI.left(),screenROI.top(),
00547                         screenROI.right(),screenROI.top());
00548             dc.DrawLine(screenROI.right(),screenROI.top(),
00549                         screenROI.right(),screenROI.bottom());
00550             dc.DrawLine(screenROI.right(),screenROI.bottom(),
00551                         screenROI.left(),screenROI.bottom());
00552             dc.DrawLine(screenROI.left(),screenROI.bottom(),
00553                         screenROI.left(),screenROI.top());
00554 
00555 
00556         }
00557     }
00558 
00559     dc.DestroyClippingRegion();
00560     dc.SetClippingRegion(offsetX, offsetY,
00561                     m_panoImgSize.x, m_panoImgSize.y);
00562 
00563     // draw center lines over display
00564     dc.SetPen(wxPen(wxT("WHITE"), 1, wxPENSTYLE_SOLID));
00565     dc.SetLogicalFunction(wxINVERT);
00566     dc.DrawLine(offsetX + w/2, offsetY,
00567                 offsetX + w/2, offsetY + h);
00568     dc.DrawLine(offsetX, offsetY + h/2,
00569                 offsetX + w, offsetY+ h/2);
00570 
00571 }
00572 
00573 void PreviewPanel::OnDraw(wxPaintEvent & event)
00574 {
00575     wxPaintDC dc(this);
00576     DrawPreview(dc);
00577 }
00578 
00579 void PreviewPanel::OnResize(wxSizeEvent & e)
00580 {
00581     DEBUG_TRACE("");
00582     wxSize sz = GetClientSize();
00583     if (sz.GetWidth() != m_panoImgSize.x && sz.GetHeight() != m_panoImgSize.y) {
00584         m_remapCache.invalidate();
00585         if (m_autoPreview) {
00586             ForceUpdate();
00587         }
00588     }
00589 }
00590 
00591 
00592 void PreviewPanel::mousePressLMBEvent(wxMouseEvent & e)
00593 {
00594     DEBUG_DEBUG("mousePressLMBEvent: " << e.m_x << "x" << e.m_y);
00595     double yaw, pitch;
00596     mouse2erect(e.m_x, e.m_y,  yaw, pitch);
00597     // calculate new rotation angles.
00598     Matrix3 rotY;
00599     rotY.SetRotationPT(DEG_TO_RAD(-yaw), 0, 0);
00600     Matrix3 rotP;
00601     rotP.SetRotationPT(0, DEG_TO_RAD(pitch), 0);
00602 
00603     double y,p,r;
00604     Matrix3 rot = rotP * rotY;
00605     rot.GetRotationPT(y,p,r);
00606     y = RAD_TO_DEG(y);
00607     p = RAD_TO_DEG(p);
00608     r = RAD_TO_DEG(r);
00609     DEBUG_DEBUG("rotation angles pitch*yaw: " << y << " " << p << " " << r);
00610 
00611     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00612             new PanoCommand::RotatePanoCmd(*pano, y, p, r)
00613         );
00614     if (!m_autoPreview) {
00615         ForceUpdate();
00616     }
00617 }
00618 
00619 
00620 void PreviewPanel::mousePressRMBEvent(wxMouseEvent & e)
00621 {
00622     DEBUG_DEBUG("mousePressRMBEvent: " << e.m_x << "x" << e.m_y);
00623     double yaw, pitch;
00624     mouse2erect(e.m_x, e.m_y,  yaw, pitch);
00625     // theta, phi: spherical coordinates in mathworld notation.
00626     double theta = DEG_TO_RAD(yaw);
00627     double phi = DEG_TO_RAD(90+pitch);
00628     // convert to cartesian coordinates.
00629 #ifdef DEBUG
00630     double x = cos(theta)* sin(phi);
00631 #endif
00632     double y = sin(theta)* sin(phi);
00633     double z = cos(phi);
00634     DEBUG_DEBUG("theta: " << theta << " phi: " << phi << " x y z:" << x << " " << y << " " << z);
00635     double roll = RAD_TO_DEG(atan(z/y));
00636 
00637     DEBUG_DEBUG("roll correction: " << roll);
00638 
00639     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00640             new PanoCommand::RotatePanoCmd(*pano, 0, 0, roll)
00641         );
00642     if (!m_autoPreview) {
00643         ForceUpdate();
00644     }
00645 }
00646 
00647 
00648 void PreviewPanel::OnMouse(wxMouseEvent & e)
00649 {
00650     double yaw, pitch;
00651     mouse2erect(e.m_x, e.m_y,  yaw, pitch);
00652 
00653     parentWindow->SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0);
00654     parentWindow->SetStatusText(wxString::Format(wxT("%.1f %.1f"), yaw, pitch), 1);
00655 }
00656 
00657 void PreviewPanel::mouse2erect(int xm, int ym, double &xd, double & yd)
00658 {
00659     if (m_pano2erect) {
00660         int offsetX=0, offsetY=0;
00661         wxSize sz = GetClientSize();
00662         if (sz.GetWidth() > m_panoImgSize.x) {
00663             offsetX = (sz.GetWidth() - m_panoImgSize.x) / 2;
00664         }
00665         if (sz.GetHeight() > m_panoImgSize.y) {
00666             offsetY = (sz.GetHeight() - m_panoImgSize.y) / 2;
00667         }
00668         double x = xm - offsetX - m_panoImgSize.x/2;
00669         double y = ym - offsetY - m_panoImgSize.y/2;
00670         m_pano2erect->transform(xd, yd, x, y);
00671         //DEBUG_DEBUG("pano: " << x << " " << y << "  erect: " << xd << "° " << yd << "°");
00672      }
00673 }
00674 
00675 void PreviewPanel::DrawOutline(const std::vector<hugin_utils::FDiff2D> & points, wxDC & dc, int offX, int offY)
00676 {
00677     for (std::vector<hugin_utils::FDiff2D>::const_iterator pnt = points.begin();
00678          pnt != points.end() ;
00679          ++pnt)
00680     {
00681         vigra::Diff2D point = pnt->toDiff2D();
00682         if (point.x < 0) point.x = 0;
00683         if (point.y < 0) point.y = 0;
00684         if (point.x >= m_panoImgSize.x)
00685             point.x = m_panoImgSize.y-1;
00686         if (point.y >= m_panoImgSize.y)
00687             point.y = m_panoImgSize.y -1;
00688         dc.DrawPoint(hugin_utils::roundi(offX + point.x), hugin_utils::roundi(offY + point.y));
00689     }
00690 }
00691 
00692 
00693 IMPLEMENT_DYNAMIC_CLASS(PreviewPanel, wxPanel)
00694 
00695         PreviewPanelXmlHandler::PreviewPanelXmlHandler()
00696     : wxXmlResourceHandler()
00697 {
00698     AddWindowStyles();
00699 }
00700 
00701 wxObject *PreviewPanelXmlHandler::DoCreateResource()
00702 {
00703     XRC_MAKE_INSTANCE(cp, PreviewPanel)
00704 
00705             cp->Create(m_parentAsWindow,
00706                        GetID(),
00707                        GetPosition(), GetSize(),
00708                        GetStyle(wxT("style")),
00709                        GetName());
00710 
00711     SetupWindow( cp);
00712 
00713     return cp;
00714 }
00715 
00716 bool PreviewPanelXmlHandler::CanHandle(wxXmlNode *node)
00717 {
00718     return IsOfClass(node, wxT("PreviewPanel"));
00719 }
00720 
00721 IMPLEMENT_DYNAMIC_CLASS(PreviewPanelXmlHandler, wxXmlResourceHandler)
00722 

Generated on 27 Jul 2016 for Hugintrunk by  doxygen 1.4.7