Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OverviewOutlinesTool.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
22 #ifdef _WIN32
23 #include "wx/msw/wrapwin.h"
24 #endif
25 
26 #include "hugin_config.h"
27 #if defined HAVE_EPOXY && HAVE_EPOXY
28 #include <epoxy/gl.h>
29 #ifdef __WXMAC__
30 #include <OpenGL/glu.h>
31 #else
32 #include <GL/glu.h>
33 #endif
34 #else
35 #include <GL/glew.h>
36 #ifdef __WXMAC__
37 #include <OpenGL/gl.h>
38 #include <OpenGL/glu.h>
39 #else
40 #include <GL/gl.h>
41 #include <GL/glu.h>
42 #endif
43 #endif
44 #ifdef __APPLE__
45  #include <GLUT/glut.h>
46 #endif
47 
48 #include "OverviewOutlinesTool.h"
49 #include "GLViewer.h"
50 
51 #include "GreatCircles.h"
52 #include <cfloat>
53 
54 const double OverviewOutlinesTool::res=10;
55 const double OverviewOutlinesTool::mindist=2;
56 
57 OverviewOutlinesTool::OverviewOutlinesTool(ToolHelper * helper, GLViewer * viewer) : thelper(helper),
58  dirty_meshes(true), preview(viewer),
59  display_list_number_canvas(glGenLists(1)),
60  display_list_number_crop(glGenLists(1)),
61  display_list_number_canvas_outline(glGenLists(1)),
62  display_list_number_crop_outline(glGenLists(1))
63 {
65 }
66 
68 {
69 }
70 
72 {
73 
74  dirty_meshes = true;
76 
77 }
78 
79 
80 struct Rec {
81  Rec(double left, double top, double right, double bottom) : left(left), top(top), right(right), bottom(bottom) {}
82  Rec() : left(0), top(0), right(0), bottom(0) {}
83  double left;
84  double top;
85  double right;
86  double bottom;
87 };
88 
89 //#define WIREFRAME
90 
92 {
95 // helper->NotifyMe(ToolHelper::DRAW_OVER_IMAGES, this);
97 }
98 
99 
101 {
102  (helper)->NotifyMe(ToolHelper::DRAW_OVER_IMAGES, this);
104 }
105 
107 {
108  draw();
109 }
110 
112 {
113  draw();
114 }
115 
117 {
118  draw();
119 }
120 
122 {
123 
124  double radius = static_cast<PanosphereOverviewVisualizationState*>(helper->GetVisualizationStatePtr())->getSphereRadius();
125  GLUquadric* grid = gluNewQuadric();
126  gluSphere(grid, radius+1,40,20);
127 
128 }
129 
131 {
132  dirty_meshes = true;
133 }
134 
136 {
137 
138  glBegin(GL_QUADS);
139 
140  double end = 1000000;
141 
142  glVertex3f(-end, end, 0);
143  glVertex3f( end, end, 0);
144  glVertex3f( end,-end, 0);
145  glVertex3f(-end,-end, 0);
146 
147  glEnd();
148 
149 }
150 
152 {
153  dirty_meshes = true;
154 }
155 
157 {
158 
159  if (!(preview->m_visualization_state)) {
160  return;
161  }
162 
163 
164  if (dirty_meshes) {
165 
166 // std::cout << "outlines after draw images\n";
167 // vigra::Rect2D trect = preview->m_visualization_state->GetVisibleArea();
168 // double hscale, wscale;
169 // hscale = (float) thelper->GetVisualizationStatePtr()->GetOptions()->getHeight() / (float) preview->m_visualization_state->GetOptions()->getHeight();
170 // wscale = (float) thelper->GetVisualizationStatePtr()->GetOptions()->getWidth() / (float) preview->m_visualization_state->GetOptions()->getWidth();
171 // std::cerr << "outlines " << hscale << " " << wscale << std::endl;
172 // std::cerr << "outlines " << trect.left() << " " << trect.top() << " " << trect.right() << " " << trect.bottom() << std::endl;
173 // vigra::Rect2D rect(trect.left() * wscale, trect.top() * hscale, trect.right() * wscale, trect.bottom() * hscale);
174 // std::cerr << "outlines " << rect.left() << " " << rect.top() << " " << rect.right() << " " << rect.bottom() << std::endl;
175 
176  vigra::Rect2D rect = preview->m_visualization_state->GetVisibleArea();
177 
178  glNewList(display_list_number_canvas,GL_COMPILE);
179  DrawRect(rect.left(), rect.top(), rect.right(), rect.bottom(),false);
180  glEndList();
181  glNewList(display_list_number_canvas_outline,GL_COMPILE);
182  DrawRect(rect.left(), rect.top(), rect.right(), rect.bottom(),true, 4.0);
183  glEndList();
184 
185  vigra::Rect2D roi = thelper->GetViewStatePtr()->GetOptions()->getROI();
186  glNewList(display_list_number_crop,GL_COMPILE);
187  DrawRect(roi.left(), roi.top(), roi.right(), roi.bottom(),false);
188  glEndList();
189  glNewList(display_list_number_crop_outline,GL_COMPILE);
190  DrawRect(roi.left(), roi.top(), roi.right(), roi.bottom(),true, 2.0);
191  glEndList();
192 
193  dirty_meshes = false;
194 
195 // std::cout << "outlines adi " << rect.left() << " " << rect.top() << " " << rect.right() << " " << rect.bottom() << std::endl;
196 // std::cout << "outlines adi " << roi.left() << " " << roi.top() << " " << roi.right() << " " << roi.bottom() << std::endl;
197  }
198 
200 
201  vigra::Rect2D rect = preview->m_visualization_state->GetVisibleArea();
202  glNewList(display_list_number_canvas_outline,GL_COMPILE);
203  DrawRect(rect.left(), rect.top(), rect.right(), rect.bottom(),true, 4.0);
204  glEndList();
205 
206  vigra::Rect2D roi = thelper->GetViewStatePtr()->GetOptions()->getROI();
207  glNewList(display_list_number_crop_outline,GL_COMPILE);
208  DrawRect(roi.left(), roi.top(), roi.right(), roi.bottom(),true, 2.0);
209  glEndList();
210 
211  }
212 
213 
214  glDisable(GL_TEXTURE_2D);
215 
216  glEnable(GL_BLEND);
217  glColor4f(0, 0, 0, 0.50f);
218  glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
219  drawBackground();
220 
221 
222  glColor4f(1.0f, 1.0f, 1.0f, 0.20f);
223  glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
224  glCallList(display_list_number_canvas);
225 
226 // std::cout << "outlines " << roi.left() << " " << roi.top() << " " << roi.right() << " " << roi.bottom() << std::endl;
227 
228  glColor4f(1.0f, 1.0f, 1.0f, 0.66f);
229  glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
230  glCallList(display_list_number_crop);
231 
232  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
233  glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
235  glColor4f(0.8f, 0.8f, 0.8f, 0.6f);
237 
238  glEnable(GL_TEXTURE_2D);
239  glDisable(GL_BLEND);
240  glColor4f(1,1,1,1);
241 
242 }
243 
244 void OverviewOutlinesTool::DrawRect(double left, double top, double right, double bottom, bool outline, double line_width)
245 {
246 
247  vigra::Size2D size = thelper->GetVisualizationStatePtr()->GetOptions()->getSize();
248  double mlength = (size->y > size->x) ? size->y : size->x;
249 
250  double fov = thelper->GetVisualizationStatePtr()->GetOptions()->getHFOV();
251 
252  //since res was initially estimated for size of 360x100;
253  //TODO make res scale dependent
254  double tres = res * mlength / fov;
255  double tmindist = mindist * mlength / fov;
256 
257 // std::cerr << "outlines " << mlength << std::endl;
258 // std::cerr << "outlines " << right << std::endl;
259 
260  double safety = 1;
261  left += safety;
262  top += safety;
263  right -= safety;
264  bottom -= safety;
265 
268 // image.setSize(vigra::Size2D(360,180));
269  image.setSize(size);
270  image.setHFOV(fov);
274  break;
276  image.setProjection(HuginBase::BaseSrcPanoImage::RECTILINEAR);
277  break;
278  default:
279  DEBUG_ERROR("OverviewOutlinesTools: unknown projection")
280  break;
281  }
282 
283  transform.createTransform(image, *(preview->m_visualization_state->GetOptions()));
284 
286 
287  switch(proj) {
288 
298 
299  {
300 
301  //in this case just the divide the base rectangle by a certain amount of steps
302 
303  float steps = 40;
304 
305  double wstep = (float)(right - left) / steps;
306  double hstep = (float)(bottom - top) / steps;
307 
308  for(int w = 0 ; w < steps ; w++) {
309  for(int h = 0 ; h < steps ; h++) {
310 
311  //if outline is needed just consider edge cases
312  if (outline) {
313  if (!(w == 0 || h == 0 || w == steps - 1 || steps - 1)) {
314  continue;
315  }
316  }
317 
318  Rect rec(left + w * wstep, top + h * hstep, left + (w+1) * wstep, top + (h+1)* hstep);
319  Rect tr = rec.transformImgCoord(&transform);
320 
321  //this section should be added to avoid certain problems with these projections
322  //(just disregard edges with lengths larger than some value with respect to the radius of the sphere)
323  //TODO this was commented when support for mosaic plane was added, make this work again
324  // double edge1 = (tr.val[0][0]-tr.val[1][0])*(tr.val[0][0]-tr.val[1][0]) + (tr.val[0][1]-tr.val[1][1])*(tr.val[0][1]-tr.val[1][1]);
325  // double edge2 = (tr.val[1][0]-tr.val[2][0])*(tr.val[1][0]-tr.val[2][0]) + (tr.val[1][1]-tr.val[2][1])*(tr.val[1][1]-tr.val[2][1]);
326  // double edge3 = (tr.val[2][0]-tr.val[3][0])*(tr.val[2][0]-tr.val[3][0]) + (tr.val[2][1]-tr.val[3][1])*(tr.val[2][1]-tr.val[3][1]);
327  // double edge4 = (tr.val[3][0]-tr.val[0][0])*(tr.val[3][0]-tr.val[0][0]) + (tr.val[3][1]-tr.val[0][1])*(tr.val[3][1]-tr.val[0][1]);
328 
329 // double maxlimit = (radius/2.0)*(radius/2.0);
330 // if (
331 // proj == HuginBase::PanoramaOptions::SINUSOIDAL ||
332 // proj == HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC
333 // )
334 // if (edge1 > maxlimit || edge2 > maxlimit || edge3 > maxlimit || edge4 > maxlimit) {
335 // continue;
336 // }
337 
338  if (outline) {
339 
340 // glBegin(GL_LINES);
341  bool edges[4] = {false,false,false,false};
342  if (w == 0) {
343  edges[0] = true;
344  }
345  if (w == steps - 1) {
346  edges[2] = true;
347  }
348  if (h == 0) {
349  edges[3] = true;
350  }
351  if (h == steps - 1) {
352  edges[1] = true;
353  }
354  for (int i = 0 ; i < 4 ; i++) {
355  if (edges[i]) {
356 
357 
358  //draw a line with the help of the GreatCircles class so that a mesh is drawn instead of just a line
359  int plus = i+1;
360  if (plus == 4) plus = 0;
361  hugin_utils::FDiff2D cd1(tr.val[i][0], tr.val[i][1]);
362  hugin_utils::FDiff2D cd2(tr.val[plus][0], tr.val[plus][1]);
364  line.vertices[0] = cd1;
365  line.vertices[1] = cd2;
366  line.doGL(line_width, thelper->GetVisualizationStatePtr());
367 
368 
369 // for (int j = 0 ; j < 2 ; j++) {
370 // int plus = i+j;
371 // if (plus == 4) plus = 0;
372 // double x,y,z;
373 // double tx,ty;
374 // tx = tr.val[plus][0];
375 // ty = tr.val[plus][1];
381 // hugin_utils::FDiff2D cd(tx,ty);
382 // MeshManager::MeshInfo::Coord3D coord = thelper->GetVisualizationStatePtr()->GetMeshManager()->GetCoord3D(cd);
383 // glVertex3f(coord.x,coord.y,coord.z);
384 // }
385 
386  }
387  }
388 // glEnd();
389 
390  } else {
391 
392  //in this case draw the mesh
393 
394  #ifdef WIREFRAME
395  glBegin(GL_LINE_LOOP);
396  #else
397  glBegin(GL_POLYGON);
398  #endif
399  for (int s = 0 ; s < 4 ; s++) {
400  double tx,ty;
401  tx = tr.val[s][0];
402  ty = tr.val[s][1];
403 // ty = ty - 90;
404 // tx = tx - 180;
405 // ty *= -1;
406  hugin_utils::FDiff2D cd(tx,ty);
408  glVertex3f(coord.x,coord.y,coord.z);
409  }
410  glEnd();
411 
412  }
413 
414  }
415  }
416 
417  }
418 
419  break;
420 
434 
435  //stack to keep the rectangles to be divided
436  std::vector<Rec> stack;
437 
438  stack.push_back(Rec(left,top,right,bottom));
439  //if outline needs to be obtained, after each rectangle another rectangle is pushed back
440  if (outline) {
441  stack.push_back(Rec(true, true, true, true));
442  }
443 
444  while(!stack.empty()) {
445 
446  Rec edge;
447  if (outline) {
448  edge = stack[stack.size() - 1];
449  stack.pop_back();
450  }
451 
452  Rec top_rec = stack[stack.size() - 1];
453  stack.pop_back();
454 
455  if (outline) {
456  if (!(edge.left || edge.top || edge.right || edge.bottom )) {
457  continue;
458  }
459  }
460 
461  Rect rect(top_rec.left, top_rec.top, top_rec.right, top_rec.bottom);
462 
463  Rect tr = rect.transformImgCoord(&transform);
464 
465  double edge1 = (tr.val[0][0]-tr.val[1][0])*(tr.val[0][0]-tr.val[1][0]) + (tr.val[0][1]-tr.val[1][1])*(tr.val[0][1]-tr.val[1][1]);
466  double edge2 = (tr.val[1][0]-tr.val[2][0])*(tr.val[1][0]-tr.val[2][0]) + (tr.val[1][1]-tr.val[2][1])*(tr.val[1][1]-tr.val[2][1]);
467  double edge3 = (tr.val[2][0]-tr.val[3][0])*(tr.val[2][0]-tr.val[3][0]) + (tr.val[2][1]-tr.val[3][1])*(tr.val[2][1]-tr.val[3][1]);
468  double edge4 = (tr.val[3][0]-tr.val[0][0])*(tr.val[3][0]-tr.val[0][0]) + (tr.val[3][1]-tr.val[0][1])*(tr.val[3][1]-tr.val[0][1]);
469 
470 // std::cout << "outlines " << top_rec.left << " " << top_rec.top << " " << top_rec.right << " " << top_rec.bottom << std::endl;
471 // std::cout << "outlines " << edge1 << " " << edge2 << " " << edge3 << " " << edge4 << std::endl;
472 
473 // std::cout << "outlines " << tr.val[0][0] << " " << tr.val[0][1] << std::endl;
474 // std::cout << "outlines " << tr.val[1][0] << " " << tr.val[1][1] << std::endl;
475 // std::cout << "outlines " << tr.val[2][0] << " " << tr.val[2][1] << std::endl;
476 // std::cout << "outlines " << tr.val[3][0] << " " << tr.val[3][1] << std::endl;
477 
478  double ressq = tres * tres;
479 
480  bool divide_ver = false;
481  bool divide_hor = false;
482 
483  //decide whether to divide the current rectangle
484  if (
485  (edge1 > ressq || edge3 > ressq)
486  &&
487  std::abs(top_rec.top - top_rec.bottom) > tmindist
488  ) {
489 
490  divide_ver = true;
491 
492  } else if (
493  (edge2 > ressq || edge4 > ressq)
494  &&
495  std::abs(top_rec.left - top_rec.right) > tmindist
496  ) {
497 
498  divide_hor = true;
499 
500  }
501 
502  if (divide_ver) {
503 
504  stack.push_back(Rec(top_rec.left,top_rec.top,top_rec.right,(top_rec.top+top_rec.bottom)/2.0));
505  if (outline) {
506  stack.push_back(Rec(edge.left, edge.top, edge.right, false));
507  }
508  stack.push_back(Rec(top_rec.left,(top_rec.top+top_rec.bottom)/2.0,top_rec.right,top_rec.bottom));
509  if (outline) {
510  stack.push_back(Rec(edge.left, false, edge.right, edge.bottom));
511  }
512  }
513 
514  if (divide_hor) {
515 
516  stack.push_back(Rec(top_rec.left,top_rec.top,(top_rec.left+top_rec.right)/2.0,top_rec.bottom));
517  if (outline) {
518  stack.push_back(Rec(edge.left, edge.top, false, edge.bottom));
519  }
520  stack.push_back(Rec((top_rec.left+top_rec.right)/2.0,top_rec.top,top_rec.right,top_rec.bottom));
521  if (outline) {
522  stack.push_back(Rec(false, edge.top, edge.right, edge.bottom));
523  }
524 
525  }
526 
527  if (!(divide_ver || divide_hor)) {
528 
529  //draw it
530 
531  if (outline) {
532 // glBegin(GL_LINES);
533  bool edges[4];
534  edges[0] = edge.left!=0;
535  edges[1] = edge.bottom!=0;
536  edges[2] = edge.right!=0;
537  edges[3] = edge.top!=0;
538  for (int i = 0 ; i < 4 ; i++) {
539  if (edges[i]) {
540 // std::cout << "outlines line!!" << i << "\n";
541 // std::cout << "outlines " << top_rec.left << " " << top_rec.top << " " << top_rec.right << " " << top_rec.bottom << std::endl;
542 
543  int plus = i+1;
544  if (plus == 4) plus = 0;
545  hugin_utils::FDiff2D cd1(tr.val[i][0], tr.val[i][1]);
546  hugin_utils::FDiff2D cd2(tr.val[plus][0], tr.val[plus][1]);
548  line.vertices[0] = cd1;
549  line.vertices[1] = cd2;
550  line.doGL(line_width, thelper->GetVisualizationStatePtr());
551 
552 // MeshManager::MeshInfo::Coord3D coord1 = thelper->GetVisualizationStatePtr()->GetMeshManager()->GetCoord3D(cd1);
553 // MeshManager::MeshInfo::Coord3D coord2 = thelper->GetVisualizationStatePtr()->GetMeshManager()->GetCoord3D(cd2);
554 // glVertex3f(coord1.x,coord1.y,coord1.z);
555 // glVertex3f(coord2.x,coord2.y,coord2.z);
556 
557 
558 // for (int j = 0 ; j < 2 ; j++) {
559 // int plus = i+j;
560 // if (plus == 4) plus = 0;
561 // double x,y,z;
562 // double tx,ty;
563 // tx = tr.val[plus][0];
564 // ty = tr.val[plus][1];
568 
569 //
570 // hugin_utils::FDiff2D cd(tx,ty);
571 // MeshManager::MeshInfo::Coord3D coord = thelper->GetVisualizationStatePtr()->GetMeshManager()->GetCoord3D(cd);
572 // glVertex3f(coord.x,coord.y,coord.z);
573 // }
574  }
575  }
576 // glEnd();
577  } else {
578  #ifdef WIREFRAME
579  glBegin(GL_LINE_LOOP);
580  #else
581  glBegin(GL_POLYGON);
582  #endif
583  for (int s = 0 ; s < 4 ; s++) {
584  double tx,ty;
585  tx = tr.val[s][0];
586  ty = tr.val[s][1];
587 // ty = ty - 90;
588 // tx = tx - 180;
589 // ty *= -1;
590  hugin_utils::FDiff2D cd(tx,ty);
592  glVertex3f(coord.x,coord.y,coord.z);
593  }
594  glEnd();
595  }
596  }
597 
598  }
599 
600  break;
601 
602  }
603 
604 }
605 
606 
607 
PanoramaOptions::ProjectionFormat getProjection() const
unsigned int display_list_number_crop_outline
ViewState * GetViewStatePtr()
Definition: ToolHelper.cpp:305
class to represent a single rectangle
void Activate()
Switch on a tool.
HuginBase::Panorama * GetPanoramaPtr()
Definition: ToolHelper.cpp:310
void doGL(double width, VisualizationState *state, LineSegment *preceding=NULL, LineSegment *proceeding=NULL) const
Draw a meshed line.
virtual void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
unsigned int display_list_number_canvas_outline
void ForceRequireRedraw()
Definition: ViewState.cpp:439
void NotifyMe(Event event, Tool *tool)
Definition: ToolHelper.cpp:315
static char * line
Definition: svm.cpp:2784
void drawBackground()
drawing the background means drawing a mesh that covers the whole panorama for the purpose of darkeni...
VisualizationState * GetVisualizationStatePtr()
Definition: ToolHelper.cpp:300
HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:273
static const double res
unsigned int display_list_number_canvas
ToolHelper * helper
The PreviewToolHelper that uses the same preview window and panorama as the tool should.
Definition: Tool.h:102
const vigra::Rect2D & getROI() const
Model for a panorama.
Definition: Panorama.h:152
MeshManager * GetMeshManager()
Definition: ViewState.h:207
vigra::Rect2D GetVisibleArea()
Definition: ViewState.h:222
OverviewOutlinesTool(ToolHelper *, GLViewer *preview)
Rect transformImgCoord(HuginBase::PTools::Transform *trans)
transform the rectangle&#39;s coordinates with a certain transform
void AfterDrawImagesBackEvent()
Draw using opengl anything after drawing the front face culled images.
Declare GreatCircles class.
virtual MeshInfo::Coord3D GetCoord3D(hugin_utils::FDiff2D &)=0
void Activate()
Switch on a tool.
virtual void drawBackground()
drawing the background means drawing a mesh that covers the whole panorama for the purpose of darkeni...
IMPEX double h[25][1024]
Definition: emor.cpp:169
void DrawRect(double left, double top, double right, double bottom, bool outline, double linewidth=1.0)
void drawBackground()
drawing the background means drawing a mesh that covers the whole panorama for the purpose of darkeni...
VisualizationState * m_visualization_state
Definition: GLViewer.h:71
#define DEBUG_ERROR(msg)
Definition: utils.h:76
bool RequireRecalculateViewport()
Definition: ViewState.cpp:415
hugin_utils::FDiff2D vertices[2]
Definition: GreatCircles.h:95
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
unsigned int display_list_number_crop
void AfterDrawImagesFrontEvent()
Draw using opengl anything after drawing the back face culled images.
void AfterDrawImagesEvent()
Draw (using OpenGL) images above the others.
virtual HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:468
Holds transformations for Image -&gt; Pano and the other way.
Rec(double left, double top, double right, double bottom)
void setSize(vigra::Size2D val)
Set the image size in pixels.
ProjectionFormat
Projection of final panorama.
static const double mindist
All variables of a source image.
Definition: SrcPanoImage.h:194
vigra::Size2D getSize() const
get size of output image
virtual void MarkDirty() override
a class to handle a 3D point
Definition: MeshManager.h:93
A wxWidget to display the fast preview.
Definition: GLViewer.h:51
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