ImageVariableGroup.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00024 #include <hugin_utils/utils.h>
00025 
00026 #include "ImageVariableGroup.h"
00027 
00028 namespace HuginBase
00029 {
00030 
00031 ConstImageVariableGroup::ConstImageVariableGroup(std::set<ImageVariableEnum> variables,
00032                                                  const PanoramaData & pano)
00033     : m_variables (variables),
00034       m_pano (pano)
00035 {
00036     // work out the initial image number to part number matching.
00037     setPartNumbers();
00038 }
00039 
00040 ConstImageVariableGroup::~ConstImageVariableGroup()
00041 {
00042 }
00043 
00044 unsigned int ConstImageVariableGroup::getPartNumber(unsigned int imageNr) const
00045 {
00046     DEBUG_ASSERT(imageNr < m_image_part_numbers.size());
00047     DEBUG_ASSERT(m_image_part_numbers.size() == m_pano.getNrOfImages());
00048     return m_image_part_numbers[imageNr];
00049 }
00050 
00051 UIntSetVector ConstImageVariableGroup::getPartsSet() const
00052 {
00053     UIntSetVector result(getNumberOfParts(), HuginBase::UIntSet());
00054     for (unsigned int imgNr = 0; imgNr<m_image_part_numbers.size(); ++imgNr)
00055     {
00056         result[m_image_part_numbers[imgNr]].insert(imgNr);
00057     };
00058     return result;
00059 }
00060 
00061 bool ConstImageVariableGroup::getVarLinkedInPart(ImageVariableEnum variable,
00062                                                  std::size_t part) const
00063 {
00064     /* Variables can be linked in strange ways, but this ignores most of that.
00065      * For the sake of the user interface, a variable should be linked across
00066      * all images in the part, or not linked across any images in a part. This
00067      * function returns true in the first case and false in the second, but is
00068      * a bit weird about any other cases:
00069      * If the first image in the part has links in this variable, true is
00070      * returned.
00071      * If the second image in the part has no links in this variable, false is
00072      * returned.
00073      * If there is only one image in this part, true is returned.
00074      * This is just to make it fast. We could check explicitly for one of the
00075      * cases above, but they are probably all that is used.
00076      */
00077     
00078     // Have we found a unlinked image previously?
00079     bool found_first = false;
00080     switch (variable)
00081     {
00082 #define image_variable( name, type, default_value )\
00083         case IVE_##name:\
00084             for (std::size_t imageNr = 0; imageNr < m_pano.getNrOfImages(); imageNr++)\
00085             {\
00086                 if (m_image_part_numbers[imageNr] == part)\
00087                 {\
00088                     if (!found_first)\
00089                     {\
00090                         found_first = true;\
00091                         if (m_pano.getImage(imageNr).name##isLinked())\
00092                         {\
00093                             return true;\
00094                         }\
00095                     } else {\
00096                         return false;\
00097                     }\
00098                 }\
00099             }\
00100             break;
00101 #include "image_variables.h"
00102 #undef image_variable
00103     }
00104     // only one image found:
00105     return true;
00106 }
00107 
00108 void ImageVariableGroup::unlinkVariablePart(ImageVariableEnum variable,
00109                                             unsigned int partNr)
00110 {
00111     DEBUG_ASSERT(m_variables.find(variable) != m_variables.end());
00112     // find all images in the requested part.
00113     for (unsigned int i = 0; i < m_image_part_numbers.size(); i++)
00114     {
00115         if (m_image_part_numbers[i] == partNr)
00116         {
00117             // unlink the variable
00118             switch (variable)
00119             {
00120 #define image_variable( name, type, default_value )\
00121                 case IVE_##name:\
00122                     m_pano.unlinkImageVariable##name(i);\
00123                     break;
00124 #include "image_variables.h"
00125 #undef image_variable
00126             }
00127         }
00128     }
00129     setPartNumbers();
00130 }
00131 
00132 void ImageVariableGroup::unlinkVariableImage(ImageVariableEnum variable,
00133                                              unsigned int imageNr)
00134 {
00135     unlinkVariablePart(variable, m_image_part_numbers[imageNr]);
00136 }
00137 
00138 void ImageVariableGroup::linkVariablePart(ImageVariableEnum variable,
00139                                           unsigned int partNr)
00140 {
00141     DEBUG_ASSERT(m_variables.find(variable) != m_variables.end());
00142     // find all images in the requested part.
00143     bool found_first_image = false;
00144     int first_image_number;
00145     for (unsigned int i = 0; i < m_image_part_numbers.size(); i++)
00146     {
00147         if (m_image_part_numbers[i] == partNr)
00148         {
00149             // make a note of the first image.
00150             if (!found_first_image)
00151             {
00152                 first_image_number = i;
00153                 found_first_image = true;
00154                 continue;
00155             }
00156             // for the other images, link the variable to the first image.
00157             switch (variable)
00158             {
00159 #define image_variable( name, type, default_value )\
00160                 case IVE_##name:\
00161                     m_pano.linkImageVariable##name(first_image_number, i);\
00162                     break;
00163 #include "image_variables.h"
00164 #undef image_variable
00165             }
00166         }
00167     }
00168     setPartNumbers(); 
00169 }
00170 
00171 void ImageVariableGroup::linkVariableImage(ImageVariableEnum variable,
00172                                            unsigned int imageNr)
00173 {
00174     linkVariablePart(variable, m_image_part_numbers[imageNr]);
00175 }
00176 
00177 void ImageVariableGroup::switchParts (unsigned int imageNr, unsigned int partNr)
00178 {
00179     if (partNr == m_image_part_numbers[imageNr])
00180     {
00181         // We're asked to switch an image to its own part, achieving nothing:
00182         return;
00183     }
00184     DEBUG_TRACE("Switching image " << imageNr << " to part " << partNr);
00185     if (partNr > m_num_parts)
00186     {
00187         DEBUG_ERROR( "Request to switch an image to a nonexistant part." );
00188         return;
00189     }
00190     // find an image in this part.
00191     unsigned int part_image_index;
00192     for (part_image_index = 0; m_image_part_numbers[part_image_index] != partNr; part_image_index++);
00193     
00194     // Decide which variables to link.
00195     // Find which variables are linked in the other image.
00196     std::set<ImageVariableEnum> linked_variables;
00197     for(std::set<ImageVariableEnum>::iterator i = m_variables.begin(); i != m_variables.end(); ++i)
00198     {
00199         switch (*i)
00200         {
00201 #define image_variable( name, type, default_value ) \
00202             case IVE_##name: \
00203                 if(m_pano.getImage(part_image_index).name##isLinked())\
00204                 {\
00205                     linked_variables.insert(IVE_##name);\
00206                 }\
00207             break;
00208 #include "image_variables.h"
00209 #undef image_variable
00210         }
00211     }
00212     
00213     // If none share links, link them all. The image must be the only one of its
00214     // part.
00215     bool singular = linked_variables.empty();
00216     if (singular)
00217     {
00218         linked_variables = m_variables;
00219     }
00220     
00221     // unlink the image from the part it originally was part off.
00222     for(std::set<ImageVariableEnum>::iterator i = m_variables.begin(); i != m_variables.end(); ++i)
00223     {
00224         switch (*i)
00225         {
00226 #define image_variable( name, type, default_value ) \
00227             case IVE_##name: \
00228                 m_pano.unlinkImageVariable##name(imageNr);\
00229                 break;
00230 #include "image_variables.h"
00231 #undef image_variable
00232         }
00233     }
00234     
00235     // link the variables
00236     for(std::set<ImageVariableEnum>::iterator i = linked_variables.begin(); i != linked_variables.end(); ++i)
00237     {
00238         switch (*i)
00239         {
00240             /* part_image_index and imageNr must be different, since if they
00241              * were the same, the image would have already been in the
00242              * correct part. This was the first thing we checked.
00243              */
00244 #define image_variable( name, type, default_value ) \
00245             case IVE_##name: \
00246                 m_pano.linkImageVariable##name(part_image_index, imageNr);\
00247                 break;
00248 #include "image_variables.h"
00249 #undef image_variable
00250         }
00251     }
00252     
00253     // Changing the links inherits variable values from the new lens, so the
00254     // variable values may have changed and the linking certainly has.
00255     m_pano.imageChanged(imageNr);
00256     
00257     // update the mapping of image numbers to part numbers.
00258     setPartNumbers();
00259 }
00260 
00261 std::size_t ConstImageVariableGroup::getNumberOfParts() const
00262 {
00263     return m_num_parts;
00264 }
00265 
00266 void ConstImageVariableGroup::updatePartNumbers()
00267 {
00268     setPartNumbers();
00269 }
00270 
00271 void ConstImageVariableGroup::setPartNumbers()
00272 {
00273     DEBUG_TRACE("")
00274     // Find links.
00275     m_image_part_numbers.clear();
00276     if (m_pano.getNrOfImages() == 0)
00277     {
00278         // no images.
00279         m_num_parts = 0;
00280         return;
00281     }
00282     /* We will keep a list of parts, containing the image number of the first
00283      * image that uses that part. When we want to find if another image is in
00284      * a part, we can then check if it is linked to any images in the list.
00285      */
00286     std::vector<std::size_t> parts_first_image;
00287     // image 0 always has part 0
00288     parts_first_image.push_back(0);
00289     m_image_part_numbers.push_back(0);
00290     for (std::size_t i = 1; i < m_pano.getNrOfImages(); i++)
00291     {
00292         // find a part for this image.
00293         /* We use parts_first_image.size() as a flag to determine when the
00294          * images is not linked to any part we have previously found, as it
00295          * will be the part number when we are done. */
00296         std::size_t part_number = parts_first_image.size();;
00297         for (std::size_t j = 0; j < parts_first_image.size(); j++)
00298         {
00299             // check each variable in the group
00300             for (std::set<ImageVariableEnum>::const_iterator k = m_variables.begin();
00301                  (k != m_variables.end()) && (part_number != j); ++k)
00302             {
00303                 switch (*k)
00304                 {
00308 #define image_variable( name, type, default_value ) \
00309                     case IVE_##name:\
00310                         if (m_pano.getImage(i).name##isLinkedWith(m_pano.getImage(parts_first_image[j]))) \
00311                             part_number = j;\
00312                         break;
00313 #include "image_variables.h"
00314 #undef image_variable
00315                 }
00316             }
00317         }
00318         // We should have a suitable part number for now.
00319         m_image_part_numbers.push_back(part_number);
00320         // If this is a new part, keep this image number to check links.
00321         if (part_number == parts_first_image.size())
00322         {
00323             parts_first_image.push_back(i);
00324         }
00325     }
00326     // set the number of parts
00327     m_num_parts = parts_first_image.size();
00328     
00329 }
00330 
00331 } // HuginBase namespace

Generated on 1 Aug 2015 for Hugintrunk by  doxygen 1.4.7