Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImageVariableGroup.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
24 #include <hugin_utils/utils.h>
25 
26 #include "ImageVariableGroup.h"
27 
28 namespace HuginBase
29 {
30 
31 ConstImageVariableGroup::ConstImageVariableGroup(std::set<ImageVariableEnum> variables,
32  const PanoramaData & pano)
33  : m_variables (variables),
34  m_pano (pano)
35 {
36  // work out the initial image number to part number matching.
38 }
39 
41 {
42 }
43 
44 unsigned int ConstImageVariableGroup::getPartNumber(unsigned int imageNr) const
45 {
46  DEBUG_ASSERT(imageNr < m_image_part_numbers.size());
48  return m_image_part_numbers[imageNr];
49 }
50 
52 {
54  for (unsigned int imgNr = 0; imgNr<m_image_part_numbers.size(); ++imgNr)
55  {
56  result[m_image_part_numbers[imgNr]].insert(imgNr);
57  };
58  return result;
59 }
60 
61 bool ConstImageVariableGroup::getVarLinkedInPart(ImageVariableEnum variable,
62  std::size_t part) const
63 {
64  /* Variables can be linked in strange ways, but this ignores most of that.
65  * For the sake of the user interface, a variable should be linked across
66  * all images in the part, or not linked across any images in a part. This
67  * function returns true in the first case and false in the second, but is
68  * a bit weird about any other cases:
69  * If the first image in the part has links in this variable, true is
70  * returned.
71  * If the second image in the part has no links in this variable, false is
72  * returned.
73  * If there is only one image in this part, true is returned.
74  * This is just to make it fast. We could check explicitly for one of the
75  * cases above, but they are probably all that is used.
76  */
77 
78  // Have we found a unlinked image previously?
79  bool found_first = false;
80  switch (variable)
81  {
82 #define image_variable( name, type, default_value )\
83  case IVE_##name:\
84  for (std::size_t imageNr = 0; imageNr < m_pano.getNrOfImages(); imageNr++)\
85  {\
86  if (m_image_part_numbers[imageNr] == part)\
87  {\
88  if (!found_first)\
89  {\
90  found_first = true;\
91  if (m_pano.getImage(imageNr).name##isLinked())\
92  {\
93  return true;\
94  }\
95  } else {\
96  return false;\
97  }\
98  }\
99  }\
100  break;
101 #include "image_variables.h"
102 #undef image_variable
103  }
104  // only one image found:
105  return true;
106 }
107 
108 void ImageVariableGroup::unlinkVariablePart(ImageVariableEnum variable,
109  unsigned int partNr)
110 {
111  DEBUG_ASSERT(m_variables.find(variable) != m_variables.end());
112  // find all images in the requested part.
113  for (unsigned int i = 0; i < m_image_part_numbers.size(); i++)
114  {
115  if (m_image_part_numbers[i] == partNr)
116  {
117  // unlink the variable
118  switch (variable)
119  {
120 #define image_variable( name, type, default_value )\
121  case IVE_##name:\
122  m_pano.unlinkImageVariable##name(i);\
123  break;
124 #include "image_variables.h"
125 #undef image_variable
126  }
127  }
128  }
129  setPartNumbers();
130 }
131 
133  unsigned int imageNr)
134 {
135  unlinkVariablePart(variable, m_image_part_numbers[imageNr]);
136 }
137 
138 void ImageVariableGroup::linkVariablePart(ImageVariableEnum variable,
139  unsigned int partNr)
140 {
141  DEBUG_ASSERT(m_variables.find(variable) != m_variables.end());
142  // find all images in the requested part.
143  bool found_first_image = false;
144  int first_image_number;
145  for (unsigned int i = 0; i < m_image_part_numbers.size(); i++)
146  {
147  if (m_image_part_numbers[i] == partNr)
148  {
149  // make a note of the first image.
150  if (!found_first_image)
151  {
152  first_image_number = i;
153  found_first_image = true;
154  continue;
155  }
156  // for the other images, link the variable to the first image.
157  switch (variable)
158  {
159 #define image_variable( name, type, default_value )\
160  case IVE_##name:\
161  m_pano.linkImageVariable##name(first_image_number, i);\
162  break;
163 #include "image_variables.h"
164 #undef image_variable
165  }
166  }
167  }
168  setPartNumbers();
169 }
170 
172  unsigned int imageNr)
173 {
174  linkVariablePart(variable, m_image_part_numbers[imageNr]);
175 }
176 
177 void ImageVariableGroup::switchParts (unsigned int imageNr, unsigned int partNr)
178 {
179  if (partNr == m_image_part_numbers[imageNr])
180  {
181  // We're asked to switch an image to its own part, achieving nothing:
182  return;
183  }
184  DEBUG_TRACE("Switching image " << imageNr << " to part " << partNr);
185  if (partNr > m_num_parts)
186  {
187  DEBUG_ERROR( "Request to switch an image to a nonexistent part." );
188  return;
189  }
190  // find an image in this part.
191  unsigned int part_image_index;
192  for (part_image_index = 0; m_image_part_numbers[part_image_index] != partNr; part_image_index++);
193 
194  // Decide which variables to link.
195  // Find which variables are linked in the other image.
196  std::set<ImageVariableEnum> linked_variables;
197  for(std::set<ImageVariableEnum>::iterator i = m_variables.begin(); i != m_variables.end(); ++i)
198  {
199  switch (*i)
200  {
201 #define image_variable( name, type, default_value ) \
202  case IVE_##name: \
203  if(m_pano.getImage(part_image_index).name##isLinked())\
204  {\
205  linked_variables.insert(IVE_##name);\
206  }\
207  break;
208 #include "image_variables.h"
209 #undef image_variable
210  }
211  }
212 
213  // If none share links, link them all. The image must be the only one of its
214  // part.
215  bool singular = linked_variables.empty();
216  if (singular)
217  {
218  linked_variables = m_variables;
219  }
220 
221  // unlink the image from the part it originally was part off.
222  for(std::set<ImageVariableEnum>::iterator i = m_variables.begin(); i != m_variables.end(); ++i)
223  {
224  switch (*i)
225  {
226 #define image_variable( name, type, default_value ) \
227  case IVE_##name: \
228  m_pano.unlinkImageVariable##name(imageNr);\
229  break;
230 #include "image_variables.h"
231 #undef image_variable
232  }
233  }
234 
235  // link the variables
236  for(std::set<ImageVariableEnum>::iterator i = linked_variables.begin(); i != linked_variables.end(); ++i)
237  {
238  switch (*i)
239  {
240  /* part_image_index and imageNr must be different, since if they
241  * were the same, the image would have already been in the
242  * correct part. This was the first thing we checked.
243  */
244 #define image_variable( name, type, default_value ) \
245  case IVE_##name: \
246  m_pano.linkImageVariable##name(part_image_index, imageNr);\
247  break;
248 #include "image_variables.h"
249 #undef image_variable
250  }
251  }
252 
253  // Changing the links inherits variable values from the new lens, so the
254  // variable values may have changed and the linking certainly has.
255  m_pano.imageChanged(imageNr);
256 
257  // update the mapping of image numbers to part numbers.
258  setPartNumbers();
259 }
260 
262 {
263  return m_num_parts;
264 }
265 
267 {
268  setPartNumbers();
269 }
270 
272 {
273  DEBUG_TRACE("")
274  // Find links.
275  m_image_part_numbers.clear();
276  if (m_pano.getNrOfImages() == 0)
277  {
278  // no images.
279  m_num_parts = 0;
280  return;
281  }
282  /* We will keep a list of parts, containing the image number of the first
283  * image that uses that part. When we want to find if another image is in
284  * a part, we can then check if it is linked to any images in the list.
285  */
286  std::vector<std::size_t> parts_first_image;
287  // image 0 always has part 0
288  parts_first_image.push_back(0);
289  m_image_part_numbers.push_back(0);
290  for (std::size_t i = 1; i < m_pano.getNrOfImages(); i++)
291  {
292  // find a part for this image.
293  /* We use parts_first_image.size() as a flag to determine when the
294  * images is not linked to any part we have previously found, as it
295  * will be the part number when we are done. */
296  std::size_t part_number = parts_first_image.size();;
297  for (std::size_t j = 0; j < parts_first_image.size(); j++)
298  {
299  // check each variable in the group
300  for (std::set<ImageVariableEnum>::const_iterator k = m_variables.begin();
301  (k != m_variables.end()) && (part_number != j); ++k)
302  {
303  switch (*k)
304  {
308 #define image_variable( name, type, default_value ) \
309  case IVE_##name:\
310  if (m_pano.getImage(i).name##isLinkedWith(m_pano.getImage(parts_first_image[j]))) \
311  part_number = j;\
312  break;
313 #include "image_variables.h"
314 #undef image_variable
315  }
316  }
317  }
318  // We should have a suitable part number for now.
319  m_image_part_numbers.push_back(part_number);
320  // If this is a new part, keep this image number to check links.
321  if (part_number == parts_first_image.size())
322  {
323  parts_first_image.push_back(i);
324  }
325  }
326  // set the number of parts
327  m_num_parts = parts_first_image.size();
328 
329 }
330 
331 } // HuginBase namespace
std::set< ImageVariableEnum > m_variables
The set of variables which make up this group.
bool getVarLinkedInPart(ImageVariableEnum variable, std::size_t part) const
Get the linked status of a particular variable for a given part number.
void linkVariableImage(ImageVariableEnum variable, unsigned int imageNr)
link one of the variables across a part containing a given image
std::vector< UIntSet > UIntSetVector
Definition: PanoramaData.h:56
const PanoramaData & m_pano
The panorama this group works on.
unsigned int getPartNumber(unsigned int imageNr) const
Get a part number from an image number.
#define DEBUG_TRACE(msg)
Definition: utils.h:67
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
Declare the ImageVariableGroup and ImageVariableGroupObserver classes.
void linkVariablePart(ImageVariableEnum variable, unsigned int partNr)
link one of the variables across a given part
virtual ~ConstImageVariableGroup()
destructor
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
ConstImageVariableGroup(std::set< ImageVariableEnum > variables, const PanoramaData &pano)
constructor
Model for a panorama.
Definition: PanoramaData.h:81
void unlinkVariablePart(ImageVariableEnum variable, unsigned int partNr)
unlink one of the variables across a given part.
std::vector< unsigned int > m_image_part_numbers
The part numbers for each image.
#define DEBUG_ERROR(msg)
Definition: utils.h:76
void setPartNumbers()
Set the part numbers in m_image_part_numbers, and notify observers of changes.
void unlinkVariableImage(ImageVariableEnum variable, unsigned int imageNr)
unlink one the variables across the part containing a given image.
void updatePartNumbers()
Update the part numbers, call this when the panorama changes.
virtual void imageChanged(unsigned int imgNr)=0
mark image change for maintainance
virtual std::size_t getNrOfImages() const =0
number of images.
std::size_t getNumberOfParts() const
get the number of parts.
void switchParts(unsigned int ImageNr, unsigned int partNr)
switch a given image to a different part number.
This file specifies what image variables SrcPanoImg should have.