diff --git a/MainWindow.cpp b/MainWindow.cpp index 52160a8..98b6a39 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -701,6 +701,8 @@ void MainWindow::createLayout() paintList = new QListWidget; paintList->setSelectionMode(QAbstractItemView::SingleSelection); paintList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + paintList->setDefaultDropAction(Qt::MoveAction); + paintList->setDragDropMode(QAbstractItemView::InternalMove); paintList->setMinimumWidth(PAINT_LIST_MINIMUM_WIDTH); // Create mapping list. @@ -1221,7 +1223,7 @@ void MainWindow::addMappingItem(uid mappingId) icon = QIcon(":/images/draw-triangle.png"); if (paintType == "color") - mapper = Mapper::ptr(new ColorMapper(mapping)); + mapper = Mapper::ptr(new PolygonColorMapper(mapping)); else mapper = Mapper::ptr(new TriangleTextureMapper(textureMapping)); } @@ -1231,7 +1233,7 @@ void MainWindow::addMappingItem(uid mappingId) label = QString(shapeType == "mesh" ? "Mesh %1" : "Quad %1").arg(mappingId); icon = QIcon(":/images/draw-rectangle-2.png"); if (paintType == "color") - mapper = Mapper::ptr(new ColorMapper(mapping)); + mapper = Mapper::ptr(new PolygonColorMapper(mapping)); else mapper = Mapper::ptr(new MeshTextureMapper(textureMapping)); } diff --git a/Mapper.cpp b/Mapper.cpp index f94fb24..0f89a2b 100644 --- a/Mapper.cpp +++ b/Mapper.cpp @@ -19,6 +19,7 @@ */ #include "Mapper.h" +#include "MainWindow.h" #include "unused.h" Mapper::Mapper(Mapping::ptr mapping) @@ -157,18 +158,18 @@ ColorMapper::ColorMapper(Mapping::ptr mapping) Q_CHECK_PTR(color); } -#include "MainWindow.h" -void ColorMapper::draw(QPainter* painter) +void PolygonColorMapper::draw(QPainter* painter) { painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(color->getColor()); // Draw shape as polygon. - painter->drawPolygon(_mapping->getShape()->toPolygon()); + Polygon* poly = (Polygon*)_mapping->getShape().get(); + painter->drawPolygon(poly->toPolygon()); } -void ColorMapper::drawControls(QPainter* painter) +void PolygonColorMapper::drawControls(QPainter* painter) { UNUSED(painter); } diff --git a/Mapper.h b/Mapper.h index d4c8860..f6a635d 100644 --- a/Mapper.h +++ b/Mapper.h @@ -61,15 +61,16 @@ class Mapper : public QObject { Q_OBJECT -protected: - Mapping::ptr _mapping; - public: typedef std::tr1::shared_ptr ptr; +protected: + Mapping::ptr _mapping; + Mapper(Mapping::ptr mapping); virtual ~Mapper(); +public: virtual QWidget* getPropertiesEditor(); virtual void draw(QPainter* painter) = 0; virtual void drawControls(QPainter* painter) = 0; @@ -110,16 +111,24 @@ class ColorMapper : public Mapper { Q_OBJECT -public: +protected: ColorMapper(Mapping::ptr mapping); virtual ~ColorMapper() {} - virtual void draw(QPainter* painter); - virtual void drawControls(QPainter* painter); - protected: std::tr1::shared_ptr color; +}; +class PolygonColorMapper : public ColorMapper +{ + Q_OBJECT + +public: + PolygonColorMapper(Mapping::ptr mapping) : ColorMapper(mapping) {} + virtual ~PolygonColorMapper() {} + + virtual void draw(QPainter* painter); + virtual void drawControls(QPainter* painter); }; class MeshColorMapper : public ColorMapper @@ -140,7 +149,8 @@ private: QtVariantProperty* _meshItem; }; -class EllipseColorMapper : public ColorMapper { +class EllipseColorMapper : public ColorMapper +{ Q_OBJECT public: diff --git a/Math.h b/Math.h index 2557ef9..b3decbb 100644 --- a/Math.h +++ b/Math.h @@ -28,4 +28,7 @@ inline double degreesToRadians(double degrees) { return degrees / 180.0 * M_PI; inline float radiansToDegrees(float radians) { return radians / M_PI * 180.0f; } inline double radiansToDegrees(double radians) { return radians / M_PI * 180.0; } +// Wrap value around ie. wrapAround(-1, 3) ==> 2 +inline int wrapAround(int index, int max) { return (index + max) % max; } + #endif /* MATH_H_ */ diff --git a/Shape.cpp b/Shape.cpp index c43c980..53ba1b0 100644 --- a/Shape.cpp +++ b/Shape.cpp @@ -19,45 +19,6 @@ #include "Shape.h" -bool Shape::includesPoint(qreal x, qreal y) -{ - return toPolygon().containsPoint(QPointF(x, y), Qt::OddEvenFill); -// QVector::iterator prev; -// int left = 0, right = 0, maxy, miny; -// for (QVector::iterator it = vertices.begin() ; -// it != vertices.end(); it++) -// { -// if (!prev) { -// prev = vertices.back(); -// } -// miny = qMin(it->y(), prev->y()); -// maxy = qMax(it->y(), prev->y()); -// -// if (y > miny && y < maxy) { -// if (prev->x() == it->x()) -// { -// if (x < it->x()) -// right++; -// else left++; -// } -// else -// { -// double slope = (it->y() - prev->y()) / (it->x() - prev->x()); -// double offset = it->y() - slope * it->x(); -// int xintersect = int((y - offset ) / slope); -// if (x < xintersect) -// right++; -// else left++; -// } -// } -// prev = *it; -// } -// if (right % 2 && left % 2) -// return true; -// return false; -} - - void Shape::translate(int x, int y) { for (QVector::iterator it = vertices.begin() ; @@ -68,7 +29,60 @@ void Shape::translate(int x, int y) } } -QPolygonF Shape::toPolygon() const +void Polygon::setVertex(int i, const QPointF& v) +{ + // Weird, but nothing to do. + if (nVertices() <= 3) + { + Shape::setVertex(i, v); + return; + } + + QPointF realV = v; + + // Look at the two adjunct segments to vertex i and see if they + // intersect with any non-adjacent segments. + + // Construct the list of segments (with the new candidate vertex). + QVector segments = _getSegments(); + int prev = wrapAround(i - 1, segments.size()); + int next = wrapAround(i + 1, segments.size()); + segments[prev] = QLineF(vertices[prev], v); + segments[i] = QLineF(v, vertices[next]); + + // For each adjunct segment. + for (int adj=0; adj<2; adj++) + { + int idx = wrapAround(i + adj - 1, segments.size()); + for (int j=0; j Polygon::_getSegments() const +{ + QVector segments; + for (int i=0; i::const_iterator it = vertices.begin() ; @@ -116,6 +130,12 @@ QPolygonF Mesh::toPolygon() const return polygon; } +void Mesh::setVertex(int i, const QPointF& v) +{ + // TODO + Shape::setVertex(i, v); +} + void Mesh::resizeVertices2d(IndexVector2d& vertices2d, int nColumns, int nRows) { vertices2d.resize(nColumns); diff --git a/Shape.h b/Shape.h index b625149..6d19692 100644 --- a/Shape.h +++ b/Shape.h @@ -40,11 +40,7 @@ #include "Math.h" /** - * Point (or vertex) on the 2-D canvas. - */ - -/** - * Series of vertices. (points) + * Shape represented by a series of control points. */ class Shape { @@ -68,11 +64,10 @@ public: virtual void setVertex(int i, const QPointF& v) { - vertices[i].setX(v.x()); - vertices[i].setY(v.y()); + vertices[i] = v; } - virtual void setVertex(int i, double x, double y) + virtual void setVertex(int i, qreal x, qreal y) { setVertex(i, QPointF(x, y)); } @@ -83,17 +78,15 @@ public: * Algorithm should work for all polygons, including non-convex * Found at http://www.cs.tufts.edu/comp/163/notes05/point_inclusion_handout.pdf */ - virtual bool includesPoint(qreal x, qreal y); - - virtual bool includesPoint(const QPointF& p) { - return includesPoint(p.x(), p.y()); + virtual bool includesPoint(qreal x, qreal y) { + return includesPoint(QPoint(x, y)); } + virtual bool includesPoint(const QPointF& p) = 0; + /* Translate all vertices of shape by the vector (x,y) */ virtual void translate(int x, int y); - virtual QPolygonF toPolygon() const; - protected: QVector vertices; @@ -104,10 +97,33 @@ protected: }; +/** + * This class represents a simple polygon (ie. the control points are vertices). + */ +class Polygon : public Shape { +public: + Polygon() {} + Polygon(QVector vertices_) : Shape(vertices_) {} + virtual ~Polygon() {} + + virtual QPolygonF toPolygon() const; + + virtual bool includesPoint(const QPointF& p) { + return toPolygon().containsPoint(p, Qt::OddEvenFill); + } + + // Override the parent, checking to make sure the vertices are displaced correctly. + virtual void setVertex(int i, const QPointF& v); + +protected: + // Returns all line segments of the polygon. + QVector _getSegments() const; +}; + /** * Four-vertex shape. */ -class Quad : public Shape +class Quad : public Polygon { public: Quad() {} @@ -126,7 +142,7 @@ public: /** * Triangle shape. */ -class Triangle : public Shape +class Triangle : public Polygon { public: Triangle() {} @@ -140,8 +156,8 @@ public: virtual QString getType() const { return "triangle"; } }; -class Mesh : public Quad { - +class Mesh : public Quad +{ typedef QVector > IndexVector2d; public: @@ -156,6 +172,9 @@ public: virtual QPolygonF toPolygon() const; + // Override the parent, checking to make sure the vertices are displaced correctly. + virtual void setVertex(int i, const QPointF& v); + QPointF getVertex2d(int i, int j) const { return vertices[_vertices2d[i][j]]; diff --git a/TODO b/TODO index 0f71c57..f2d28b7 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,7 @@ Code ---- * MapperGLCanvas has a strange name considering we also have a Mapper class; actually I'm thinking we should rename Mapper to MappingView or something (since a Mapper is actually the View of the Mapping class) -* Override includesPoint() in Mesh +* DONE Override includesPoint() in Mesh * video gstreamer Packaging