PreviewPanel.cpp

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

Generated on 26 May 2017 for Hugintrunk by  doxygen 1.4.7