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 
void Activate() override
Switch on a tool.
PanoramaOptions::ProjectionFormat getProjection() const
unsigned int display_list_number_crop_outline
ViewState * GetViewStatePtr()
Definition: ToolHelper.cpp:305
class to represent a single rectangle
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 AfterDrawImagesBackEvent() override
Draw using opengl anything after drawing the front face culled images.
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
Declare GreatCircles class.
virtual MeshInfo::Coord3D GetCoord3D(hugin_utils::FDiff2D &)=0
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)
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:96
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
void drawBackground() override
drawing the background means drawing a mesh that covers the whole panorama for the purpose of darkeni...
unsigned int display_list_number_crop
void drawBackground() override
drawing the background means drawing a mesh that covers the whole panorama for the purpose of darkeni...
void AfterDrawImagesEvent() override
Draw (using OpenGL) images above the others.
virtual HuginBase::PanoramaOptions * GetOptions()
Definition: ViewState.cpp:468
void Activate() override
Switch on a tool.
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.
void AfterDrawImagesFrontEvent() override
Draw using opengl anything after drawing the back face culled images.
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
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