From 35fb1ca821a29ff72d8c9ced7794b39809b93b6a Mon Sep 17 00:00:00 2001 From: Vasilis Liaskovitis Date: Tue, 3 Dec 2013 01:14:17 +0200 Subject: [PATCH] Implement shape drag-and-drop A user may find it useful in some cases to drag and drop a whole shape, instead of moving each vertex separately. This patch implements shape drag-and-drop by pressing and holding the right mouse button. Point inclusion algorithm should work for non-convex and convex polygons, as suggested in http://www.cs.tufts.edu/comp/163/notes05/point_inclusion_handout.pdf --- MapperGLCanvas.cpp | 30 ++++++++++++++++++++++++++ MapperGLCanvas.h | 2 ++ Shape.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/MapperGLCanvas.cpp b/MapperGLCanvas.cpp index 1261b25..275ee44 100644 --- a/MapperGLCanvas.cpp +++ b/MapperGLCanvas.cpp @@ -119,12 +119,22 @@ void MapperGLCanvas::mousePressEvent(QMouseEvent* event) _mousepressed = true; } } + if (event->buttons() & Qt::RightButton) + { + Shape* shape = getCurrentShape(); + if (shape->includesPoint(xmouse, ymouse)) + { + _shapegrabbed = true; + _shapefirstgrab = true; + } + } } void MapperGLCanvas::mouseReleaseEvent(QMouseEvent* event) { // std::cout << "Mouse Release event " << std::endl; _mousepressed = false; + _shapegrabbed = false; } void MapperGLCanvas::mouseMoveEvent(QMouseEvent* event) @@ -145,6 +155,26 @@ void MapperGLCanvas::mouseMoveEvent(QMouseEvent* event) emit quadChanged(); } } + else if (_shapegrabbed) + { + // std::cout << "Move event " << std::endl; + Shape* shape = getCurrentShape(); + static Point p(0,0); + if (shape) + { + if (_shapefirstgrab == false) + { + shape->translate(event->x() - p.x, event->y() - p.y); + update(); + emit quadChanged(); + } + else + _shapefirstgrab = false; + } + p.x = event->x(); + p.y = event->y(); + + } } void MapperGLCanvas::keyPressEvent(QKeyEvent* event) diff --git a/MapperGLCanvas.h b/MapperGLCanvas.h index 4870aa8..010c97d 100644 --- a/MapperGLCanvas.h +++ b/MapperGLCanvas.h @@ -65,6 +65,8 @@ private: virtual void doDraw() = 0; void exitDraw(); bool _mousepressed; + bool _shapegrabbed; + bool _shapefirstgrab; signals: void quadChanged(); diff --git a/Shape.h b/Shape.h index 54ef9a3..03177db 100644 --- a/Shape.h +++ b/Shape.h @@ -22,6 +22,7 @@ #include #include +#include /** * Point (or vertex) on the 2-D canvas. @@ -68,6 +69,57 @@ public: } void setActiveVertex(int x) {active_vertex = x;} int getActiveVertex() {return active_vertex;} + /** Return true if Shape includes point (x,y), false otherwise + * Algorithm should work for all polygons, including non-convex + * Found at http://www.cs.tufts.edu/comp/163/notes05/point_inclusion_handout.pdf + */ + bool includesPoint(int x, int y) + { + Point *prev = NULL, *cur; + int left = 0, right = 0, maxy, miny; + for (std::vector::iterator it = vertices.begin() ; it != + vertices.end(); it++) + { + if (!prev) { + prev = &vertices.back(); + } + cur = &(*it); + miny = std::min(cur->y, prev->y); + maxy = std::max(cur->y, prev->y); + + if (y > miny && y < maxy) { + if (prev->x == cur->x) + { + if (x < cur->x) + right++; + else left++; + } + else + { + double slope = (cur->y - prev->y) / (cur->x - prev->x); + double offset = cur->y - slope * cur->x; + int xintersect = int((y - offset ) / slope); + if (x < xintersect) + right++; + else left++; + } + } + prev = &(*it); + } + if (right % 2 && left % 2) + return true; + return false; + } + /* Translate all vertices of shape by the vector (x,y) */ + void translate(int x, int y) + { + for (std::vector::iterator it = vertices.begin() ; it != + vertices.end(); ++it) + { + it->x += x; + it->y += y; + } + } }; /**