00001
00022 #if !defined Hugin_shared || !defined _WINDOWS
00023 #define GLEW_STATIC
00024 #endif
00025 #include <GL/glew.h>
00026 #ifdef __WXMAC__
00027 #include <OpenGL/gl.h>
00028 #include <OpenGL/glu.h>
00029 #else
00030 #include <GL/gl.h>
00031 #include <GL/glu.h>
00032 #endif
00033 #ifdef __APPLE__
00034 #include <GLUT/glut.h>
00035 #endif
00036
00037 #include "OverviewOutlinesTool.h"
00038 #include "GLViewer.h"
00039
00040 #include "GreatCircles.h"
00041 #include <cfloat>
00042
00043 const double OverviewOutlinesTool::res=10;
00044 const double OverviewOutlinesTool::mindist=2;
00045
00046 OverviewOutlinesTool::OverviewOutlinesTool(ToolHelper * helper, GLViewer * viewer) : preview(viewer), thelper(helper),
00047 display_list_number_canvas(glGenLists(1)),
00048 display_list_number_crop(glGenLists(1)),
00049 display_list_number_canvas_outline(glGenLists(1)),
00050 display_list_number_crop_outline(glGenLists(1)),
00051 dirty_meshes(true)
00052 {
00053 thelper->GetPanoramaPtr()->addObserver(this);
00054 }
00055
00056 OverviewOutlinesTool::~OverviewOutlinesTool()
00057 {
00058 }
00059
00060 void OverviewOutlinesTool::panoramaChanged(HuginBase::PanoramaData &pano)
00061 {
00062
00063 dirty_meshes = true;
00064 thelper->GetVisualizationStatePtr()->ForceRequireRedraw();
00065
00066 }
00067
00068
00069 struct Rec {
00070 Rec(double left, double top, double right, double bottom) : left(left), top(top), right(right), bottom(bottom) {}
00071 Rec() {}
00072 double left;
00073 double top;
00074 double right;
00075 double bottom;
00076 };
00077
00078
00079
00080 void PanosphereOverviewOutlinesTool::Activate()
00081 {
00082 ((PanosphereOverviewToolHelper*)helper)->NotifyMe(PanosphereOverviewToolHelper::DRAW_OVER_IMAGES_FRONT, this);
00083 ((PanosphereOverviewToolHelper*)helper)->NotifyMe(PanosphereOverviewToolHelper::DRAW_OVER_IMAGES_BACK, this);
00084
00085 }
00086
00087
00088 void PlaneOverviewOutlinesTool::Activate()
00089 {
00090 (helper)->NotifyMe(ToolHelper::DRAW_OVER_IMAGES, this);
00091 }
00092
00093 void PlaneOverviewOutlinesTool::AfterDrawImagesEvent()
00094 {
00095 draw();
00096 }
00097
00098 void PanosphereOverviewOutlinesTool::AfterDrawImagesBackEvent()
00099 {
00100 draw();
00101 }
00102
00103 void PanosphereOverviewOutlinesTool::AfterDrawImagesFrontEvent()
00104 {
00105 draw();
00106 }
00107
00108 void PanosphereOverviewOutlinesTool::drawBackground()
00109 {
00110
00111 double radius = ((PanosphereOverviewVisualizationState*) helper->GetVisualizationStatePtr())->getSphereRadius();
00112 GLUquadric* grid = gluNewQuadric();
00113 gluSphere(grid, radius+1,40,20);
00114
00115 }
00116
00117 void PlaneOverviewOutlinesTool::drawBackground()
00118 {
00119
00120 glBegin(GL_QUADS);
00121
00122 double end = 1000000;
00123
00124 glVertex3f(-end, end, 0);
00125 glVertex3f( end, end, 0);
00126 glVertex3f( end,-end, 0);
00127 glVertex3f(-end,-end, 0);
00128
00129 glEnd();
00130
00131 }
00132
00133 void OverviewOutlinesTool::draw()
00134 {
00135
00136 if (!(preview->m_visualization_state)) {
00137 return;
00138 }
00139
00140
00141 if (dirty_meshes) {
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 vigra::Rect2D rect = preview->m_visualization_state->GetVisibleArea();
00154
00155 glNewList(display_list_number_canvas,GL_COMPILE);
00156 DrawRect(rect.left(), rect.top(), rect.right(), rect.bottom(),false);
00157 glEndList();
00158 glNewList(display_list_number_canvas_outline,GL_COMPILE);
00159 DrawRect(rect.left(), rect.top(), rect.right(), rect.bottom(),true, 4.0);
00160 glEndList();
00161
00162 vigra::Rect2D roi = thelper->GetViewStatePtr()->GetOptions()->getROI();
00163 glNewList(display_list_number_crop,GL_COMPILE);
00164 DrawRect(roi.left(), roi.top(), roi.right(), roi.bottom(),false);
00165 glEndList();
00166 glNewList(display_list_number_crop_outline,GL_COMPILE);
00167 DrawRect(roi.left(), roi.top(), roi.right(), roi.bottom(),true, 2.0);
00168 glEndList();
00169
00170 dirty_meshes = false;
00171
00172
00173
00174 }
00175
00176 if (thelper->GetVisualizationStatePtr()->RequireRecalculateViewport()) {
00177
00178 vigra::Rect2D rect = preview->m_visualization_state->GetVisibleArea();
00179 glNewList(display_list_number_canvas_outline,GL_COMPILE);
00180 DrawRect(rect.left(), rect.top(), rect.right(), rect.bottom(),true, 4.0);
00181 glEndList();
00182
00183 vigra::Rect2D roi = thelper->GetViewStatePtr()->GetOptions()->getROI();
00184 glNewList(display_list_number_crop_outline,GL_COMPILE);
00185 DrawRect(roi.left(), roi.top(), roi.right(), roi.bottom(),true, 2.0);
00186 glEndList();
00187
00188 }
00189
00190
00191 glDisable(GL_TEXTURE_2D);
00192
00193 glEnable(GL_BLEND);
00194 glColor4f(0,0,0,0.50);
00195 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
00196 drawBackground();
00197
00198
00199 glColor4f(1.0,1.0,1.0,0.20);
00200 glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
00201 glCallList(display_list_number_canvas);
00202
00203
00204
00205 glColor4f(1.0,1.0,1.0,0.66);
00206 glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
00207 glCallList(display_list_number_crop);
00208
00209 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00210 glColor4f(0.8,0.8,0.8,0.5);
00211 glCallList(display_list_number_canvas_outline);
00212 glColor4f(0.8,0.8,0.8,0.6);
00213 glCallList(display_list_number_crop_outline);
00214
00215 glEnable(GL_TEXTURE_2D);
00216 glDisable(GL_BLEND);
00217 glColor4f(1,1,1,1);
00218
00219 }
00220
00221 void OverviewOutlinesTool::DrawRect(double left, double top, double right, double bottom, bool outline, double line_width)
00222 {
00223
00224 vigra::Size2D size = thelper->GetVisualizationStatePtr()->GetOptions()->getSize();
00225 double mlength = (size->y > size->x) ? size->y : size->x;
00226
00227 double fov = thelper->GetVisualizationStatePtr()->GetOptions()->getHFOV();
00228
00229
00230
00231 double tres = res * mlength / fov;
00232 double tmindist = mindist * mlength / fov;
00233
00234
00235
00236
00237 double safety = 1;
00238 left += safety;
00239 top += safety;
00240 right -= safety;
00241 bottom -= safety;
00242
00243 HuginBase::PTools::Transform transform;
00244 HuginBase::SrcPanoImage image;
00245
00246 image.setSize(size);
00247 image.setHFOV(fov);
00248 switch(thelper->GetVisualizationStatePtr()->GetOptions()->getProjection()) {
00249 case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
00250 image.setProjection(HuginBase::BaseSrcPanoImage::EQUIRECTANGULAR);
00251 break;
00252 case HuginBase::PanoramaOptions::RECTILINEAR:
00253 image.setProjection(HuginBase::BaseSrcPanoImage::RECTILINEAR);
00254 break;
00255 }
00256
00257 transform.createTransform(image, *(preview->m_visualization_state->GetOptions()));
00258
00259 HuginBase::PanoramaOptions::ProjectionFormat proj = thelper->GetViewStatePtr()->GetOptions()->getProjection();
00260
00261 switch(proj) {
00262
00263 case HuginBase::PanoramaOptions::SINUSOIDAL:
00264 case HuginBase::PanoramaOptions::LAMBERT:
00265 case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL:
00266 case HuginBase::PanoramaOptions::HAMMER_AITOFF:
00267 case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE:
00268 case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC:
00269 case HuginBase::PanoramaOptions::ORTHOGRAPHIC:
00270 case HuginBase::PanoramaOptions::EQUISOLID:
00271 case HuginBase::PanoramaOptions::THOBY_PROJECTION:
00272
00273 {
00274
00275
00276
00277 float steps = 40;
00278
00279 double wstep = (float)(right - left) / steps;
00280 double hstep = (float)(bottom - top) / steps;
00281
00282 for(int w = 0 ; w < steps ; w++) {
00283 for(int h = 0 ; h < steps ; h++) {
00284
00285
00286 if (outline) {
00287 if (!(w == 0 || h == 0 || w == steps - 1 || steps - 1)) {
00288 continue;
00289 }
00290 }
00291
00292 Rect rec(left + w * wstep, top + h * hstep, left + (w+1) * wstep, top + (h+1)* hstep);
00293 Rect tr = rec.transformImgCoord(&transform);
00294
00295 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]);
00296 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]);
00297 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]);
00298 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]);
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 if (outline) {
00314
00315
00316 bool edges[4] = {false,false,false,false};
00317 if (w == 0) {
00318 edges[0] = true;
00319 }
00320 if (w == steps - 1) {
00321 edges[2] = true;
00322 }
00323 if (h == 0) {
00324 edges[3] = true;
00325 }
00326 if (h == steps - 1) {
00327 edges[1] = true;
00328 }
00329 for (int i = 0 ; i < 4 ; i++) {
00330 if (edges[i]) {
00331
00332
00333
00334 int plus = i+1;
00335 if (plus == 4) plus = 0;
00336 hugin_utils::FDiff2D cd1(tr.val[i][0], tr.val[i][1]);
00337 hugin_utils::FDiff2D cd2(tr.val[plus][0], tr.val[plus][1]);
00338 GreatCircleArc::LineSegment line;
00339 line.vertices[0] = cd1;
00340 line.vertices[1] = cd2;
00341 line.doGL(line_width, thelper->GetVisualizationStatePtr());
00342
00343
00344
00345
00346
00347
00348
00349
00350
00356
00357
00358
00359
00360
00361 }
00362 }
00363
00364
00365 } else {
00366
00367
00368
00369 #ifdef WIREFRAME
00370 glBegin(GL_LINE_LOOP);
00371 #else
00372 glBegin(GL_POLYGON);
00373 #endif
00374 for (int s = 0 ; s < 4 ; s++) {
00375 double tx,ty;
00376 tx = tr.val[s][0];
00377 ty = tr.val[s][1];
00378
00379
00380
00381 hugin_utils::FDiff2D cd(tx,ty);
00382 MeshManager::MeshInfo::Coord3D coord = thelper->GetVisualizationStatePtr()->GetMeshManager()->GetCoord3D(cd);
00383 glVertex3f(coord.x,coord.y,coord.z);
00384 }
00385 glEnd();
00386
00387 }
00388
00389 }
00390 }
00391
00392 }
00393
00394 break;
00395
00396 case HuginBase::PanoramaOptions::RECTILINEAR:
00397 case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
00398 case HuginBase::PanoramaOptions::CYLINDRICAL:
00399 case HuginBase::PanoramaOptions::STEREOGRAPHIC:
00400 case HuginBase::PanoramaOptions::MERCATOR:
00401 case HuginBase::PanoramaOptions::TRANSVERSE_MERCATOR:
00402 case HuginBase::PanoramaOptions::MILLER_CYLINDRICAL:
00403 case HuginBase::PanoramaOptions::PANINI:
00404 case HuginBase::PanoramaOptions::EQUI_PANINI:
00405 case HuginBase::PanoramaOptions::BIPLANE:
00406 case HuginBase::PanoramaOptions::TRIPLANE:
00407 case HuginBase::PanoramaOptions::GENERAL_PANINI:
00408 case HuginBase::PanoramaOptions::ARCHITECTURAL:
00409
00410
00411 std::vector<Rec> stack;
00412
00413 stack.push_back(Rec(left,top,right,bottom));
00414
00415 if (outline) {
00416 stack.push_back(Rec(true, true, true, true));
00417 }
00418
00419 while(stack.size() > 0) {
00420
00421 Rec edge;
00422 if (outline) {
00423 edge = stack[stack.size() - 1];
00424 stack.pop_back();
00425 }
00426
00427 Rec top_rec = stack[stack.size() - 1];
00428 stack.pop_back();
00429
00430 if (outline) {
00431 if (!(edge.left || edge.top || edge.right || edge.bottom )) {
00432 continue;
00433 }
00434 }
00435
00436 Rect rect(top_rec.left, top_rec.top, top_rec.right, top_rec.bottom);
00437
00438 Rect tr = rect.transformImgCoord(&transform);
00439
00440 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]);
00441 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]);
00442 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]);
00443 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]);
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 double ressq = tres * tres;
00454
00455 bool divide_ver = false;
00456 bool divide_hor = false;
00457
00458 bool invalid = false;
00459 int countx = 0, county = 0;
00460
00461
00462
00463 if (
00464 (edge1 > ressq || edge3 > ressq)
00465 &&
00466 abs(top_rec.top - top_rec.bottom) > tmindist
00467 ) {
00468
00469 divide_ver = true;
00470
00471 } else if (
00472 (edge2 > ressq || edge4 > ressq)
00473 &&
00474 abs(top_rec.left - top_rec.right) > tmindist
00475 ) {
00476
00477 divide_hor = true;
00478
00479 }
00480
00481 if (divide_ver) {
00482
00483 stack.push_back(Rec(top_rec.left,top_rec.top,top_rec.right,(top_rec.top+top_rec.bottom)/2.0));
00484 if (outline) {
00485 stack.push_back(Rec(edge.left, edge.top, edge.right, false));
00486 }
00487 stack.push_back(Rec(top_rec.left,(top_rec.top+top_rec.bottom)/2.0,top_rec.right,top_rec.bottom));
00488 if (outline) {
00489 stack.push_back(Rec(edge.left, false, edge.right, edge.bottom));
00490 }
00491 }
00492
00493 if (divide_hor) {
00494
00495 stack.push_back(Rec(top_rec.left,top_rec.top,(top_rec.left+top_rec.right)/2.0,top_rec.bottom));
00496 if (outline) {
00497 stack.push_back(Rec(edge.left, edge.top, false, edge.bottom));
00498 }
00499 stack.push_back(Rec((top_rec.left+top_rec.right)/2.0,top_rec.top,top_rec.right,top_rec.bottom));
00500 if (outline) {
00501 stack.push_back(Rec(false, edge.top, edge.right, edge.bottom));
00502 }
00503
00504 }
00505
00506 if (!(divide_ver || divide_hor)) {
00507
00508
00509
00510 if (outline) {
00511
00512 bool edges[4];
00513 edges[0] = edge.left!=0;
00514 edges[1] = edge.bottom!=0;
00515 edges[2] = edge.right!=0;
00516 edges[3] = edge.top!=0;
00517 for (int i = 0 ; i < 4 ; i++) {
00518 if (edges[i]) {
00519
00520
00521
00522 int plus = i+1;
00523 if (plus == 4) plus = 0;
00524 hugin_utils::FDiff2D cd1(tr.val[i][0], tr.val[i][1]);
00525 hugin_utils::FDiff2D cd2(tr.val[plus][0], tr.val[plus][1]);
00526 GreatCircleArc::LineSegment line;
00527 line.vertices[0] = cd1;
00528 line.vertices[1] = cd2;
00529 line.doGL(line_width, thelper->GetVisualizationStatePtr());
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00547
00548
00549
00550
00551
00552
00553 }
00554 }
00555
00556 } else {
00557 #ifdef WIREFRAME
00558 glBegin(GL_LINE_LOOP);
00559 #else
00560 glBegin(GL_POLYGON);
00561 #endif
00562 for (int s = 0 ; s < 4 ; s++) {
00563 double tx,ty;
00564 tx = tr.val[s][0];
00565 ty = tr.val[s][1];
00566
00567
00568
00569 hugin_utils::FDiff2D cd(tx,ty);
00570 MeshManager::MeshInfo::Coord3D coord = thelper->GetVisualizationStatePtr()->GetMeshManager()->GetCoord3D(cd);
00571 glVertex3f(coord.x,coord.y,coord.z);
00572 }
00573 glEnd();
00574 }
00575 }
00576
00577 }
00578
00579 break;
00580
00581 }
00582
00583 }
00584
00585
00586