Hugin trunk 0.1
Loading...
Searching...
No Matches
ImagesTree.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
10/* This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This software is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this software. If not, see
22 * <http://www.gnu.org/licenses/>.
23 *
24 */
25
26#include "hugin_config.h"
27#include "panoinc_WX.h"
28#include "panoinc.h"
29
30#include "base_wx/wxPlatform.h"
31#include "base_wx/LensTools.h"
32#include "hugin/ImagesTree.h"
34#include "base_wx/platform.h"
35#include "base_wx/wxutils.h"
40#include "base_wx/PanoCommand.h"
43#include "hugin/huginApp.h"
44#include "hugin/MainFrame.h"
46#include <wx/renderer.h>
47
48enum
49{
60};
61
62class ImagesTreeData : public wxTreeItemData
63{
64public:
65 explicit ImagesTreeData(const long& nr) : m_nr(nr) { };
66 const long GetImgNr() const { return m_nr;};
68 const long GetGroupNr() const { return -(m_nr+1);};
69 const bool IsGroup() const { return (m_nr<0); };
70
71private:
72 long m_nr;
73};
74
75// Define a constructor for the Images Panel
87
89 const wxPoint& pos,
90 const wxSize& size,
91 long style,
92 const wxString& name)
93{
94 DEBUG_TRACE("List");
96 {
97 return false;
98 }
99
100 DEBUG_TRACE("Tree, adding columns");
101 m_configClassName = "/ImagesTree";
103 DEBUG_TRACE("");
104 m_degDigits = wxConfigBase::Get()->Read("/General/DegreeFractionalDigits",1);
105 m_pixelDigits = wxConfigBase::Get()->Read("/General/PixelFractionalDigits",1);
106 m_distDigits = wxConfigBase::Get()->Read("/General/DistortionFractionalDigits",3);
107 //create root
108 m_root=AddRoot("root");
109 // bind event handler
116 // for working double click we need also the menu handler on ID_EDIT
122
123 return true;
124}
125
127{
128 size_t counter=0;
129#define ADDCOLUMN(header, mapName, width, align, isEditable, IVE, tooltip) \
130 AddColumn(header, width, align, -1, true, false, tooltip);\
131 m_columnMap[mapName]=counter;\
132 m_columnVector.push_back(mapName);\
133 if(isEditable)\
134 {\
135 m_editableColumns.insert(counter);\
136 };\
137 m_variableVector.push_back(IVE);\
138 counter++;
139 ADDCOLUMN("#", "imgNr", 35, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image number"))
140 ADDCOLUMN(_("Filename"), "filename", 200, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Filename"))
141 ADDCOLUMN(_("Width"), "width", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image width"))
142 ADDCOLUMN(_("Height"), "height", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image height"))
143 ADDCOLUMN(_("Anchor"), "anchor", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Anchor image for position and/or exposure"))
144 ADDCOLUMN(_("# Ctrl Pnts"), "cps", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Number of control points in this image"))
145 ADDCOLUMN(_("Lens no."), "lensNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned lens number"))
146 ADDCOLUMN(_("Stack no."), "stackNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned stack number"))
147
148 ADDCOLUMN(_("Maker"), "maker", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera maker"))
149 ADDCOLUMN(_("Model"), "model", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera model"))
150 ADDCOLUMN(_("Lens"), "lens", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Used lens"))
151 ADDCOLUMN(_("Capture date"), "date", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Date, image was taken"))
152 ADDCOLUMN(_("Focal length"), "focallength", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Focal length"))
153 ADDCOLUMN(_("Aperture"), "aperture", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Aperture"))
154 ADDCOLUMN(_("Shutter Speed"), "time", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Shutter speed"))
155 ADDCOLUMN(_("ISO"), "iso", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("ISO speed"))
156
157 ADDCOLUMN(_("Yaw (y)"), "y", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Yaw"))
158 ADDCOLUMN(_("Pitch (p)"), "p", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Pitch"))
159 ADDCOLUMN(_("Roll (r)"), "r", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Roll"))
160 ADDCOLUMN("X (TrX)", "TrX", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation X"))
161 ADDCOLUMN("Y (TrY)", "TrY", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Y"))
162 ADDCOLUMN("Z (TrZ)", "TrZ", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Z"))
163 ADDCOLUMN(_("Plane yaw"), "Tpy", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane yaw"))
164 ADDCOLUMN(_("Plane pitch"), "Tpp", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane pitch"))
165 ADDCOLUMN(_("Camera translation"), "cam_trans", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation"))
166
167 ADDCOLUMN(_("Lens type (f)"), "projection", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Lens type (rectilinear, fisheye, equirectangular, ...)"))
168 ADDCOLUMN(_("Hfov (v)"), "v", 80, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_HFOV, _("Horizontal field of view (v)"))
169 ADDCOLUMN("a", "a", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (a)"))
170 ADDCOLUMN("b", "b", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (b, barrel)"))
171 ADDCOLUMN("c", "c", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (c)"))
172 ADDCOLUMN("d", "d", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Horizontal image center shift (d)"))
173 ADDCOLUMN("e", "e", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Vertical image center shift (e)"))
174 ADDCOLUMN("g", "g", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Horizontal image shearing (g)"))
175 ADDCOLUMN("t", "t", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Vertical image shearing (t)"))
176
177 ADDCOLUMN("EV", "Eev", 50, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_ExposureValue, _("Exposure value (Eev)"))
178 ADDCOLUMN("Er", "Er", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceRed, _("Red multiplier (Er)"))
179 ADDCOLUMN("Eb", "Eb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceBlue, _("Blue multiplier (Eb)"))
180 ADDCOLUMN("Vb", "Vb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
181 ADDCOLUMN("Vc", "Vc", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
182 ADDCOLUMN("Vd", "Vd", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
183 ADDCOLUMN("Vx", "Vx", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Horizontal vignetting center shift (Vx)"))
184 ADDCOLUMN("Vy", "Vy", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Vertical vignetting center shift (Vy)"))
185 ADDCOLUMN(_("Response type"), "response", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera response type"))
186 ADDCOLUMN("Ra", "Ra", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
187 ADDCOLUMN("Rb", "Rb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
188 ADDCOLUMN("Rc", "Rc", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
189 ADDCOLUMN("Rd", "Rd", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
190 ADDCOLUMN("Re", "Re", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
191
192 //empty column to have enough space on the right side
194
195 //get saved width
196 for ( int j=0; j < GetColumnCount() ; j++ )
197 {
198 // -1 is auto
199 int width = wxConfigBase::Get()->Read(wxString::Format(m_configClassName+"/ColumnWidth%d", j ), -1);
200 if(width != -1)
201 SetColumnWidth(j, width);
202 }
203};
204
218
225
227{
229 {
230 Freeze();
232 Thaw();
233#ifdef __WXGTK__
234 Refresh();
235#endif
236 };
238 {
240 fill_set(imgs, 0, pano.getNrOfImages()-1);
241 panoramaImagesChanged(pano, imgs);
242 };
243 m_needsUpdate=true;
244};
245
247{
248 DEBUG_TRACE("");
249
250 Freeze();
252 // Make sure the part numbers are up to date before writing them to the table.
256 //if the number of lenses or stacks have changed we need to update all images
257 //because the changed images set contains only the list of the changed imagges
258 //but not these images where the stack or lens number has changed because
259 //an images has been inserted
260 if(pano.getNrOfImages()>0)
261 {
264 {
265 fill_set(changedImgs, 0, pano.getNrOfImages()-1);
266 };
267 };
269 {
271 {
273 };
275 {
277 };
278 };
280 {
282 if(m_pano->getNrOfImages()>0)
283 {
284 fill_set(imgs,0,m_pano->getNrOfImages()-1);
285 };
287 }
288 else
289 {
291 switch (m_groupMode)
292 {
293 case GROUP_LENS:
295 break;
296 case GROUP_STACK:
298 break;
301 break;
303 imageGroups=getExposureLayers(*m_pano,m_pano->getActiveImages(), m_pano->getOptions());
304 break;
305 };
306
307 size_t nrItems=GetChildrenCount(m_root,false);
308 if(nrItems!=imageGroups.size())
309 {
310 if(nrItems<imageGroups.size())
311 {
312 for(size_t i=nrItems;i<imageGroups.size();i++)
313 {
314 AppendItem(m_root,wxEmptyString,-1,-1,new ImagesTreeData(-(long)i-1));
315 };
316 }
317 else
318 {
319 while(GetChildrenCount(m_root,false)>imageGroups.size())
320 {
323 Delete(item);
324 };
325 };
326 };
327
330 size_t i=0;
331 while(item.IsOk())
332 {
336 };
337 };
338 // updates checkboxes images for optimizer variables
340 {
342 };
344 {
346 };
347
348 Thaw();
349 m_needsUpdate = false;
350
351 // HACK! need to notify clients anyway... send dummy event..
352 // lets hope our clients query for the selected images with GetSelected()
353 // and do not try to interpret the event.
354 wxListEvent e;
355 e.SetEventType(wxEVT_COMMAND_LIST_ITEM_SELECTED);
356 e.m_itemIndex = -1;
357 GetEventHandler()->ProcessEvent(e);
358}
359
361{
363 // NAMEisLinked returns always false, if the lens or stacks contains only a single image
364 // so add a special handling for this case
365 bool isSingleImage = false;
366 if (m_groupMode != GROUP_NONE)
367 {
369 };
370 wxString s;
371 const size_t imgNr=itemData->GetImgNr();
372 const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
373 wxFileName fn(wxString (img.getFilename().c_str(), HUGIN_CONV_FILENAME));
374
375 s << imgNr;
376 SetItemText(item, m_columnMap["imgNr"], s);
377 s.Clear();
378 SetItemText(item, m_columnMap["filename"], fn.GetFullName() );
379 SetItemText(item, m_columnMap["width"], wxString::Format("%d", img.getSize().width()));
380 SetItemText(item, m_columnMap["height"], wxString::Format("%d", img.getSize().height()));
381
384 {
385 flags.Append("A");
386 }
387 else
388 {
389 flags.Append("-");
390 }
391 if (m_pano->getOptions().colorReferenceImage == imgNr)
392 {
393 flags.Append("C");
394 }
395 else
396 {
397 flags.Append("-");
398 };
399 SetItemText(item, m_columnMap["anchor"], flags);
400 std::vector<unsigned int> cps = m_pano->getCtrlPointsForImage(imgNr);
401 s << cps.size();
402 SetItemText(item, m_columnMap["cps"], s);
403 s.Clear();
404 const unsigned int stackNumber = m_variable_groups->getStacks().getPartNumber(imgNr);
405 SetItemText(item, m_columnMap["stackNr"], wxString::Format("%u", stackNumber));
406 const unsigned int lensNr=m_variable_groups->getLenses().getPartNumber(imgNr);
407 SetItemText(item, m_columnMap["lensNr"], wxString::Format("%u", lensNr));
408
409 SetItemText(item, m_columnMap["maker"], wxString(img.getExifMake().c_str(), wxConvLocal));
410 SetItemText(item, m_columnMap["model"], wxString(img.getExifModel().c_str(), wxConvLocal));
411 SetItemText(item, m_columnMap["lens"], wxString(img.getExifLens().c_str(), wxConvLocal));
417
418 if (m_groupMode == GROUP_STACK && (img.YawisLinked() || isSingleImage))
419 {
429 }
430 else
431 {
438 SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
439 SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
440 wxString text=_("not active");
441 if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
442 {
443 text=_("active");
444 };
445 text.Prepend(" ");
446 SetItemText(item, m_columnMap["cam_trans"], text);
447 };
448
450 {
451 SetItemText(item, m_columnMap["projection"], wxEmptyString);
453 }
454 else
455 {
456 SetItemText(item, m_columnMap["projection"], getProjectionString(img));
457 SetItemText(item, m_columnMap["response"], getResponseString(img));
458 };
459
460 if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || isSingleImage))
461 {
463 }
464 else
465 {
467 };
468
469 if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || isSingleImage))
470 {
474 }
475 else
476 {
477 std::vector<double> dist=img.getRadialDistortion();
481 };
482
483 if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || isSingleImage))
484 {
487 }
488 else
489 {
490 hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
493 };
494
495 if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || isSingleImage))
496 {
499 }
500 else
501 {
502 hugin_utils::FDiff2D p=img.getShear();
505 };
506
507 if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || isSingleImage))
508 {
510 }
511 else
512 {
514 };
515
516 if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || isSingleImage))
517 {
519 }
520 else
521 {
522 SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
523 };
524
525 if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || isSingleImage))
526 {
528 }
529 else
530 {
531 SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
532 };
533
534 if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || isSingleImage))
535 {
539 }
540 else
541 {
542 std::vector<double> dist=img.getRadialVigCorrCoeff();
546 };
547
548 if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || isSingleImage))
549 {
552 }
553 else
554 {
555 hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
558 };
559
560 if (m_groupMode == GROUP_LENS && (img.EMoRParamsisLinked() || isSingleImage))
561 {
567 }
568 else
569 {
570 if (img.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_EMOR)
571 {
572 // display Ra..Re only when response type is emor
573 // otherwise they have no meaning
574 std::vector<float> vec = img.getEMoRParams();
580 }
581 else
582 {
588 };
589 };
590};
591
593{
595 switch(m_groupMode)
596 {
597 case GROUP_LENS:
598 SetItemText(item, 1, wxString::Format(_("Lens %ld"),itemData->GetGroupNr()));
599 break;
600 case GROUP_STACK:
601 SetItemText(item, 1, wxString::Format(_("Stack %ld"),itemData->GetGroupNr()));
602 break;
604 SetItemText(item, 1, wxString::Format(_("Output stack %ld"),itemData->GetGroupNr()));
605 break;
607 SetItemText(item, 1, wxString::Format(_("Output exposure layer %ld"),itemData->GetGroupNr()));
608 break;
609 };
610 SetItemBold(item,1,true);
613 // NAMEisLinked returns always false, if the lens or stacks contains only a single image
614 // so add a special handling for this case
615 bool haveSingleChild = false;
616 if (m_groupMode != GROUP_NONE)
617 {
618 haveSingleChild = (GetChildrenCount(item, false) == 1);
619 };
620 if(childItem.IsOk())
621 {
623 const HuginBase::SrcPanoImage& img=m_pano->getImage(data->GetImgNr());
624
625 if (m_groupMode == GROUP_STACK && (img.YawisLinked() || haveSingleChild))
626 {
633 SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
634 SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
635 wxString text=_("not active");
636 if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
637 {
638 text=_("active");
639 };
640 text.Prepend(" ");
641 SetItemText(item, m_columnMap["cam_trans"], text);
642 }
643 else
644 {
654 };
655
657 {
658 SetItemText(item, m_columnMap["projection"], getProjectionString(img));
659 SetItemText(item, m_columnMap["response"], getResponseString(img));
660 }
661 else
662 {
663 SetItemText(item, m_columnMap["projection"], wxEmptyString);
665 };
666
667 if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || haveSingleChild))
668 {
670 }
671 else
672 {
674 };
675
676 if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || haveSingleChild))
677 {
678 std::vector<double> dist=img.getRadialDistortion();
682 }
683 else
684 {
688 };
689
690 if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || haveSingleChild))
691 {
692 hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
695 }
696 else
697 {
700 };
701
702 if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || haveSingleChild))
703 {
704 hugin_utils::FDiff2D p=img.getShear();
707 }
708 else
709 {
712 };
713
714 if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || haveSingleChild))
715 {
717 }
718 else
719 {
721 };
722
723 if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || haveSingleChild))
724 {
725 SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
726 }
727 else
728 {
730 };
731
732 if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || haveSingleChild))
733 {
734 SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
735 }
736 else
737 {
739 };
740
741 if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || haveSingleChild))
742 {
743 std::vector<double> dist=img.getRadialVigCorrCoeff();
747 }
748 else
749 {
753 };
754
755 if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || haveSingleChild))
756 {
757 hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
760 }
761 else
762 {
765 };
766
767 if (m_groupMode == GROUP_LENS && (img.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_EMOR && (img.EMoRParamsisLinked()) || haveSingleChild))
768 {
769 std::vector<float> vec=img.getEMoRParams();
775 }
776 else
777 {
783 };
784 };
785};
786
788{
789 size_t nrItems=GetChildrenCount(parent,false);
790 bool forceUpdate=false;
791 if(nrItems!=imgs.size())
792 {
793 forceUpdate=true;
794 if(nrItems<imgs.size())
795 {
796 for(size_t i=nrItems;i<imgs.size();i++)
797 {
799 };
800 }
801 else
802 {
803 while(GetChildrenCount(parent,false)>imgs.size())
804 {
807 Delete(item);
808 };
809 };
810 };
811 //now update values
814 HuginBase::UIntSet::const_iterator it=imgs.begin();
815 while(item.IsOk())
816 {
817 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
818 if(it==imgs.end())
819 {
820 break;
821 };
822 bool needsUpdate=false;
823 if(data->GetImgNr()!=*it)
824 {
825 data->SetImgNr(*it);
826 needsUpdate=true;
827 }
828 else
829 {
831 {
832 needsUpdate=true;
833 };
834 };
836 {
838 changed.erase(*it);
839 };
841 ++it;
842 };
843};
844
846{
850 while(item.IsOk())
851 {
852 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
853 HuginBase::UIntSet imgNrs;
854 if(data->IsGroup())
855 {
858 while(child.IsOk())
859 {
860 data=static_cast<ImagesTreeData*>(GetItemData(child));
861 imgNrs.insert(data->GetImgNr());
863 };
864 }
865 else
866 {
867 imgNrs.insert(data->GetImgNr());
868 };
869 if(!imgNrs.empty())
870 {
871 for(size_t i=0;i<GetColumnCount();i++)
872 {
874 {
875 if (GetItemText(item, i).IsEmpty())
876 {
877 // item with no text can have no checkbox
878 // this can happen with linked variables
879 SetItemImage(item, i, -1);
880 }
881 else
882 {
883 bool opt=false;
884 for(HuginBase::UIntSet::const_iterator it=imgNrs.begin(); it!=imgNrs.end() && !opt;++it)
885 {
886 if(m_columnVector[i]=="cam_trans")
887 {
888 opt=set_contains(optVec[*it], "TrX") &&
889 set_contains(optVec[*it], "TrY") &&
890 set_contains(optVec[*it], "TrZ") &&
891 set_contains(optVec[*it], "Tpy") &&
892 set_contains(optVec[*it], "Tpp");
893 }
894 else
895 {
897 };
898 };
899 SetItemImage(item, i, opt ? 1 : 0);
900 };
901 };
902 };
903 };
905 };
906};
907
909{
912 if(GetSelections (selected)>0)
913 {
914 for(size_t i=0;i<selected.size();i++)
915 {
916 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selected[i]));
917 if(data->IsGroup())
918 {
921 while(item.IsOk())
922 {
923 data=static_cast<ImagesTreeData*>(GetItemData(item));
924 imgs.insert(data->GetImgNr());
926 };
927 }
928 else
929 {
930 imgs.insert(data->GetImgNr());
931 };
932 };
933 }
934 return imgs;
935}
936
942
944{
946 {
947 int colNum = e.GetColumn();
948 wxConfigBase::Get()->Write( m_configClassName+wxString::Format("/ColumnWidth%d",colNum), GetColumnWidth(colNum) );
949 }
950}
951
958
960{
961 //create bitmaps for different checkboxes state
962 wxRendererNative& renderer = wxRendererNative::Get();
963 const wxSize checkBoxSize = renderer.GetCheckBoxSize(this);
964 wxImageList* checkboxImageList = new wxImageList(checkBoxSize.GetWidth(), checkBoxSize.GetHeight(), true, 0);
967 // unchecked checkbox
968 dc.Clear();
969 renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize));
970 dc.SelectObject(wxNullBitmap);
972 // checked checkbox
973 dc.SelectObject(checkBoxImage);
974 dc.Clear();
975 renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CHECKED);
976 dc.SelectObject(wxNullBitmap);
978 // mouse over unchecked checkbox
979 dc.SelectObject(checkBoxImage);
980 dc.Clear();
981 renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CURRENT);
982 dc.SelectObject(wxNullBitmap);
984 // mouse over checked checkbox
985 dc.SelectObject(checkBoxImage);
986 dc.Clear();
988 dc.SelectObject(wxNullBitmap);
990
992}
993
995{
996 m_optimizerMode=true;
997 // connnect events with handlers
1000 // build image list with check box images
1002 // activate edit mode
1003 for(HuginBase::UIntSet::const_iterator it=m_editableColumns.begin(); it!=m_editableColumns.end(); ++it)
1004 {
1005 if(m_columnVector[*it]!="cam_trans")
1006 {
1007 SetColumnEditable(*it,true);
1008 };
1009 };
1010}
1011
1013{
1014 // dpi has changed, we need to update the images of the checkboxes
1015 if (m_optimizerMode)
1016 {
1018 Refresh();
1019 };
1020}
1021
1023{
1025 {
1028 {
1029 SetWindowStyle(GetWindowStyle() | wxTR_NO_LINES);
1030 }
1031 else
1032 {
1033 SetWindowStyle(GetWindowStyle() & ~wxTR_NO_LINES);
1034 };
1036 HuginBase::UIntSet imgs;
1037 if(m_pano->getNrOfImages()>0)
1038 {
1039 fill_set(imgs,0,m_pano->getNrOfImages()-1);
1040 };
1042 // reset already modified tag
1043 m_needsUpdate = true;
1045 };
1046};
1047
1049{
1051
1058
1067
1077
1087
1102
1103 Refresh();
1104};
1105
1107{
1108 m_selectedColumn=e.GetInt();
1109 wxMenu menu;
1110 bool allowMenuExtension=true;
1111 if(e.GetItem().IsOk())
1112 {
1113 //click on item
1115 {
1116 bool emptyText=GetItemText(e.GetItem(),m_selectedColumn).IsEmpty();
1117 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
1118 bool varIsLinkable = false;
1119 if (m_groupMode == GROUP_LENS)
1120 {
1121 varIsLinkable = m_variableVector[m_selectedColumn] != HuginBase::ImageVariableGroup::IVE_Yaw &&
1123 }
1124 else
1125 {
1126 if (m_groupMode == GROUP_STACK)
1127 {
1128 varIsLinkable = m_variableVector[m_selectedColumn] == HuginBase::ImageVariableGroup::IVE_Yaw;
1129 }
1130 };
1131 if(varIsLinkable)
1132 {
1133 if(data->IsGroup())
1134 {
1135 if(emptyText)
1136 {
1137 menu.Append(ID_LINK,_("Link"));
1139 }
1140 else
1141 {
1142 menu.Append(ID_UNLINK, _("Unlink"));
1144 };
1145 }
1146 else
1147 {
1148 if(emptyText)
1149 {
1150 menu.Append(ID_UNLINK,_("Unlink"));
1152 }
1153 else
1154 {
1155 menu.Append(ID_LINK, _("Link"));
1157 };
1158 };
1159 menu.AppendSeparator();
1160 };
1161 if(m_optimizerMode)
1162 {
1163 if(data->IsGroup() == emptyText)
1164 {
1165 if(m_groupMode==GROUP_LENS && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Yaw)
1166 {
1167 menu.Append(ID_SELECT_LENS_STACK, _("Select all for current lens"));
1169 menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current lens"));
1171 };
1172 if(m_groupMode==GROUP_STACK && m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
1173 {
1174 menu.Append(ID_SELECT_LENS_STACK, _("Select all for current stack"));
1176 menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current stack"));
1178 };
1179 };
1180 if(m_columnVector[m_selectedColumn]!="cam_trans")
1181 {
1182 menu.Append(ID_SELECT_ALL, _("Select all"));
1184 };
1185 menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
1187 menu.AppendSeparator();
1188 }
1189 };
1190 menu.Append(ID_EDIT, _("Edit image variables..."));
1191 // handler for ID_EDIT is already Bind() in ImagesTreeCtrl::Create to make it work with double click,
1192 // so no need to call Bind again
1194 {
1196 if (selectedImages.size() == 1)
1197 {
1198 if (m_pano->getImage(*selectedImages.begin()).getActive())
1199 {
1200 menu.Append(ID_DEACTIVATE_IMAGE, _("Deactivate image"));
1202 }
1203 else
1204 {
1205 menu.Append(ID_ACTIVATE_IMAGE, _("Activate image"));
1207 };
1208 }
1209 else
1210 {
1211 menu.Append(ID_ACTIVATE_IMAGE, _("Activate images"));
1213 menu.Append(ID_DEACTIVATE_IMAGE, _("Deactivate images"));
1215 };
1216 };
1217 }
1218 else
1219 {
1221 {
1222 if(m_columnVector[m_selectedColumn]!="cam_trans")
1223 {
1224 menu.Append(ID_SELECT_ALL, _("Select all"));
1226 };
1227 menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
1229 allowMenuExtension=false;
1230 }
1231 };
1233 {
1234 if(menu.GetMenuItemCount()>0)
1235 {
1236 menu.AppendSeparator();
1237 };
1238 int id=ID_OPERATION_START;
1239 m_menuOperation.clear();
1241 wxMenu* subMenu=new wxMenu();
1243 if(subMenu->GetMenuItemCount()>0)
1244 {
1245 menu.Append(-1,_("Lens"), subMenu);
1246 }
1247 else
1248 {
1249 delete subMenu;
1250 };
1252 {
1253 subMenu=new wxMenu();
1255 if(subMenu->GetMenuItemCount()>0)
1256 {
1257 menu.Append(-1,_("Stacks"), subMenu);
1258 }
1259 else
1260 {
1261 delete subMenu;
1262 };
1263 };
1264 subMenu=new wxMenu();
1266 if(subMenu->GetMenuItemCount()>0)
1267 {
1268 menu.Append(-1, _("Control points"), subMenu);
1269 }
1270 else
1271 {
1272 delete subMenu;
1273 };
1274 subMenu=new wxMenu();
1276 if(subMenu->GetMenuItemCount()>0)
1277 {
1278 menu.Append(-1, _("Reset"), subMenu);
1279 }
1280 else
1281 {
1282 delete subMenu;
1283 };
1284 };
1285 if(menu.GetMenuItemCount()>0)
1286 {
1287 PopupMenu(&menu);
1288 };
1289 e.Skip();
1290};
1291
1293{
1295 for(size_t i=0; i<operations->size(); i++)
1296 {
1297 if((*operations)[i]->IsEnabled(*m_pano, imgs, m_guiLevel))
1298 {
1299 menu->Append(id, (*operations)[i]->GetLabel());
1300 m_menuOperation[id]=(*operations)[i];
1302 id++;
1303 }
1304 };
1305}
1306
1308{
1309 const wxColour normalColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
1310 const wxColour disabledColour = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
1312 {
1315 while (item.IsOk())
1316 {
1318 bool isActive = true;
1319 if (itemData->IsGroup())
1320 {
1323 while (child.IsOk())
1324 {
1327 if (isActive)
1328 {
1329 break;
1330 };
1332 };
1333 }
1334 else
1335 {
1336 isActive = m_pano->getImage(itemData->GetImgNr()).getActive();
1337 };
1338 if (isActive)
1339 {
1341 }
1342 else
1343 {
1345 };
1346 if(itemData->IsGroup())
1347 {
1350 while (child.IsOk())
1351 {
1353 if (m_pano->getImage(childItemData->GetImgNr()).getActive())
1354 {
1356 }
1357 else
1358 {
1360 };
1362 };
1363 };
1365 };
1366 }
1367 else
1368 {
1371 while (item.IsOk())
1372 {
1375 if (itemData->IsGroup())
1376 {
1379 while (child.IsOk())
1380 {
1383 };
1384 };
1386 };
1387 };
1388};
1389
1391{
1392 m_selectedColumn=e.GetColumn();
1393 wxMenu menu;
1395 {
1396 menu.Append(ID_SELECT_ALL, _("Select all"));
1398 menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
1400 PopupMenu(&menu);
1401 };
1402 e.Skip();
1403}
1404void ImagesTreeCtrl::OnActivateImage(wxCommandEvent & e)
1405{
1406 HuginBase::UIntSet activeImages = m_pano->getActiveImages();
1408 std::copy(selectedImages.begin(), selectedImages.end(), std::inserter(activeImages, activeImages.end()));
1410 new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
1411 );
1412};
1413
1415{
1416 HuginBase::UIntSet activeImages = m_pano->getActiveImages();
1419 std::set_difference(activeImages.begin(), activeImages.end(), selectedImages.begin(), selectedImages.end(), std::inserter(newActiveImages, newActiveImages.end()));
1422 );
1423};
1424
1426{
1428 if(!images.empty() && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Filename)
1429 {
1430 std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
1431 variables.insert(m_variableVector[m_selectedColumn]);
1432 if(m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
1433 {
1434 variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
1435 variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
1436 variables.insert(HuginBase::ImageVariableGroup::IVE_X);
1437 variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
1438 variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
1439 variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
1440 variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
1441 };
1443 {
1446 );
1447 }
1448 else
1449 {
1452 );
1453 };
1454 };
1455};
1456
1458{
1460};
1461
1463{
1464 UnLinkImageVariables(false);
1465};
1466
1468{
1470 if(!imgs.empty())
1471 {
1472 ImageVariableDialog dlg(this, m_pano, imgs);
1473 dlg.SetGuiLevel(m_guiLevel);
1474 switch(m_displayMode)
1475 {
1476 case DISPLAY_LENS:
1477 dlg.SelectTab(1);
1478 break;
1482 if(m_selectedColumn==m_columnMap["response"] ||
1488 {
1489 dlg.SelectTab(3);
1490 }
1491 else
1492 {
1493 dlg.SelectTab(2);
1494 };
1495 break;
1496 default:
1497 break;
1498 };
1499 dlg.ShowModal();
1500 };
1501};
1502
1504{
1506 if(m_pano->getNrOfImages()>0 && !m_dragging)
1507 {
1509 if(!m_draggingImages.empty())
1510 {
1511 if((m_groupMode==GROUP_NONE && m_draggingImages.size()==1 && !ctrlPressed) ||
1513 {
1514 e.Allow();
1516 m_dragging=true;
1517 };
1518 };
1519 };
1520};
1521
1523{
1524 //we can't use wxEVT_TREE_END_DRAG because this event is fire several times, e.g. when
1525 // the mouse leaves the area of the tree
1526 // so we are listing to left mouse up, as described in documentation
1527 if(m_dragging)
1528 {
1530 m_dragging=false;
1531 wxTreeItemId item=HitTest(e.GetPosition());
1533 {
1534 size_t img1=*m_draggingImages.begin();
1535 size_t img2=-1;
1536 if(item.IsOk())
1537 {
1538 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
1539 img2=data->GetImgNr();
1540 }
1541 else
1542 {
1543 //we are checking the points above, if we find then
1544 // an item, the user drop it below the last item, if not
1545 // the drop happened right beside the item
1546 wxPoint pos(e.GetPosition());
1547 pos.y-=10;
1548 while(pos.y>0)
1549 {
1550 item=HitTest(pos);
1551 if(item.IsOk())
1552 {
1553 img2=m_pano->getNrOfImages()-1;
1554 break;
1555 };
1556 pos.y-=10;
1557 };
1558 };
1559 if(img2!=-1)
1560 {
1561 if(img1!=img2)
1562 {
1564 new PanoCommand::MoveImageCmd(*m_pano, img1, img2)
1565 );
1566 // now update drag images groups in fast preview window, this information is not stored in Panorama class
1568 if (!images.empty() && images.size() < m_pano->getNrOfImages())
1569 {
1570 std::vector<bool> imgList(m_pano->getNrOfImages(), false);
1571 for (auto& i : images)
1572 {
1573 imgList[i] = true;
1574 };
1575 const bool moveImageChecked = imgList[img1];
1576 imgList.erase(imgList.begin() + img1);
1577 if (img2 < imgList.size())
1578 {
1579 imgList.insert(imgList.begin() + img2, moveImageChecked);
1580 }
1581 else
1582 {
1583 imgList.push_back(moveImageChecked);
1584 };
1585 images.clear();
1586 for (size_t i = 0; i < imgList.size(); ++i)
1587 {
1588 if (imgList[i])
1589 {
1590 images.insert(i);
1591 };
1592 };
1594 };
1595 };
1596 };
1597 }
1598 else
1599 {
1600 //dragging to stack/lenses
1601 if(item.IsOk())
1602 {
1603 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
1604 long groupNr=-1;
1605 if(data->IsGroup())
1606 {
1607 groupNr=data->GetGroupNr();
1608 }
1609 else
1610 {
1612 if(item.IsOk())
1613 {
1614 data=static_cast<ImagesTreeData*>(GetItemData(item));
1615 groupNr=data->GetGroupNr();
1616 };
1617 };
1618 if(groupNr>=0)
1619 {
1621 {
1624 );
1625 }
1626 else
1627 {
1630 );
1631 };
1632 };
1633 }
1634 else // item not ok, drop not on existing item, create new lens/stack
1635 {
1637 {
1640 );
1641 }
1642 else
1643 {
1646 );
1647 }
1648 };
1649 }
1650 m_draggingImages.clear();
1651 }
1652 else
1653 {
1654 if (m_optimizerMode && m_leftDownItem.IsOk())
1655 {
1656 int flags;
1657 int col;
1658 wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
1659 // check if left up is on the same item as left down
1661 {
1662 HuginBase::UIntSet imgs;
1664 if (markSelected)
1665 {
1666 // if the user clicked on one of the selected pass the selection to all selected images
1667 imgs = GetSelectedImages();
1668 }
1669 else
1670 {
1671 // the user clicked on a non-selected images, work only on this image
1672 // or all images of the clicked lens/stack
1674 if (data->IsGroup())
1675 {
1678 while (childItem.IsOk())
1679 {
1680 data = static_cast<ImagesTreeData*>(GetItemData(childItem));
1681 imgs.insert(data->GetImgNr());
1683 };
1684 }
1685 else
1686 {
1687 imgs.insert(data->GetImgNr());
1688 };
1689 };
1691 std::set<std::string> var;
1692 if (m_columnVector[m_leftDownColumn] == "cam_trans")
1693 {
1694 var.insert("TrX");
1695 var.insert("TrY");
1696 var.insert("TrZ");
1697 var.insert("Tpy");
1698 var.insert("Tpp");
1699 }
1700 else
1701 {
1702 var.insert(m_columnVector[m_leftDownColumn]);
1704 {
1705 var.insert("Tpy");
1706 var.insert("Tpp");
1707 };
1709 {
1710 var.insert("Vb");
1711 var.insert("Vc");
1712 var.insert("Vd");
1713 };
1715 {
1716 var.insert("Vx");
1717 var.insert("Vy");
1718 };
1721 {
1722 var.insert("Ra");
1723 var.insert("Rb");
1724 var.insert("Rc");
1725 var.insert("Rd");
1726 var.insert("Re");
1727 };
1728 };
1729 bool deactivate = false;
1730 if (markSelected)
1731 {
1732 // check which state the clicked image have
1734 }
1735 else
1736 {
1737 for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
1738 {
1739 //search, if image variable is marked for optimise for at least one image of group
1740 for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end() && !deactivate; ++imgIt)
1741 {
1742 if (set_contains(optVec[*imgIt], *varIt))
1743 {
1744 deactivate = true;
1745 };
1746 };
1747 };
1748 };
1749 // now deactivate or activate the image variable for optimisation
1750 if (deactivate)
1751 {
1752 for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
1753 {
1754 for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end(); ++imgIt)
1755 {
1756 optVec[*imgIt].erase(*varIt);
1757 };
1758 }
1759 }
1760 else
1761 {
1762 for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
1763 {
1764 for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end(); ++imgIt)
1765 {
1766 optVec[*imgIt].insert(*varIt);
1767 };
1768 };
1769 };
1772 );
1773 m_leftDownItem.Unset();
1774 return;
1775 };
1776 };
1777 if (m_leftDownItem.IsOk())
1778 {
1779 m_leftDownItem.Unset();
1780 };
1781 e.Skip();
1782 };
1783};
1784
1786{
1787 if (!m_dragging)
1788 {
1789 if (e.LeftDown())
1790 {
1791 // force end editing
1792 EndEdit(false);
1793 // find where user clicked
1794 int flags;
1795 int col;
1796 wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
1797 if (item.IsOk() && (flags & wxTREE_HITTEST_ONITEMICON))
1798 {
1800 {
1801 if (!GetItemText(item, col).IsEmpty())
1802 {
1803 // store for later and stop processing this event further
1806 return;
1807 };
1808 };
1809 };
1810 };
1811 };
1812 e.Skip();
1813};
1814
1816{
1817 int flags;
1818 int col;
1819 wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
1820 if (item.IsOk() && (flags & wxTREE_HITTEST_ONITEMICON))
1821 {
1822 // mouse moved over optimizer checkbox
1823 int imgNr = GetItemImage(item, col);
1824 if (imgNr >= 0 && imgNr < 2)
1825 {
1826 // update checkbox image and store position for later
1827 SetItemImage(item, col, imgNr + 2);
1830 };
1831 }
1832 else
1833 {
1834 // mouse moved from checkbox away, so update images
1835 if (m_lastCurrentItem.IsOk())
1836 {
1838 if (imgNr > 1)
1839 {
1841 };
1842 m_lastCurrentItem.Unset();
1843 };
1844 };
1845 e.Skip();
1846};
1847
1849{
1850 std::set<std::string> imgVars;
1851 std::string var=m_columnVector[m_selectedColumn];
1852 if(var=="cam_trans")
1853 {
1854 imgVars.insert("TrX");
1855 imgVars.insert("TrY");
1856 imgVars.insert("TrZ");
1857 imgVars.insert("Tpy");
1858 imgVars.insert("Tpp");
1859 }
1860 else
1861 {
1862 imgVars.insert(var);
1863 if(var=="Vb" || var=="Vc" || var=="Vd")
1864 {
1865 imgVars.insert("Vb");
1866 imgVars.insert("Vc");
1867 imgVars.insert("Vd");
1868 };
1869 if(var=="Vx" || var=="Vy")
1870 {
1871 imgVars.insert("Vx");
1872 imgVars.insert("Vy");
1873 };
1874 if(var=="Ra" || var=="Rb" || var=="Rc" || var=="Rd" || var=="Re")
1875 {
1876 imgVars.insert("Ra");
1877 imgVars.insert("Rb");
1878 imgVars.insert("Rc");
1879 imgVars.insert("Rd");
1880 imgVars.insert("Re");
1881 };
1882
1883 };
1884
1885 HuginBase::UIntSet imgs;
1886 if(allImages)
1887 {
1888 fill_set(imgs, 0, m_pano->getNrOfImages()-1);
1889 }
1890 else
1891 {
1894 {
1895 for(size_t i=0;i<selectedItem.size();i++)
1896 {
1899 if(data->IsGroup())
1900 {
1902 }
1903 else
1904 {
1906 };
1909 while(item.IsOk())
1910 {
1911 data=static_cast<ImagesTreeData*>(GetItemData(item));
1912 imgs.insert(data->GetImgNr());
1914 };
1915 };
1916 };
1917 };
1918
1920 for(HuginBase::UIntSet::iterator img=imgs.begin(); img!=imgs.end(); ++img)
1921 {
1922 for(std::set<std::string>::const_iterator it=imgVars.begin(); it!=imgVars.end(); ++it)
1923 {
1924 if(select)
1925 {
1926 if((*it=="y" || *it=="p" || *it=="r" || *it=="TrX" || *it=="TrY" || *it=="TrZ" || *it=="Tpy" || *it=="Tpp") &&
1928 {
1929 optVec[*img].erase(*it);
1930 continue;
1931 };
1932 if(*it=="Eev" && (*img==m_pano->getOptions().colorReferenceImage || m_pano->getImage(*img).ExposureValueisLinkedWith(m_pano->getImage(m_pano->getOptions().colorReferenceImage))))
1933 {
1934 optVec[*img].erase(*it);
1935 continue;
1936 };
1937 if (*it == "Er" && (*img == m_pano->getOptions().colorReferenceImage || m_pano->getImage(*img).WhiteBalanceRedisLinkedWith(m_pano->getImage(m_pano->getOptions().colorReferenceImage))))
1938 {
1939 optVec[*img].erase(*it);
1940 continue;
1941 };
1942 if (*it == "Eb" && (*img == m_pano->getOptions().colorReferenceImage || m_pano->getImage(*img).WhiteBalanceBlueisLinkedWith(m_pano->getImage(m_pano->getOptions().colorReferenceImage))))
1943 {
1944 optVec[*img].erase(*it);
1945 continue;
1946 };
1947 optVec[*img].insert(*it);
1948 }
1949 else
1950 {
1951 optVec[*img].erase(*it);
1952 };
1953 };
1954 };
1957 );
1958};
1959
1960void ImagesTreeCtrl::OnSelectAll(wxCommandEvent &e)
1961{
1962 SelectAllParameters(true, true);
1963};
1964
1965void ImagesTreeCtrl::OnUnselectAll(wxCommandEvent &e)
1966{
1967 SelectAllParameters(false, true);
1968};
1969
1971{
1972 SelectAllParameters(true, false);
1973};
1974
1976{
1977 SelectAllParameters(false, false);
1978};
1979
1981{
1982 switch(e.GetKeyCode())
1983 {
1984 case WXK_INSERT:
1985 {
1986 wxCommandEvent ev(wxEVT_COMMAND_MENU_SELECTED, XRCID("action_add_images"));
1987 MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
1988 break;
1989 };
1990 case WXK_DELETE:
1991 {
1993 if(!imgs.empty())
1994 {
1995 // remove all marked images from cache
1996 for (auto& img : imgs)
1997 {
1998 ImageCache::getInstance().removeImage(m_pano->getImage(img).getFilename());
1999 };
2000 // now remove images from panorama object
2003 );
2004 };
2005 break;
2006 };
2007#if defined __WXMAC__
2008 case 'A':
2009 case 'a':
2010 // check for cmd+A -> select all
2011 if (e.GetExtraLong() == wxMOD_CMD)
2012 {
2013 SelectAll();
2014 };
2015 break;
2016#endif
2017 case 1: //Ctrl+A
2018 {
2019 SelectAll();
2020 break;
2021 }
2022 default:
2023 e.Skip();
2024 };
2025};
2026
2028{
2029 m_editOldString=GetItemText(e.GetItem(), e.GetInt());
2030 if(m_editOldString.IsEmpty())
2031 {
2032 e.Veto();
2033 }
2034 else
2035 {
2036 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
2037 if(data->IsGroup())
2038 {
2040 wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
2041 data=static_cast<ImagesTreeData*>(GetItemData(item));
2042 };
2043 m_editVal=m_pano->getImage(data->GetImgNr()).getVar(m_columnVector[e.GetInt()]);
2044 SetItemText(e.GetItem(), e.GetInt(), hugin_utils::doubleTowxString(m_editVal));
2045 e.Allow();
2046 };
2047};
2048
2050{
2051 if(e.IsEditCancelled())
2052 {
2053 //restore old string
2054 SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2055 Refresh();
2056 }
2057 else
2058 {
2059 double val;
2060 if(!hugin_utils::str2double(e.GetLabel(),val))
2061 {
2062 //restore old string
2063 SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2064 Refresh();
2065 e.Veto();
2066 }
2067 else
2068 {
2069 //only update if value was changed
2070 if(val!=m_editVal)
2071 {
2072 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
2073 if(data->IsGroup())
2074 {
2076 wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
2077 data=static_cast<ImagesTreeData*>(GetItemData(item));
2078 };
2079 HuginBase::UIntSet imgs;
2080 imgs.insert(data->GetImgNr());
2081 if(m_columnVector[e.GetInt()]=="v")
2082 {
2083 if(m_pano->getImage(data->GetImgNr()).getProjection()==HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC && val>190)
2084 {
2086 wxString::Format(_("You have given a field of view of %.2f degrees.\n But the orthographic projection is limited to a field of view of 180 degress.\nDo you want still use that high value?"), val),
2087 _("Hugin"), wxICON_EXCLAMATION | wxYES_NO, this) == wxNO)
2088 {
2089 //restore old string
2090 SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2091 Refresh();
2092 e.Veto();
2093 e.Skip();
2094 return;
2095 };
2096 };
2097 };
2098 HuginBase::Variable var(m_columnVector[e.GetInt()], val);
2100 new PanoCommand::SetVariableCmd(*m_pano, imgs, var)
2101 );
2102 //we need to veto the event otherwise the internal
2103 //function does update the text to the full number
2104 e.Veto();
2105 }
2106 else
2107 {
2108 //restore old string
2109 SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2110 Refresh();
2111 };
2112 };
2113 };
2114 e.Skip();
2115};
2116
2126
2128{
2129 if(!m_optimizerMode)
2130 {
2131 int flags;
2132 int col;
2133 wxTreeItemId item=HitTest(e.GetPosition(), flags, col);
2136 GetEventHandler()->AddPendingEvent(commandEvent);
2137 };
2138 e.Skip();
2139};
2140
2141IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrl, wxTreeListCtrl)
2142
2144 : wxTreeListCtrlXmlHandler()
2145{
2146}
2147
2149{
2151
2152 cp->Create(m_parentAsWindow,
2153 GetID(),
2154 GetPosition(), GetSize(),
2155 GetStyle("style"),
2156 GetName());
2157
2158 SetupWindow( cp);
2159
2160 return cp;
2161}
2162
2164{
2165 return IsOfClass(node, "ImagesTreeList");
2166}
2167
2168IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrlXmlHandler, wxTreeListCtrlXmlHandler)
2169
2170
GuiLevel
Definition GuiLevel.h:32
@ GUI_EXPERT
Definition GuiLevel.h:35
@ GUI_ADVANCED
Definition GuiLevel.h:34
@ GUI_SIMPLE
Definition GuiLevel.h:33
Definition of dialog to edit image variables.
Declare the ImageVariableGroup and ImageVariableGroupObserver classes.
#define ADDCOLUMN(header, mapName, width, align, isEditable, IVE, tooltip)
@ ID_SELECT_ALL
@ ID_ACTIVATE_IMAGE
@ ID_UNSELECT_ALL
@ ID_LINK
@ ID_UNSELECT_LENS_STACK
@ ID_DEACTIVATE_IMAGE
@ ID_SELECT_LENS_STACK
@ ID_EDIT
@ ID_UNLINK
@ ID_OPERATION_START
declaration of main image tree control
declaration of functions to handle stacks and layers
wxString getProjectionString(const HuginBase::SrcPanoImage &img)
Returns translated projection for given image.
wxString getResponseString(const HuginBase::SrcPanoImage &img)
Returns translated response type for given SrcPanoImage.
some helper classes for graphes
Somewhere to specify what variables belong to what.
HuginBase::UIntSet GetDragGroupImages()
void SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box=true)
@ RESPONSE_EMOR
empirical model of response
std::size_t getNumberOfParts() const
get the number of parts.
unsigned int getPartNumber(unsigned int imageNr) const
Get a part number from an image number.
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getLensVariables()
Get the set of lens image variables.
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getStackVariables()
Get the set of stack image variables.
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition Panorama.h:481
std::vector< unsigned int > getCtrlPointsForImage(unsigned int imgNr) const
return all control points for a given image.
Definition Panorama.cpp:83
void addObserver(PanoramaObserver *o)
add a panorama observer.
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
const OptimizeVector & getOptimizeVector() const
return the optimize settings stored inside panorama
Definition Panorama.h:454
UIntSet getActiveImages() const
get active images
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
ImageVariableGroup & getStacks()
Get the ImageVariableGroup representing the group of stack variables.
ImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
void update()
Update part numbers for each variable group.
a variable has a value and a name.
Dialog for editing image variables.
virtual wxObject * DoCreateResource()
virtual bool CanHandle(wxXmlNode *node)
the main images tree control, used on images and optimizer tabs
Definition ImagesTree.h:37
HuginBase::StandardImageVariableGroups * m_variable_groups
Definition ImagesTree.h:173
void OnExecuteOperation(wxCommandEvent &e)
menu event handler for PanoOperation (context menu items)
void UpdateItemFont()
update the font colour for all items
void OnMouseMove(wxMouseEvent &e)
event handler for mouse motion, handles focussing of check boxes
wxTreeItemId m_leftDownItem
stores where left mouse click happend
Definition ImagesTree.h:217
std::vector< HuginBase::ImageVariableGroup::ImageVariableEnum > m_variableVector
vector for easier access to linking information
Definition ImagesTree.h:194
void OnContextMenu(wxTreeEvent &e)
event handler to display context menu
void OnActivateImage(wxCommandEvent &e)
event handler for activate image
void OnBeginEdit(wxTreeEvent &e)
event handler for beginning editing
void GenerateSubMenu(wxMenu *menu, PanoOperation::PanoOperationVector *operations, int &id)
generates submenu for given PanoOperationVector
void UpdateGroupText(wxTreeItemId item)
updates the information fot the given lens/stack in the tree
void OnSelectLensStack(wxCommandEvent &e)
event handler for select all optimizer variables for selected lens/stack
void UpdateImageText(wxTreeItemId item)
updates the information for the given image in tree
void CreateCheckboxImages()
create image list with necessary images of checkboxes
void OnEditImageVariables(wxCommandEvent &e)
event handler for showing image variables editing dialog
long m_leftDownColumn
Definition ImagesTree.h:218
bool m_optimizerMode
true, if in optimizer mode
Definition ImagesTree.h:182
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
creates the control
void OnUnselectLensStack(wxCommandEvent &e)
event handler for unselect all optimizer variables for selected lens/stack
void OnBeginDrag(wxTreeEvent &e)
event handler when dragging begins, veto if dragging is not possible
wxTreeItemId m_lastCurrentItem
stores last item on which the mouse was hovering
Definition ImagesTree.h:214
bool m_needsUpdate
helper variable for update of output stacks/layers
Definition ImagesTree.h:208
virtual ~ImagesTreeCtrl(void)
destructor
HuginBase::Panorama * m_pano
Definition ImagesTree.h:168
void OnSelectAll(wxCommandEvent &e)
event handler for select all optimizer variables
HuginBase::UIntSet GetSelectedImages()
returns the selected images
void SelectAllParameters(bool select, bool allImages)
select/unselect all variables in the active column @select true selects all, false unselect all @allI...
void SetGuiLevel(GuiLevel newSetting)
sets the GuiLevel of the control
void OnLinkImageVariables(wxCommandEvent &e)
event handler for linking image variables
HuginBase::UIntSet m_editableColumns
set, which contains editable columns (all column which contains numeric image variables
Definition ImagesTree.h:192
void OnDeactivateImage(wxCommandEvent &e)
event handler for deactivate image
void Init(HuginBase::Panorama *pano)
initialization, connects all control with Panorama, register observer
std::map< std::string, size_t > m_columnMap
map for easier access to column information
Definition ImagesTree.h:188
void OnHeaderContextMenu(wxListEvent &e)
event handler for context menu on header
void OnColumnWidthChange(wxListEvent &e)
event handler, when column width was changed, save into wxConfig
void SetGroupMode(GroupMode newMode)
sets the group mode to given mode
GroupMode m_groupMode
the active group mode
Definition ImagesTree.h:170
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
receive the update signal and update display accordingly
void OnUnselectAll(wxCommandEvent &e)
event handler for unselect all optimizer variables
void SetOptimizerMode()
sets to control into optimizer mode
size_t m_selectedColumn
selected column
Definition ImagesTree.h:198
void OnUnlinkImageVariables(wxCommandEvent &e)
event handler for unlinking image variables
GroupMode
enumeration for grouping mode
Definition ImagesTree.h:41
void CreateColumns()
creates all columns and stores information in m_columnMap, m_columnVector, m_editableColumns and m_va...
void OnLeftDblClick(wxMouseEvent &e)
event handler for left double click
std::map< int, PanoOperation::PanoOperation * > m_menuOperation
map with current active context menu PanoOperation
Definition ImagesTree.h:196
wxString m_editOldString
wxString, as shown before editing started
Definition ImagesTree.h:206
void UnLinkImageVariables(bool linked)
helper procedure for link/unlink image variables
void OnLeftDown(wxMouseEvent &e)
event handler for left mouse down, handles toggle of optimizer variables
bool m_markDisabledImages
true, if disabled images should be marked with other font color
Definition ImagesTree.h:184
GuiLevel m_guiLevel
stores the active GuiLevel
Definition ImagesTree.h:180
long m_lastCurrentCol
Definition ImagesTree.h:215
void SetDisplayMode(DisplayMode newMode)
sets the display mode to given mode
void UpdateOptimizerVariables()
updates the display of the optimizer variables (set font)
bool m_dragging
true, if dragging
Definition ImagesTree.h:202
DisplayMode
enumeration for display mode, limits the displayed columns
Definition ImagesTree.h:50
@ DISPLAY_PHOTOMETRICS_LENSES
Definition ImagesTree.h:57
@ DISPLAY_PHOTOMETRICS_IMAGES
Definition ImagesTree.h:56
void OnLeftUp(wxMouseEvent &e)
event handler for left up, handles end of dragging and updates of optimizer variables states
HuginBase::UIntSet m_draggingImages
UIntSet of dragging images.
Definition ImagesTree.h:200
wxTreeItemId m_root
pointer to root item, not shown
Definition ImagesTree.h:211
virtual void panoramaChanged(HuginBase::Panorama &pano)
receives notification about panorama changes
double m_editVal
value, which is currently edited
Definition ImagesTree.h:204
void UpdateGroup(wxTreeItemId parent, const HuginBase::UIntSet imgs, HuginBase::UIntSet &changed)
updates the given group, updates number of images and the images itself
void OnDpiChanged(wxDPIChangedEvent &e)
event handler for updating dpi
void MarkActiveImages(const bool markActive)
sets the flag, if active/disabled image should be marked with different colour
void OnChar(wxTreeEvent &e)
event handler for key events
void OnEndEdit(wxTreeEvent &e)
event handler for ending editing, updates the Panorama with modified value
DisplayMode m_displayMode
the active display mode
Definition ImagesTree.h:186
ImagesTreeCtrl()
general constructor
wxString m_configClassName
Definition ImagesTree.h:221
std::vector< std::string > m_columnVector
vector for easier access to column information
Definition ImagesTree.h:190
const bool IsGroup() const
const long GetImgNr() const
void SetImgNr(long newImgNr)
const long GetGroupNr() const
ImagesTreeData(const long &nr)
static MainFrame * Get()
hack.. kind of a pseudo singleton...
GLPreviewFrame * getGLPreview()
Change the linking of some variables across parts of an ImageVariableGroup containing some specified ...
Switch the part number of an image.
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
static GlobalCmdHist & getInstance()
move image from position1 to position2
Make a new part in a ImageVariableGroup for a set of images, given the variables that make up the gro...
Base class for all panorama commands.
Definition Command.h:39
remove multiple images from a panorama
Definition PanoCommand.h:95
update a single variable, possibly for a group of images
updates the optimize vector, aka all variables which should be optimized
simple class that forward the drop to the mainframe
Definition MainFrame.h:62
base class for different PanoOperations derived classes should overwrite protected PanoOperation::Get...
virtual PanoCommand::PanoCommand * GetCommand(wxWindow *parent, HuginBase::Panorama &pano, HuginBase::UIntSet images, GuiLevel guiLevel)
returns the appropriate PanoCommand::PanoCommand to be inserted into GlobalCmdHistory,...
void SetItemText(const wxTreeItemId &item, const wxString &text)
wxTreeItemData * GetItemData(const wxTreeItemId &item) const
wxTreeItemId GetNext(const wxTreeItemId &item) const
size_t GetSelections(wxArrayTreeItemIds &) const
void AddColumn(const wxString &text, int width=DEFAULT_COL_WIDTH, int flag=wxALIGN_LEFT, int image=-1, bool shown=true, bool edit=false, const wxString &tooltip=wxEmptyString)
size_t GetChildrenCount(const wxTreeItemId &item, bool recursively=true)
bool IsSelected(const wxTreeItemId &item) const
wxTreeItemId AddRoot(const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void SetItemImage(const wxTreeItemId &item, int image, wxTreeItemIcon which=wxTreeItemIcon_Normal)
void Refresh(bool erase=TRUE, const wxRect *rect=NULL)
wxString GetItemText(const wxTreeItemId &item) const
wxTreeItemId AppendItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void SetColumnWidth(int column, int width)
void SetColumnEditable(int column, bool edit=true)
int GetColumnWidth(int column) const
void SetColumnShown(int column, bool shown=true)
void ExpandAll(const wxTreeItemId &item)
int GetItemImage(const wxTreeItemId &item, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
wxTreeItemId HitTest(const wxPoint &point)
void SetItemTextColour(const wxTreeItemId &item, const wxColour &colour)
void DeleteChildren(const wxTreeItemId &item)
void AssignImageList(wxImageList *imageList)
wxTreeItemId GetItemParent(const wxTreeItemId &item) const
wxTreeItemId GetFirstChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
void SetItemBold(const wxTreeItemId &item, bool bold=true)
void EndEdit(bool isCancelled)
void Delete(const wxTreeItemId &item)
wxTreeItemId GetLastChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
wxTreeItemId GetNextChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
static uint16_t flags
implementation of huginApp Class
#define HUGIN_CONV_FILENAME
Definition platform.h:40
#define DEBUG_ASSERT(cond)
Definition utils.h:80
#define DEBUG_TRACE(msg)
Definition utils.h:67
wxString GetIso(const HuginBase::SrcPanoImage *img)
returns formatted iso value
wxString GetFocalLength(const HuginBase::SrcPanoImage *img)
return focallength and focallength 35 mm as wxString
wxString GetExifDateTime(const HuginBase::SrcPanoImage *img)
returns Exif DateTimeOriginal as formatted wxString
wxString GetExposureTime(const HuginBase::SrcPanoImage *img)
returns formatted exposure time
wxString GetAperture(const HuginBase::SrcPanoImage *img)
returns formatted aperture value
std::vector< std::set< std::string > > OptimizeVector
std::vector< UIntSet > UIntSetVector
std::set< unsigned int > UIntSet
PanoOperationVector * GetStacksOperationVector()
returns list of PanoOperation for stacks
PanoOperationVector * GetImagesOperationVector()
returns list of PanoOperation for work with images
std::vector< PanoOperation * > PanoOperationVector
PanoOperationVector * GetControlPointsOperationVector()
returns list of PanoOperation for work with control points
PanoOperationVector * GetLensesOperationVector()
returns list of PanoOperation for work with lenses
PanoOperationVector * GetResetOperationVector()
returns list of PanoOperation for resetting
bool str2double(const wxString &s, double &d)
wxString doubleTowxString(double d, int digits)
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition wxutils.cpp:176
include file for the hugin project
include file for the hugin project
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition stl_utils.h:74
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition stl_utils.h:81
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41
platform/compiler specific stuff.