00001
00023 #include <config.h>
00024 #include "panoinc_WX.h"
00025 #include "panoinc.h"
00026
00027 #include "DragTool.h"
00028 #include "CommandHistory.h"
00029 #include "PT/PanoCommand.h"
00030 #include "PT/ImageGraph.h"
00031
00032 #include <math.h>
00033 #include <wx/platform.h>
00034 #ifdef __WXMAC__
00035 #include <OpenGL/gl.h>
00036 #else
00037 #include <GL/gl.h>
00038 #endif
00039
00040 #include "GLPreviewFrame.h"
00041
00042 DragTool::DragTool(ToolHelper *helper)
00043 : Tool(helper)
00044 {
00045 }
00046
00047 void DragTool::setDragMode(PreviewDragTool::DragMode dmode)
00048 {
00049 drag_mode = dmode;
00050 }
00051
00052 DragTool::DragMode DragTool::getDragMode()
00053 {
00054 return drag_mode;
00055 }
00056
00057
00058 void DragTool::getTranslationShift(double &delta_x, double &delta_y)
00059 {
00060 double startx = atan(DEG_TO_RAD(start_coordinates.x));
00061 double starty = atan(DEG_TO_RAD(start_coordinates.y));
00062 double shiftx = atan(DEG_TO_RAD(shift_coordinates.x));
00063 double shifty = atan(DEG_TO_RAD(shift_coordinates.y));
00064 delta_x = shiftx - startx;
00065 delta_y = shifty - starty;
00066 }
00067
00068
00069 void DragTool::Activate()
00070 {
00071 drag_yaw = false; drag_pitch = false; drag_roll = false;
00072 shift = false; control = false;
00073
00074 helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this);
00075 helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this);
00076 helper->NotifyMe(PreviewToolHelper::REALLY_DRAW_OVER_IMAGES, this);
00077
00078 helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or Ctrl-drag."));
00079 }
00080
00081 void DragTool::MouseMoveEvent(double x, double y, wxMouseEvent & e)
00082 {
00083 hugin_utils::FDiff2D pos = helper->GetMousePanoPosition();
00084 x = pos.x;
00085 y = pos.y;
00086 if (drag_yaw || drag_pitch || drag_roll)
00087 {
00088
00089
00090
00091 if (drag_yaw || drag_pitch)
00092 {
00093
00094 double yaw, pitch;
00095 helper->GetVisualizationStatePtr()->GetProjectionInfo()->ImageToAngular(yaw,
00096 pitch, x, y);
00097 shift_coordinates.x = yaw;
00098 shift_coordinates.y = pitch;
00099 shift = e.m_shiftDown;
00100 if (shift)
00101 {
00102 if (abs(shift_coordinates.x - start_coordinates.x)
00103 < abs(shift_coordinates.y - start_coordinates.y))
00104 {
00105 shift_coordinates.x = start_coordinates.x;
00106 helper->SetStatusMessage(_("Currently constrained to moving only pitch. Make a larger movement in the opposite direction to constrain to yaw."));
00107
00108 } else {
00109 shift_coordinates.y = start_coordinates.y;
00110 helper->SetStatusMessage(_("Currently constrained to moving only yaw. Make a larger movement in the opposite direction to constrain to pitch."));
00111 }
00112 }
00113
00114 }
00115 if (drag_roll)
00116 {
00117 shift_angle = atan2(y - centre.y, x- centre.x) - start_angle;
00118 }
00119
00120
00121
00122 if (drag_mode == drag_mode_mosaic) {
00123
00124 SetRotationMatrix(0,0,shift_angle, 0,0,0);
00125 } else {
00126 SetRotationMatrix(shift_coordinates.x, shift_coordinates.y, shift_angle,
00127 start_coordinates.x, start_coordinates.y, 0.0);
00128 }
00129
00130 std::map<unsigned int, ParamStore>::iterator i;
00131 for (i = image_params.begin(); i != image_params.end(); i++ )
00132 {
00133 HuginBase::SrcPanoImage img = *helper->GetViewStatePtr()->
00134 GetSrcImage(i->first);
00135 double new_yaw, new_pitch, new_roll, new_TrX, new_TrY, new_TrZ, new_Tpy, new_Tpp;
00136
00137 if (drag_mode == drag_mode_mosaic) {
00138
00139 double shift_x, shift_y;
00140 getTranslationShift(shift_x, shift_y);
00141 i->second.TrX = img.getX() + shift_x;
00142 i->second.TrY = img.getY() + shift_y;
00143 }
00144 i->second.Move(&rotation_matrix, new_yaw, new_pitch, new_roll, new_TrX, new_TrY, new_TrZ, new_Tpy, new_Tpp);
00145 img.setX(new_TrX);
00146 img.setY(new_TrY);
00147 img.setZ(new_TrZ);
00148 img.setTranslationPlaneYaw(new_Tpy);
00149 img.setTranslationPlanePitch(new_Tpp);
00150 img.setYaw(new_yaw);
00151 img.setPitch(new_pitch);
00152 img.setRoll(new_roll);
00153 helper->GetViewStatePtr()->SetSrcImage(i->first, &img);
00154 }
00155
00156
00157 helper->GetVisualizationStatePtr()->Redraw();
00158 }
00159 }
00160
00161 void DragTool::MouseButtonEvent(wxMouseEvent &e)
00162 {
00163 if (e.ButtonDown())
00164 {
00165
00166 if (helper->IsMouseOverPano()) {
00167
00168 control = e.m_controlDown;
00169 shift = e.m_shiftDown;
00170
00171 if (control && (helper->GetPreviewFrame()->individualDragging())) {
00172
00173 std::set<unsigned int> images_under_mouse = helper->GetImageNumbersUnderMouse();
00174 std::set<unsigned int>::iterator it;
00175 for(it = images_under_mouse.begin() ; it != images_under_mouse.end() ; it++) {
00176 if (shift) {
00177 helper->GetPreviewFrame()->RemoveImageFromDragGroup(*it);
00178 } else {
00179 helper->GetPreviewFrame()->AddImageToDragGroup(*it);
00180 }
00181 }
00182 return;
00183
00184 }
00185
00186 switch (e.GetButton())
00187 {
00188
00189 case wxMOUSE_BTN_LEFT:
00190
00191
00192
00193
00194
00195 drag_yaw = true; drag_pitch = true;
00196 break;
00197 case wxMOUSE_BTN_RIGHT:
00198 drag_roll = true;
00199 break;
00200 }
00201 if (drag_roll)
00202 {
00203
00204 helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage(
00205 centre.x, centre.y, 0.0, 0.0);
00206 centre.x += 0.5;
00207 centre.y += 0.5;
00208 hugin_utils::FDiff2D angular = helper->GetMousePanoPosition() - centre;
00209 start_angle = atan2(angular.y, angular.x);
00210 shift_angle = 0.0;
00211
00212 start_coordinates.x = 0.0; start_coordinates.y = 0.0;
00213 shift_coordinates.x = 0.0; shift_coordinates.y = 0.0;
00214 helper->SetStatusMessage(_("Rotate around the centre to roll."));
00215 }
00216 if (drag_yaw || drag_pitch)
00217 {
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 double yaw, pitch;
00228 hugin_utils::FDiff2D mouse_pos = helper->GetMousePanoPosition();
00229 helper->GetVisualizationStatePtr()->GetProjectionInfo()->ImageToAngular(yaw,
00230 pitch, mouse_pos.x, mouse_pos.y);
00231 start_coordinates.x = yaw; start_coordinates.y = pitch;
00232 shift_coordinates.x = yaw; shift_coordinates.y = pitch;
00233
00234 if (shift) {
00235 helper->SetStatusMessage(_("Constrained drag: make a movement and it will be snapped to the yaw or pitch."));
00236 } else {
00237 helper->SetStatusMessage(_("Drag to move."));
00238 }
00239 }
00240 if (drag_roll || drag_yaw || drag_pitch)
00241 {
00242 shift_angle = 0.0;
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 bool customDragging = helper->GetPreviewFrame()->individualDragging();
00259 if (customDragging) {
00260 draging_images = helper->GetPreviewFrame()->GetDragGroupImages();
00261 std::set<unsigned int>::iterator i, end;
00262 end = draging_images.end();
00263 for (i = draging_images.begin(); i != end; i++)
00264 {
00265 image_params[*i].Set(
00266 helper->GetViewStatePtr()->GetSrcImage(*i));
00267 }
00268
00269 } else {
00270
00271
00272 PT::CPGraph graph;
00273 PT::createCPGraph(*helper->GetPanoramaPtr(), graph);
00274 PT::CPComponents components;
00275 unsigned int n = PT::findCPComponents(graph, components);
00276
00277
00278 if (n == 1)
00279 {
00280 unsigned int imgs = helper->GetPanoramaPtr()->getNrOfImages();
00281 draging_images.clear();
00282 fill_set(draging_images, 0, imgs - 1);
00283
00284 ViewState *view_state_ptr = helper->GetViewStatePtr();
00285 for (unsigned int i = 0; i < imgs; i++)
00286 {
00287 image_params[i].Set(view_state_ptr->GetSrcImage(i));
00288 };
00289 } else
00290 {
00291
00292 if (n == 0 || helper->GetImageNumbersUnderMouse().empty())
00293 {
00294
00295 drag_roll = false; drag_yaw = false; drag_pitch = false;
00296 return;
00297 }
00298
00299
00300 unsigned int img = *helper->GetImageNumbersUnderMouse().begin();
00301 for (unsigned int component_index = 0;
00302 component_index < components.size(); component_index ++)
00303 {
00304 if (components[component_index].count(img))
00305 {
00306
00307 draging_images = components[component_index];
00308 std::set<unsigned int>::iterator i, end;
00309 end = draging_images.end();
00310 for (i = draging_images.begin(); i != end; i++)
00311 {
00312 image_params[*i].Set(
00313 helper->GetViewStatePtr()->GetSrcImage(*i));
00314 }
00315 break;
00316 }
00317 }
00318 }
00319 }
00320 SetRotationMatrix(shift_coordinates.x, shift_coordinates.y,
00321 shift_angle,
00322 start_coordinates.x, start_coordinates.y, 0.0);
00323 }
00324 }
00325 } else {
00326
00327 if (! (drag_pitch || drag_roll || drag_yaw)) return;
00328
00329
00330 drag_yaw = false; drag_pitch = false; drag_roll = false;
00331
00332
00333 std::vector<HuginBase::SrcPanoImage> src_images(draging_images.size() + 1);
00334 std::map<unsigned int, ParamStore>::iterator i;
00335 unsigned int count = 0;
00336 for (i = image_params.begin(); i != image_params.end(); i++)
00337 {
00338 double nyaw, npitch, nroll, nx, ny, nz, npy, npp;
00339 i->second.Move(&rotation_matrix, nyaw, npitch, nroll, nx, ny, nz, npy, npp);
00340 src_images[count] = helper->GetPanoramaPtr()->getSrcImage(i->first);
00341 src_images[count].setX(nx);
00342 src_images[count].setY(ny);
00343 src_images[count].setZ(nz);
00344 src_images[count].setTranslationPlaneYaw(npy);
00345 src_images[count].setTranslationPlanePitch(npp);
00346 src_images[count].setYaw(nyaw);
00347 src_images[count].setPitch(npitch);
00348 src_images[count].setRoll(nroll);
00349 count++;
00350 }
00351 GlobalCmdHist::getInstance().addCommand(
00352 new PT::UpdateSrcImagesCmd(*helper->GetPanoramaPtr(),
00353 draging_images,
00354 src_images)
00355 );
00356
00357 image_params.clear();
00358
00359 helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or ctrl-drag."));
00360 }
00361 }
00362
00363
00364
00365 void DragTool::ParamStore::Set(HuginBase::SrcPanoImage *img)
00366 {
00367 yaw = img->getYaw();
00368 pitch = img->getPitch();
00369 roll = img->getRoll();
00370 TrX = img->getX();
00371 TrY = img->getY();
00372 TrZ = img->getZ();
00373 Tpy = img->getTranslationPlaneYaw();
00374 Tpp = img->getTranslationPlanePitch();
00375 }
00376
00377 void DragTool::ParamStore::Move(Matrix3 *matrix,
00378 double &yaw_out, double &pitch_out, double &roll_out,
00379 double &TrX_out, double &TrY_out, double &TrZ_out,
00380 double &Tpy_out, double &Tpp_out)
00381 {
00382 Matrix3 start, output_matrix;
00383
00384 start.SetRotationPT(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), DEG_TO_RAD(roll));
00385
00386 output_matrix = *matrix * start;
00387
00388 output_matrix.GetRotationPT(yaw_out, pitch_out, roll_out);
00389 yaw_out = RAD_TO_DEG(yaw_out);
00390 pitch_out = RAD_TO_DEG(pitch_out);
00391 roll_out = RAD_TO_DEG(roll_out);
00392
00393 if(TrX != 0.0 || TrY != 0.0 || TrZ != 0.0)
00394 {
00395
00396 Vector3 vecRot=matrix->Inverse().TransformVector(Vector3(TrZ, TrX, TrY));
00397 TrX_out=vecRot.y;
00398 TrY_out=vecRot.z;
00399 TrZ_out=vecRot.x;
00400
00401 start.SetRotationPT(DEG_TO_RAD(Tpy), DEG_TO_RAD(Tpp), 0.0);
00402 output_matrix = (*matrix) * start;
00403 double dummy;
00404 output_matrix.GetRotationPT(Tpy_out, Tpp_out, dummy);
00405 Tpy_out=RAD_TO_DEG(Tpy_out);
00406 Tpp_out=RAD_TO_DEG(Tpp_out);
00407 }
00408 else
00409 {
00410 TrX_out=0;
00411 TrY_out=0;
00412 TrZ_out=0;
00413 Tpy_out=0;
00414 Tpp_out=0;
00415 };
00416 }
00417
00418 void DragTool::SetRotationMatrix(double yaw_shift, double pitch_shift,
00419 double roll_shift,
00420 double yaw_start, double pitch_start,
00421 double roll_start)
00422 {
00423 Matrix3 y1_mat, r_mat, y2_mat, p1_mat, p2_mat;
00424
00425 y1_mat.SetRotationPT(-DEG_TO_RAD(yaw_start), 0.0, 0.0);
00426 p1_mat.SetRotationPT(0.0, DEG_TO_RAD(pitch_start), 0.0);
00427
00428 r_mat.SetRotationPT(0.0, 0.0, roll_shift);
00429
00430 p2_mat.SetRotationPT(0.0, -DEG_TO_RAD(pitch_shift), 0.0);
00431 y2_mat.SetRotationPT(DEG_TO_RAD(yaw_shift), 0.0, 0.0);
00432
00433 rotation_matrix = y2_mat * p2_mat * r_mat *p1_mat * y1_mat;
00434 }
00435
00436 void PreviewDragTool::ReallyAfterDrawImagesEvent()
00437 {
00438
00439 HuginBase::PanoramaOptions *opts = helper->GetViewStatePtr()->GetOptions();
00440 double width = (double) opts->getSize().width(),
00441 height = (double) opts->getSize().height();
00442
00443 helper->GetViewStatePtr()->GetTextureManager()->DisableTexture();
00444 glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
00445 glEnable(GL_BLEND);
00446 glColor3f(1.0, 1.0, 1.0);
00447 glPushMatrix();
00448 glTranslatef(-0.5, -0.5, -0.5);
00449 glBegin(GL_LINES);
00450 glVertex2f(width / 2.0, 0.0);
00451 glVertex2f(width / 2.0, height);
00452 glVertex2f(0.0, height / 2.0);
00453 glVertex2f(width, height / 2.0);
00454 glEnd();
00455
00456 if (drag_roll)
00457 {
00458
00459
00460 double distance = width * width + height * height,
00461 angle = start_angle;
00462 glPushMatrix();
00463 glTranslatef(centre.x, centre.y, 0.0);
00464 glBegin(GL_LINES);
00465
00466 glVertex2d(0.0, 0.0);
00467 glVertex2f(distance * cos(angle), distance * sin(angle));
00468
00469 angle += shift_angle;
00470 glVertex2d(0.0, 0.0);
00471 glVertex2f(distance * cos(angle), distance * sin(angle));
00472 glEnd();
00473 glPopMatrix();
00474 }
00475 if (drag_pitch || drag_yaw)
00476 {
00477
00478
00479
00480 glBegin(GL_LINE_STRIP);
00481 for (double t = 0.0; t <= 1.0; t+= 0.005)
00482 {
00483 double x, y, ti = 1.0 - t;
00484 helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage(
00485 x, y,
00486 t * start_coordinates.x + ti *shift_coordinates.x,
00487 t * start_coordinates.y + ti *shift_coordinates.y);
00488 glVertex2d(x, y);
00489 }
00490 glEnd();
00491 }
00492 glPopMatrix();
00493 glDisable(GL_BLEND);
00494 glEnable(GL_TEXTURE_2D);
00495 }
00496
00497 void OverviewDragTool::ReallyAfterDrawImagesEvent()
00498 {
00499
00500 }
00501