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

Generated on Tue Sep 16 01:25:39 2014 for Hugintrunk by  doxygen 1.3.9.1