Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PreviewLayoutLinesTool.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
22 #include "panoinc_WX.h"
23 #include "panoinc.h"
24 
25 #include "PreviewLayoutLinesTool.h"
26 #include "hugin_config.h"
27 
28 #include "base_wx/platform.h"
29 #include "MainFrame.h"
30 #include "GreatCircles.h"
31 
32 #include <wx/platform.h>
33 #ifdef __WXMAC__
34 #include <OpenGL/gl.h>
35 #include <OpenGL/glu.h>
36 #else
37 #include <GL/gl.h>
38 #include <GL/glu.h>
39 #endif
40 
41 #include <cfloat>
42 #include <cmath>
43 
44 // the size of the rectangular texture. Must be a power of two, and at least 8.
45 #define rect_ts 64
46 
47 // The resolution to use to sample overlaps.
48 /* The time it takes to sample it is a multiple of this squared + a constant.
49  * So keep it low to make the redraws faster, set it higher to make the grey
50  * lines' appearence more accurate. Make sure to adjust MIN_SAMPLE_OVERLAPS
51  * below to keep the proportion that need to overlap the same.
52  */
53 #define SAMPLE_FREQUENCY 12
54 
55 /* The amount of samples that are required to be within the other image for it
56  * to count as a large enough overlap to warrent a grey line. It is affected by
57  * the SAMPLE_FREQUENCY. An image with SAMPLE_FREQUENCY squared overlaps is
58  * entirely within the other image. Must be > 0.
59  *
60  * 12*12 = 144 samples. 16 / 144 = 1/9, so a 9th of the image must overlap for
61  * the grey line to appear. If just the corners overlap, the overlap must be a
62  * third in both directions:
63  * |||
64  * |||
65  * ||$SS
66  * SSS
67  * SSS
68  */
69 #define MIN_SAMPLE_OVERLAPS 16
70 
72 class PosMap
73 {
74 public:
76  hugin_utils::FDiff2D * operator[](std::size_t index)
77  {
78  return data[index];
79  }
80 };
81 
83  : Tool(helper),
84  m_holdOnNear(false),
85  m_updateStatistics(true),
86  m_nearestLine(-1),
87  m_useNearestLine(false)
88 {
89  helper->GetPanoramaPtr()->addObserver(this);
90  // make the textures. We have a circle border and a square one.
91  // the textures are white with a the alpha chanel forming a border.
92  glGenTextures(1, (GLuint*) &m_rectangleBorderTex);
93  // we only want to specify alpha, but using just alpha in opengl attaches 0
94  // for the luminosity. I tried biasing the red green and blue values to get
95  // them to 1.0, but it didn't work under OS X for some reason. Instead we
96  // use a luminance alpha pair, and use 1.0 for luminance all the time.
97 
98  // In the rectangle texture, the middle is 1/8 opaque, the outer pixels
99  // are completely transparent, and one pixel in from the edges is
100  // a completly opaque line.
101  GLubyte rect_tex_data[rect_ts][rect_ts][2];
102  // make everything white
103  for (unsigned int x = 0; x < rect_ts; x++)
104  {
105  for (unsigned int y = 0; y < rect_ts; y++)
106  {
107  rect_tex_data[x][y][0] = 255;
108  }
109  }
110  // now set the middle of the mask semi transparent
111  for (unsigned int x = 2; x < rect_ts - 2; x++)
112  {
113  for (unsigned int y = 2; y < rect_ts - 2; y++)
114  {
115  rect_tex_data[x][y][1] = 31;
116  }
117  }
118  // make an opaque border
119  for (unsigned int d = 1; d < rect_ts - 1; d++)
120  {
121  rect_tex_data[d][1][1] = 255;
122  rect_tex_data[d][rect_ts - 2][1] = 255;
123  rect_tex_data[1][d][1] = 255;
124  rect_tex_data[rect_ts - 2][d][1] = 255;
125  }
126  // make a transparent border around that
127  for (unsigned int d = 0; d < rect_ts; d++)
128  {
129  rect_tex_data[d][0][1] = 0;
130  rect_tex_data[d][rect_ts - 1][1] = 0;
131  rect_tex_data[0][d][1] = 0;
132  rect_tex_data[rect_ts - 1][d][1] = 0;
133  }
134  glBindTexture(GL_TEXTURE_2D, m_rectangleBorderTex);
135  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, rect_ts, rect_ts,
136  GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, rect_tex_data);
137  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
138  GL_LINEAR_MIPMAP_LINEAR);
139  // clamp texture so it won't wrap over the border of the cropped region.
140  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
141  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
142 }
144 {
145  // free the textures
146  glDeleteTextures(1, (GLuint*) &m_rectangleBorderTex);
147 
148  // delete all the transforms.
149  while (!m_transforms.empty())
150  {
151  delete m_transforms.back();
152  m_transforms.pop_back();
153  }
154 
155  // stop observing the panorama
157 }
158 
160 {
161  m_updateStatistics = true;
162 }
164  const HuginBase::UIntSet&)
165 {
166  m_updateStatistics = true;
167 }
168 
170 {
171  // register notifications
176 
177  helper->SetStatusMessage(_("Click a connection to edit control points."));
178 }
179 
180 void PreviewLayoutLinesTool::MouseMoveEvent(double x, double y, wxMouseEvent & e)
181 {
182 
183  // Try to find the nearest line to the mouse pointer.
184  // ...Unless there are no lines.
185  if (m_lines.empty())
186  {
187  return;
188  }
189 
190  if (!(helper->IsMouseOverPano())) {
191  if (m_useNearestLine) {
192  m_useNearestLine = false;
195  }
196  return;
197  }
198 
199  if (e.Dragging() && !m_holdOnNear) {
200  return;
201  }
202 
203  // Check each line in turn.
204  double minDistance = DBL_MAX;
205  unsigned int nearestLineOld = m_nearestLine;
206  for (unsigned int i = 0; i < m_lines.size(); i++)
207  {
208  if (m_lines[i].dud) continue;
209  double lineDistance = m_lines[i].getDistance(helper->GetMousePanoPosition());
210  if (lineDistance < minDistance)
211  {
212  // found a new minimum.
213  minDistance = lineDistance;
214  m_nearestLine = i;
215  }
216  }
217 
218  // Work out if it is close enough to highlight it.
219  bool oldUseNearestLine = m_useNearestLine;
220  // The limit is 70 pixels from the line.
221  // Coordinates are panorama pixels squared, so we'll need to scale it.
222  double scale = helper->GetVisualizationStatePtr()->GetScale();
223  scale *= scale;
224  m_useNearestLine = minDistance < 4900.0 / scale;
225 
226  if (oldUseNearestLine != m_useNearestLine || m_nearestLine != nearestLineOld)
227  {
229  // get notification of when the connected images are drawn so we can
230  // draw them on top with a highlight.
231  helper->NotifyMeBeforeDrawing(line.image1, this);
232  helper->NotifyMeBeforeDrawing(line.image2, this);
233 
234  // Redraw with new indicators. Since the indicators aren't part of the
235  // panorama, we have to persuade the viewstate that a redraw is required.
238  }
239 }
240 
242 {
243  // We should check if the lines or image centers have changed.
244  if (m_updateStatistics)
245  {
246  m_updateStatistics = false;
247  // Must be done in this order since the transforms updateImageCentres
248  // uses are also used by updateLineInformation.
251 
252  if (m_nearestLine >= m_lines.size())
253  {
254  // The line we had selected no longer exists. Use the first line
255  // until the mouse moves again.
256  m_nearestLine = 0;
257  }
258  }
259 
260  // now draw each line.
261  glEnable(GL_LINE_SMOOTH);
262  helper->GetViewStatePtr()->GetTextureManager()->DisableTexture();// for (unsigned int i = 0; i < m_lines.size(); i++)
263  for (unsigned int i = 0; i < m_lines.size(); i++)
264  {
265  m_lines[i].draw(m_useNearestLine && i == m_nearestLine);
266  }
267  glDisable(GL_LINE_SMOOTH);
268  glEnable(GL_TEXTURE_2D);
269  // reset some openGL state back to its normal value.
270  glColor3ub(255, 255, 255);
271  glLineWidth(1.0);
272 }
273 
275 {
276  // we draw the partly transparent identification boxes over the top of the
277  // two images connecting the nearest line to the mouse pointer.
278 
279  // If there are no lines, there isn't a nearest one. Also check if we use it
280  if (m_lines.empty() || !m_useNearestLine) return;
281 
282  // draw the actual images
283  unsigned int image1 = m_lines[m_nearestLine].image1;
284  unsigned int image2 = m_lines[m_nearestLine].image2;
289 
290  // Setup OpenGL blending state for identification borders.
291  glEnable(GL_BLEND);
292  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
293  // use the border texture.
295  glBindTexture(GL_TEXTURE_2D, m_rectangleBorderTex);
296  // We use the texture matrix to align the texture with the cropping region.
297  glMatrixMode(GL_TEXTURE);
298 
299  // now draw the identification boxes
300  drawIdentificationBorder(image1);
301  drawIdentificationBorder(image2);
302 
303  // set OpenGL state back how we found it.
304  glMatrixMode(GL_MODELVIEW);
305  glDisable(GL_BLEND);
306 }
307 
309 {
310  // we want to shift the texture so it lines up with the cropped region.
311  glPushMatrix();
312  const HuginBase::SrcPanoImage & src = *(helper->GetViewStatePtr()->
313  GetSrcImage(image));
314  int width = src.getSize().width(), height = src.getSize().height();
315  vigra::Rect2D crop_region = src.getCropRect();
316  // pick a texture depending on crop mode and move it to the cropped area
317  switch (src.getCropMode())
318  {
321  // get the biggest rectangle contained by both the image and the
322  // cropped area.
323  crop_region &= vigra::Rect2D(src.getSize());
324  glScalef((float) width / (float) crop_region.width(),
325  (float) height / (float) crop_region.height(),
326  1.0);
327  glTranslatef(-(float) crop_region.left() / (float) width,
328  -(float) crop_region.top() / (float) height,
329  0.0);
330  break;
332  break;
333  }
334  // draw the image with the border texture.
335  glMatrixMode(GL_MODELVIEW);
336  glCallList(helper->GetVisualizationStatePtr()->GetMeshDisplayList(image));
337  glMatrixMode(GL_TEXTURE);
338  // reset the texture matrix.
339  glPopMatrix();
340 }
341 
343 {
344  if (m_lines.empty() || !m_useNearestLine)
345  {
346  // there are no lines, so none should be highlighted, therefore every
347  // image must be drawn. Don't notify us any longer and draw the image.
348  helper->DoNotNotifyMeBeforeDrawing(image, this);
349  return true;
350  }
351  // Delay drawing of images, so we can show them on top of the others.
353  if (image == line.image1 || image == line.image2) return false;
354  // We must be done with this event, so don't notify us any longer:
355  helper->DoNotNotifyMeBeforeDrawing(image, this);
356  return true;
357 }
358 
360 {
361  // If it was a left click and we have at least one line, bring up the images
362  // in that line in the control point editor.
363  if ( e.LeftDown() && !m_lines.empty() && m_useNearestLine)
364  {
365  m_holdOnNear = true;
366  }
367 
368  if (m_holdOnNear && e.LeftUp() && m_useNearestLine) {
369  m_holdOnNear = false;
372  MainFrame::Get()->Raise();
373  }
374 
375  if (m_useNearestLine && e.LeftUp()) {
376  m_useNearestLine = false;
377  }
378 }
379 
381 {
382  m_lines.clear();
383  const HuginBase::Panorama & pano = *(helper->GetPanoramaPtr());
384  unsigned int numberOfImages = pano.getNrOfImages();
385  HuginBase::UIntSet active_images = pano.getActiveImages();
386  // make a line for every image pair, but set the unneeded ones as dud.
387  // This is for constant look up times when we scan control points.
388  m_lines.resize(numberOfImages * numberOfImages);
389  unsigned int numberOfControlPoints = pano.getNrOfCtrlPoints();
390  // loop over all control points to count them and get error statistics.
391  for (unsigned int cpi = 0 ; cpi < numberOfControlPoints ; cpi++)
392  {
393  const HuginBase::ControlPoint & cp = pano.getCtrlPoint(cpi);
394  unsigned int low_index, high_index;
395  if (cp.image1Nr < cp.image2Nr)
396  {
397  low_index = cp.image1Nr;
398  high_index = cp.image2Nr;
399  } else {
400  low_index = cp.image2Nr;
401  high_index = cp.image1Nr;
402  }
403  // find the line.
404  // We use the formula in the line below to record image numbers to each
405  // line later.
406  LineDetails & line = m_lines[low_index * numberOfImages + high_index];
407  // update control point count.
408  line.numberOfControlPoints++;
409  // update error statistics
410  line.totalError += cp.error;
411  if (cp.error > line.worstError)
412  {
413  line.worstError = cp.error;
414  }
415  }
416 
417  /* Find some locations of the images. We will test if they overlap using
418  * these locations. We don't need the last image as we can always take the
419  * smallest numbered image as the source of points.
420  */
427  std::vector<PosMap> positions(pano.getNrOfImages() - 1);
428  for (unsigned int i = 0; i < numberOfImages - 1; i++)
429  {
430  const HuginBase::SrcPanoImage & img = pano.getImage(i);
431  for (unsigned int x = 0; x < SAMPLE_FREQUENCY; x++)
432  {
433  for (unsigned int y = 0; y < SAMPLE_FREQUENCY; y++)
434  {
435  // scale (x, y) so it is always within the cropped region of the
436  // image.
437  vigra::Rect2D c = img.getCropRect();
441  double xc = double (x) / double (SAMPLE_FREQUENCY)
442  * double(c.width()) + c.left();
443  double yc = double (y) / double (SAMPLE_FREQUENCY)
444  * double(c.height()) + c.top();
445  // now look up (xc, yc) in the image, find where in the panorama
446  // it ends up.
447  m_transforms[i]->transformImgCoord (
448  positions[i][x][y].x, positions[i][x][y].y,
449  xc, yc );
450  }
451  }
452  }
453 
454  // write other line data.
455  for (unsigned int i = 0; i < numberOfImages; i++)
456  {
457  for (unsigned int j = 0; j < numberOfImages; j++)
458  {
459  LineDetails & line = m_lines[i * numberOfImages + j];
460  line.image1 = i;
461  line.image2 = j;
463  if (!(set_contains(active_images, i) &&
464  set_contains(active_images, j)))
465  {
466  // At least one of the images is hidden, so don't show the line.
467  line.dud = true;
468  }
469  else if (line.numberOfControlPoints > 0)
470  {
471  line.dud = false;
472  } else if (i >= j) {
473  // We only use lines where image1 is the lowest numbered image.
474  // We don't bother with lines from one image to the same one.
475  line.dud = true;
476  } else {
477  // test overlapping regions.
479  ViewState & viewState = *helper->GetViewStatePtr();
480  HuginBase::SrcPanoImage & src = *viewState.GetSrcImage(j);
481  transform.createTransform(src, *(viewState.GetOptions()));
482  unsigned int overlapingSamples = 0;
483  for (unsigned int x = 0; x < SAMPLE_FREQUENCY; x++)
484  {
485  for (unsigned int y = 0; y < SAMPLE_FREQUENCY; y++)
486  {
487  // check if mapping a point that was found earilier to
488  // be inside an image in panorama space is inside the
489  // other image when transformed from panorama to image.
490  double dx, dy;
491  transform.transformImgCoord (
492  dx, dy,
493  positions[i][x][y].x,
494  positions[i][x][y].y
495  );
496  if (src.isInside(vigra::Point2D((int) dx, (int) dy)))
497  {
498  // they overlap
499  overlapingSamples++;
500  }
501  }
502  }
503  // If the overlap isn't big enough, the line isn't used.
504  line.dud = (overlapingSamples < MIN_SAMPLE_OVERLAPS);
505  }
506 
507  if (!line.dud)
508  {
514  }
515  }
516  }
517 }
518 
520 {
521  unsigned int numberOfImages = helper->GetPanoramaPtr()->getNrOfImages();
522  // The transforms have no copy constructor, so we can't have a direct vector
523  // and use resize. Instead we have a vector of pointers and we create and
524  // delete transforms as they are needed.
525  while (m_transforms.size() > numberOfImages)
526  {
527  delete m_transforms.back();
528  m_transforms.pop_back();
529  }
530  m_transforms.reserve(numberOfImages);
531  while (m_transforms.size() < numberOfImages)
532  {
534  }
537 
538  HuginBase::PanoramaOptions spherical_pano_opts;
540  spherical_pano_opts.setWidth(360);
541  spherical_pano_opts.setHeight(180);
542  spherical_pano_opts.setHFOV(360);
543 
544  for (unsigned int image_number = 0;
545  image_number < helper->GetPanoramaPtr()->getNrOfImages();
546  image_number++)
547  {
548  // transforming image coordinates to panorama coordinates.
549  m_transforms[image_number]->createInvTransform (
550  *(helper->GetViewStatePtr()->GetSrcImage(image_number)),
552  );
553  HuginBase::PTools::Transform to_spherical;
554  to_spherical.createInvTransform (
555  *(helper->GetViewStatePtr()->GetSrcImage(image_number)),
556  spherical_pano_opts
557  );
558  const vigra::Size2D & s = helper->GetViewStatePtr()->GetSrcImage(image_number)->getSize();
559  // find where the middle of the image maps to.
560  m_transforms[image_number]->transformImgCoord (
561  m_imageCentres[image_number].x,
562  m_imageCentres[image_number].y,
563  double(s.x) / 2.0, double(s.y) / 2.0
564  );
565  to_spherical.transformImgCoord(
566  m_imageCentresSpherical[image_number].x,
567  m_imageCentresSpherical[image_number].y,
568  double(s.x) / 2.0, double(s.y) / 2.0
569  );
570  }
571 }
572 
574 {
575  if (dud)
576  {
577  // The line isn't real, don't draw it.
578  return;
579  }
580  // work out the colour
581  if (highlight)
582  {
583  glColor3ub(255, 255, 255);
584  } else if (numberOfControlPoints == 0) {
585  // no control points, use a grey line
586  glColor3ub(170, 170, 170);
587  }else {
588  double red, green, blue;
590  glColor3d(red, green, blue);
591  }
592 
593  double lineWidth = numberOfControlPoints / 5.0 + 1.0;
594  if (lineWidth > 5.0) lineWidth = 5.0;
595 // glLineWidth(lineWidth);
596 
597  arc.draw(false, lineWidth);
598 }
599 
601  : numberOfControlPoints(0),
602  worstError(0),
603  totalError(0)
604 {
605 
606 }
607 
609 {
610  if (dud)
611  {
612  // This isn't a real line, so return the maximum distance to it possible.
613  return FLT_MAX;
614  }
615  else
616  {
617  return arc.squareDistance(point);
618  }
619 }
620 
implementation of huginApp Class
hugin_utils::FDiff2D GetMousePanoPosition()
Definition: ToolHelper.cpp:295
void MouseButtonEvent(wxMouseEvent &e)
Capture clicks on lines, and load up the relavent images in the control point tab.
A class to store information about each line that will be drawn.
double totalError
the total of all the control point errors between these images
ViewState * GetViewStatePtr()
Definition: ToolHelper.cpp:305
void setHeight(unsigned int h)
set panorama height
unsigned int m_rectangleBorderTex
OpenGL texture names for the border highlight.
void NotifyMeBeforeDrawing(unsigned int image_nr, Tool *tool)
Definition: ToolHelper.cpp:349
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
HuginBase::Panorama * GetPanoramaPtr()
Definition: ToolHelper.cpp:310
#define MIN_SAMPLE_OVERLAPS
hugin_utils::FDiff2D data[SAMPLE_FREQUENCY][SAMPLE_FREQUENCY]
unsigned int image1
index of images for this line
void DisableTexture(bool maskOnly=false)
bool m_useNearestLine
True if we should highlight the nearest line to the mouse position.
PreviewLayoutLinesTool(ToolHelper *helper)
std::size_t getNrOfCtrlPoints() const
number of control points
Definition: Panorama.h:306
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
bool BeforeDrawImageEvent(unsigned int image)
Draw what the tool requires just before a given image is drawn.
std::vector< HuginBase::PTools::Transform * > m_transforms
The transformations used to make the image centres.
include file for the hugin project
void ForceRequireRedraw()
Definition: ViewState.cpp:439
void NotifyMe(Event event, Tool *tool)
Definition: ToolHelper.cpp:315
static char * line
Definition: svm.cpp:2784
bool isInside(vigra::Point2D p, bool ignoreMasks=false) const
check if a coordinate is inside the source image
hugin_utils::FDiff2D * operator[](std::size_t index)
represents a control point
Definition: ControlPoint.h:38
bool dud
false if the line should be used, true if it shouldn&#39;t.
VisualizationState * GetVisualizationStatePtr()
Definition: ToolHelper.cpp:300
HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:273
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
unsigned int m_nearestLine
The index of nearest line to the mouse position.
ToolHelper * helper
The PreviewToolHelper that uses the same preview window and panorama as the tool should.
Definition: Tool.h:102
void panoramaChanged(HuginBase::Panorama &pano)
This just sets a flag when the panorama is changed.
Model for a panorama.
Definition: Panorama.h:152
void DoNotNotifyMeBeforeDrawing(unsigned int image_nr, Tool *tool)
Definition: ToolHelper.cpp:397
float getDistance(hugin_utils::FDiff2D point)
Get the square of the distance from the arc to some panorama coordinate.
#define rect_ts
std::vector< hugin_utils::FDiff2D > m_imageCentresSpherical
The spherical coordinates of the middle of the images.
Definition: Tool.h:42
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2181
bool IsMouseOverPano()
Definition: ToolHelper.h:136
void createInvTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
create image-&gt;pano transformation
const ControlPoint & getCtrlPoint(std::size_t nr) const
get a control point, counting starts with 0
Definition: Panorama.h:312
TextureManager * GetTextureManager()
Definition: ViewState.h:104
void AfterDrawImagesEvent()
Draw a border over the images when a line is hilighted, similar to the identify tool.
Declare GreatCircles class.
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
void BeforeDrawImagesEvent()
Draw all the lines between images that indicate the quality and quantity of control points...
double worstError
the error of the control point with the greatest error between these images
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
std::vector< LineDetails > m_lines
A container for the line information.
void DrawImage(unsigned int image_number, unsigned int display_list)
include file for the hugin project
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
bool m_updateStatistics
Flag set to true to update statistics next redraw.
void Activate()
Start using the PreviewLayoutLinesTool.
void panoramaImagesChanged(HuginBase::Panorama &, const HuginBase::UIntSet &)
notifies about changes to images
std::vector< hugin_utils::FDiff2D > m_imageCentres
The location on the panorama that the middle of the images map to.
void ShowCtrlPointEditor(unsigned int img1, unsigned int img2)
opens the control points tab with the both images selected
Definition: MainFrame.cpp:2040
Holds transformations for Image -&gt; Pano and the other way.
void ControlPointErrorColour(const double cperr, double &r, double &g, double &b)
Definition: utils.cpp:341
void SetStatusMessage(wxString message)
Definition: ToolHelper.cpp:409
void draw(bool highlight)
Draw a line in the preview for this pair of images.
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
A map from image positions to panorama positions.
#define SAMPLE_FREQUENCY
HuginBase::SrcPanoImage * GetSrcImage(unsigned int image_nr)
Definition: ViewState.cpp:283
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
Panorama image options.
unsigned int GetMeshDisplayList(unsigned int image_nr)
Definition: ViewState.cpp:462
virtual void MouseMoveEvent(double x, double y, wxMouseEvent &e)
Revaluate the lines under the mouse pointer when it moves.
void updateImageCentres()
Update the locations of the image centres.
void updateLineInformation()
Update the line information.
void draw(bool withCross=true, double width=1.0) const
Draw the great circle arc on the fast preview.
void drawIdentificationBorder(unsigned int image)
Draw a border for an image.
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
unsigned int numberOfControlPoints
the number of control points between these images