Draw rectangles and ellipses!
authorunc0rr
Fri, 18 Oct 2013 15:26:43 +0400
changeset 9551 61f160dfd0f1
parent 9549 ac5c1f691ce2
child 9553 f92d43816186
Draw rectangles and ellipses!
QTfrontend/drawmapscene.cpp
QTfrontend/drawmapscene.h
QTfrontend/ui/page/pagedrawmap.cpp
QTfrontend/ui/page/pagedrawmap.h
QTfrontend/ui/widget/drawmapwidget.cpp
QTfrontend/ui/widget/drawmapwidget.h
--- a/QTfrontend/drawmapscene.cpp	Tue Oct 15 23:07:22 2013 +0400
+++ b/QTfrontend/drawmapscene.cpp	Fri Oct 18 15:26:43 2013 +0400
@@ -20,6 +20,7 @@
 #include <QGraphicsPathItem>
 #include <QtEndian>
 #include <QDebug>
+#include <math.h>
 
 #include "drawmapscene.h"
 
@@ -44,6 +45,8 @@
     setBackgroundBrush(m_eraser);
     m_isErasing = false;
 
+    m_pathType = Polyline;
+
     m_pen.setWidth(76);
     m_pen.setJoinStyle(Qt::RoundJoin);
     m_pen.setCapStyle(Qt::RoundCap);
@@ -61,18 +64,41 @@
     {
         QPainterPath path = m_currPath->path();
 
-        if(mouseEvent->modifiers() & Qt::ControlModifier)
+        switch (m_pathType)
         {
-            int c = path.elementCount();
-            QPointF pos = mouseEvent->scenePos();
-            path.setElementPositionAt(c - 1, pos.x(), pos.y());
+        case Polyline:
+            if(mouseEvent->modifiers() & Qt::ControlModifier)
+            {
+                int c = path.elementCount();
+                QPointF pos = mouseEvent->scenePos();
+                path.setElementPositionAt(c - 1, pos.x(), pos.y());
 
+            }
+            else
+            {
+                path.lineTo(mouseEvent->scenePos());
+                paths.first().points.append(mouseEvent->scenePos().toPoint());
+            }
+            break;
+        case Rectangle: {
+            path = QPainterPath();
+            QPointF p1 = paths.first().initialPoint;
+            QPointF p2 = mouseEvent->scenePos();
+            path.moveTo(p1);
+            path.lineTo(p1.x(), p2.y());
+            path.lineTo(p2);
+            path.lineTo(p2.x(), p1.y());
+            path.lineTo(p1);
+            break;
+            }
+        case Ellipse: {
+            path = QPainterPath();
+            QList<QPointF> points = makeEllipse(paths.first().initialPoint, mouseEvent->scenePos());
+            path.addPolygon(QPolygonF(QVector<QPointF>::fromList(points)));
+            break;
         }
-        else
-        {
-            path.lineTo(mouseEvent->scenePos());
-            paths.first().points.append(mouseEvent->scenePos().toPoint());
         }
+
         m_currPath->setPath(path);
 
         emit pathChanged();
@@ -96,7 +122,8 @@
     PathParams params;
     params.width = serializePenWidth(m_pen.width());
     params.erasing = m_isErasing;
-    params.points = QList<QPoint>() << mouseEvent->scenePos().toPoint();
+    params.initialPoint = mouseEvent->scenePos().toPoint();
+    params.points = QList<QPoint>() << params.initialPoint;
     paths.prepend(params);
     m_currPath->setPath(path);
 
@@ -107,10 +134,33 @@
 {
     if (m_currPath)
     {
-        QPainterPath path = m_currPath->path();
-        path.lineTo(mouseEvent->scenePos());
-        paths.first().points.append(mouseEvent->scenePos().toPoint());
-        m_currPath->setPath(path);
+        switch (m_pathType)
+        {
+        case Polyline: {
+            QPainterPath path = m_currPath->path();
+            path.lineTo(mouseEvent->scenePos());
+            paths.first().points.append(mouseEvent->scenePos().toPoint());
+            m_currPath->setPath(path);
+            break;
+        }
+        case Rectangle: {
+            QPoint p1 = paths.first().initialPoint;
+            QPoint p2 = mouseEvent->scenePos().toPoint();
+            QList<QPoint> rpoints;
+            rpoints << p1 << QPoint(p1.x(), p2.y()) << p2 << QPoint(p2.x(), p1.y()) << p1;
+            paths.first().points = rpoints;
+            break;
+        }
+        case Ellipse:
+            QPoint p1 = paths.first().initialPoint;
+            QPoint p2 = mouseEvent->scenePos().toPoint();
+            QList<QPointF> points = makeEllipse(p1, p2);
+            QList<QPoint> epoints;
+            foreach(const QPointF & p, points)
+                epoints.append(p.toPoint());
+            paths.first().points = epoints;
+            break;
+        }
 
         simplifyLast();
 
@@ -383,3 +433,29 @@
 {
     return width * 10 + 6;
 }
+
+void DrawMapScene::setPathType(PathType pathType)
+{
+    m_pathType = pathType;
+}
+
+QList<QPointF> DrawMapScene::makeEllipse(const QPointF &center, const QPointF &corner)
+{
+    QList<QPointF> l;
+    qreal r = (center - corner).manhattanLength();
+    qreal rx = qAbs(center.x() - corner.x());
+    qreal ry = qAbs(center.y() - corner.y());
+
+    if(r < 4)
+    {
+        l.append(center);
+    } else
+    {
+        qreal angleDelta = 12 / r;
+        for(qreal angle = 0.0; angle < 2*M_PI; angle += angleDelta)
+            l.append(center + QPointF(rx * cos(angle), ry * sin(angle)));
+        l.append(l.first());
+    }
+
+    return l;
+}
--- a/QTfrontend/drawmapscene.h	Tue Oct 15 23:07:22 2013 +0400
+++ b/QTfrontend/drawmapscene.h	Fri Oct 18 15:26:43 2013 +0400
@@ -29,6 +29,7 @@
 {
     quint8 width;
     bool erasing;
+    QPoint initialPoint;
     QList<QPoint> points;
 };
 
@@ -38,6 +39,12 @@
 {
         Q_OBJECT
     public:
+        enum PathType {
+            Polyline  = 0,
+            Rectangle = 1,
+            Ellipse   = 2
+        };
+
         explicit DrawMapScene(QObject *parent = 0);
 
         QByteArray encode();
@@ -54,6 +61,7 @@
         void setErasing(bool erasing);
         void showCursor();
         void hideCursor();
+        void setPathType(PathType pathType);
 
     private:
         QPen m_pen;
@@ -67,6 +75,7 @@
         QGraphicsEllipseItem * m_cursor;
         bool m_isCursorShown;
         QByteArray m_specialPoints;
+        PathType m_pathType;
 
         virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);
         virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);
@@ -77,6 +86,7 @@
 
         quint8 serializePenWidth(int width);
         int deserializePenWidth(quint8 width);
+        QList<QPointF> makeEllipse(const QPointF & center, const QPointF & corner);
 };
 
 #endif // DRAWMAPSCENE_H
--- a/QTfrontend/ui/page/pagedrawmap.cpp	Tue Oct 15 23:07:22 2013 +0400
+++ b/QTfrontend/ui/page/pagedrawmap.cpp	Fri Oct 18 15:26:43 2013 +0400
@@ -20,6 +20,7 @@
 #include <QPushButton>
 #include <QFileDialog>
 #include <QCheckBox>
+#include <QRadioButton>
 
 #include "pagedrawmap.h"
 #include "drawmapwidget.h"
@@ -32,12 +33,22 @@
     cbEraser = new QCheckBox(tr("Eraser"), this);
     pageLayout->addWidget(cbEraser, 0, 0);
     pbUndo = addButton(tr("Undo"), pageLayout, 1, 0);
-    pbClear = addButton(tr("Clear"), pageLayout, 2, 0);
-    pbLoad = addButton(tr("Load"), pageLayout, 3, 0);
-    pbSave = addButton(tr("Save"), pageLayout, 4, 0);
+
+    rbPolyline = new QRadioButton(tr("Polyline"), this);
+    pageLayout->addWidget(rbPolyline, 2, 0);
+    rbRectangle = new QRadioButton(tr("Rectangle"), this);
+    pageLayout->addWidget(rbRectangle, 3, 0);
+    rbEllipse = new QRadioButton(tr("Ellipse"), this);
+    pageLayout->addWidget(rbEllipse, 4, 0);
+
+    rbPolyline->setChecked(true);
+
+    pbClear = addButton(tr("Clear"), pageLayout, 5, 0);
+    pbLoad = addButton(tr("Load"), pageLayout, 6, 0);
+    pbSave = addButton(tr("Save"), pageLayout, 7, 0);
 
     drawMapWidget = new DrawMapWidget(this);
-    pageLayout->addWidget(drawMapWidget, 0, 1, 6, 1);
+    pageLayout->addWidget(drawMapWidget, 0, 1, 9, 1);
 
     return pageLayout;
 }
@@ -49,6 +60,10 @@
     connect(pbClear, SIGNAL(clicked()), drawMapWidget, SLOT(clear()));
     connect(pbLoad, SIGNAL(clicked()), this, SLOT(load()));
     connect(pbSave, SIGNAL(clicked()), this, SLOT(save()));
+
+    connect(rbPolyline, SIGNAL(toggled(bool)), this, SLOT(pathTypeSwitched(bool)));
+    connect(rbRectangle, SIGNAL(toggled(bool)), this, SLOT(pathTypeSwitched(bool)));
+    connect(rbEllipse, SIGNAL(toggled(bool)), this, SLOT(pathTypeSwitched(bool)));
 }
 
 PageDrawMap::PageDrawMap(QWidget* parent) : AbstractPage(parent)
@@ -71,3 +86,13 @@
     if(!fileName.isEmpty())
         drawMapWidget->save(fileName);
 }
+
+void PageDrawMap::pathTypeSwitched(bool b)
+{
+    if(b)
+    {
+        if(rbPolyline->isChecked()) drawMapWidget->setPathType(DrawMapScene::Polyline);
+        else if(rbRectangle->isChecked()) drawMapWidget->setPathType(DrawMapScene::Rectangle);
+        else if(rbEllipse->isChecked()) drawMapWidget->setPathType(DrawMapScene::Ellipse);
+    }
+}
--- a/QTfrontend/ui/page/pagedrawmap.h	Tue Oct 15 23:07:22 2013 +0400
+++ b/QTfrontend/ui/page/pagedrawmap.h	Fri Oct 18 15:26:43 2013 +0400
@@ -22,6 +22,7 @@
 #include "AbstractPage.h"
 
 class DrawMapWidget;
+class QRadioButton;
 
 class PageDrawMap : public AbstractPage
 {
@@ -42,10 +43,14 @@
         QPushButton * pbLoad;
         QPushButton * pbSave;
         QCheckBox * cbEraser;
+        QRadioButton * rbPolyline;
+        QRadioButton * rbRectangle;
+        QRadioButton * rbEllipse;
 
     private slots:
         void load();
         void save();
+        void pathTypeSwitched(bool b);
 };
 
 #endif
--- a/QTfrontend/ui/widget/drawmapwidget.cpp	Tue Oct 15 23:07:22 2013 +0400
+++ b/QTfrontend/ui/widget/drawmapwidget.cpp	Fri Oct 18 15:26:43 2013 +0400
@@ -123,6 +123,11 @@
     if(m_scene) m_scene->setErasing(erasing);
 }
 
+void DrawMapWidget::setPathType(DrawMapScene::PathType pathType)
+{
+    if(m_scene) m_scene->setPathType(pathType);
+}
+
 void DrawMapWidget::save(const QString & fileName)
 {
     if(m_scene)
@@ -192,7 +197,7 @@
     QGraphicsView::setScene(scene);
 }
 
-// Why don't I ever recieve this event?
+// Why don't I ever receive this event?
 void DrawMapView::enterEvent(QEvent *event)
 {
     if(m_scene)
--- a/QTfrontend/ui/widget/drawmapwidget.h	Tue Oct 15 23:07:22 2013 +0400
+++ b/QTfrontend/ui/widget/drawmapwidget.h	Fri Oct 18 15:26:43 2013 +0400
@@ -100,6 +100,7 @@
         void setErasing(bool erasing);
         void save(const QString & fileName);
         void load(const QString & fileName);
+        void setPathType(DrawMapScene::PathType pathType);
 
     protected:
         void changeEvent(QEvent *e);