File indexing completed on 2024-05-19 03:53:36

0001 #include "image/imagepainter.h"
0002 #include "image/polygon.h"
0003 
0004 #include <QGraphicsItem>
0005 
0006 
0007 ImagePainter::ImagePainter(Container* parent) :
0008     Painter(parent),
0009     m_shape(Shape::Polygon)
0010 {
0011     m_parent->setCurrentObject(new Polygon(m_parent->currentObject()->objClass()));
0012     m_parent->viewport()->installEventFilter(m_parent);
0013     m_parent->viewport()->setMouseTracking(false);
0014 }
0015 
0016 ImagePainter::~ImagePainter()
0017 {
0018     if (m_items.isEmpty())
0019         return;
0020 
0021     for (QGraphicsItem* item : m_items)
0022         m_parent->scene()->removeItem(item);
0023 
0024     m_items.clear();
0025 
0026     m_parent->scene()->removeItem(m_currentItem);
0027 }
0028 
0029 void ImagePainter::paint(QPoint point, bool isDragging)
0030 {
0031     QGraphicsPixmapItem* currentItem = static_cast<QGraphicsPixmapItem*>(m_currentItem);
0032     if (currentItem != nullptr) {
0033         QPointF clickedPoint = m_parent->mapToScene(point);
0034 
0035         bool isImageClicked = m_parent->scene()->itemAt(clickedPoint, m_parent->transform()) == currentItem;
0036         
0037         Polygon* currentPolygon = static_cast<Polygon*>(m_parent->currentObject());
0038 
0039         if (m_shape == Shape::Polygon) {
0040             int idxSavedPolygClicked = -1;
0041             QPointF scaledClickedPoint = QPointF(-m_currentItem->pos());
0042             scaledClickedPoint += QPointF(scaledClickedPoint.x()/m_scaleW, scaledClickedPoint.y()/m_scaleH);
0043             for (int i = 0; i < m_parent->savedObjects().size(); i++) {
0044                 const Polygon* polygon = static_cast<const Polygon*>(m_parent->savedObjects()[i]);
0045                 if (polygon->containsPoint(scaledClickedPoint, Qt::OddEvenFill)) {
0046                     idxSavedPolygClicked = i;
0047                     break;
0048                 }
0049             }
0050 
0051             bool isSavedPolygClicked = idxSavedPolygClicked != -1;
0052             if (isSavedPolygClicked) {
0053                 if (isDragging)
0054                     return;
0055                 delete currentPolygon;
0056                 m_parent->setCurrentObject(m_parent->savedObjects()[idxSavedPolygClicked]);
0057                 m_parent->savedObjects().remove(idxSavedPolygClicked);
0058                 currentPolygon = static_cast<Polygon*>(m_parent->currentObject());
0059                 currentPolygon->unscale(m_currentItem->pos(), m_scaleW, m_scaleH);
0060                 currentPolygon->pop_back();
0061             }
0062 
0063             bool isPolygFirstPtClicked = false;
0064             if (!currentPolygon->empty()) {
0065                 QPointF cPolygFirstPt = currentPolygon->first();
0066                 QRectF cPolygFirstPtRect(cPolygFirstPt, QPointF(cPolygFirstPt.x() + 10, cPolygFirstPt.y() + 10));
0067                 isPolygFirstPtClicked = cPolygFirstPtRect.contains(clickedPoint);
0068                 if (isPolygFirstPtClicked)
0069                     clickedPoint = cPolygFirstPt;
0070             }
0071 
0072             if (isSavedPolygClicked || isPolygFirstPtClicked || isImageClicked) {
0073                 *currentPolygon << clickedPoint;
0074 
0075                 if (currentPolygon->size() > 1 && currentPolygon->isClosed()) {
0076                     currentPolygon->scale(m_currentItem->pos(), m_scaleW, m_scaleH);
0077                     m_parent->appendObject(currentPolygon);
0078                     m_parent->setCurrentObject(new Polygon(currentPolygon->objClass()));
0079                 }
0080 
0081                 repaint();
0082             }
0083         }
0084         else if (m_shape == Shape::Rectangle) {
0085             bool toSave = point.isNull() && currentPolygon->size() > 1;
0086             if (isImageClicked) {
0087                 if (currentPolygon->empty())
0088                     *currentPolygon << clickedPoint;
0089 
0090                 else {
0091                     QPointF firstPt = currentPolygon->first();
0092                     if (isDragging) {
0093                         currentPolygon->clear();
0094                         *currentPolygon << firstPt;
0095                     }
0096                     else
0097                         toSave = true;
0098                     *currentPolygon << QPointF(clickedPoint.x(), firstPt.y()) << clickedPoint << QPointF(firstPt.x(), clickedPoint.y()) << firstPt;
0099                 }
0100 
0101                 repaint();
0102             }
0103             if (toSave) {
0104                 currentPolygon->scale(m_currentItem->pos(), m_scaleW, m_scaleH);
0105                 m_parent->appendObject(currentPolygon);
0106                 m_parent->setCurrentObject(new Polygon(m_parent->currentObject()->objClass()));
0107             }
0108         }
0109     }
0110 }
0111 
0112 void ImagePainter::changeItem(const QString& filepath)
0113 {
0114     QGraphicsPixmapItem* pixmapItem = nullptr;
0115 
0116     if (filepath != "") {
0117         QPixmap image(filepath);
0118         QPixmap scaledImage;
0119 
0120         if (image.height() >= 1280)
0121             scaledImage = image.scaledToHeight(int(1280 * 0.8));
0122 
0123         if (image.width() >= 960)
0124             scaledImage = image.scaledToWidth(int(960 * 0.8));
0125 
0126         if (!scaledImage.isNull()) {
0127             m_scaleW = qreal(scaledImage.width()) / qreal(image.width());
0128             m_scaleH = qreal(scaledImage.height()) / qreal(image.height());
0129             image = scaledImage;
0130         }
0131         else {
0132             m_scaleW = 1.0;
0133             m_scaleH = 1.0;
0134         }
0135 
0136         pixmapItem = m_parent->scene()->addPixmap(image);
0137 
0138         int x_scene = int(m_parent->scene()->width() / 2);
0139         int y_scene = int(m_parent->scene()->height() / 2);
0140         int x_image = int(image.width() / 2);
0141         int y_image = int(image.height() / 2);
0142 
0143         pixmapItem->setPos(x_scene - x_image, y_scene - y_image);
0144     }
0145 
0146     m_currentItem = pixmapItem;
0147     m_filepath = filepath;
0148 }
0149 
0150 void ImagePainter::repaint()
0151 {
0152     for (QGraphicsItem* item : m_items)
0153         m_parent->scene()->removeItem(item);
0154 
0155     m_items.clear();
0156 
0157     for (MarkedObject* obj : m_parent->savedObjects())
0158         paintObject(obj);
0159 
0160     paintObject(m_parent->currentObject());
0161 }
0162 
0163 void ImagePainter::undo()
0164 {
0165     Polygon* polygon = static_cast<Polygon*>(m_parent->currentObject());
0166 
0167     if (!polygon->empty()) {
0168         polygon->pop_back();
0169         repaint();
0170     }
0171 }
0172 
0173 void ImagePainter::deleteCurrentObject()
0174 {
0175     Polygon* polygon = static_cast<Polygon*>(m_parent->currentObject());
0176 
0177     if (!polygon->isClosed()) {
0178         polygon->clear();
0179         repaint();
0180     }
0181 }
0182 
0183 void ImagePainter::paintObject(MarkedObject* object)
0184 {
0185     Polygon polygon (static_cast<const Polygon*>(object));
0186     if (object != m_parent->currentObject()) {
0187         QPointF offset = m_currentItem->pos();
0188         for (QPointF& point : polygon) {
0189             point = QPointF(point.x() * m_scaleW, point.y() * m_scaleH);
0190             point += offset;
0191         }
0192     }
0193 
0194     QColor color(polygon.objClass()->color());
0195     QBrush brush(color);
0196     QPen pen(brush, 2);
0197 
0198     if (polygon.size() > 1 && polygon.isClosed()) {
0199         color.setAlpha(35);
0200 
0201         QGraphicsPolygonItem* pol = m_parent->scene()->addPolygon(polygon, pen, QBrush(color));
0202 
0203         m_items << pol;
0204     }
0205     else {
0206         for (auto it = polygon.begin(); it != polygon.end(); ++it) {
0207             QGraphicsItem* item;
0208             if (it == polygon.begin())
0209                 item = m_parent->scene()->addRect((*it).x(), (*it).y(), 10, 10, pen, brush);
0210             else
0211                 item = m_parent->scene()->addLine(QLineF(*(it - 1), *it), pen);
0212 
0213             m_items << item;
0214         }
0215     }
0216 }
0217 
0218 bool ImagePainter::importObjects(QVector<MarkedObject*> objects)
0219 {
0220     if (objects.isEmpty() || objects.first()->type() != MarkedObject::Type::Polygon)
0221         return false;
0222 
0223     m_parent->savedObjects() = objects;
0224     repaint();
0225 
0226     return true;
0227 }
0228 
0229 void ImagePainter::zoomIn()
0230 {
0231     m_parent->currentObject()->clear();
0232     if (m_scaleH < 4.0 && m_scaleW < 4.0)
0233         scaleImage(1.25);
0234 }
0235 
0236 void ImagePainter::zoomOut()
0237 {
0238     m_parent->currentObject()->clear();
0239     if (m_scaleH > 0.25 && m_scaleW > 0.25)
0240         scaleImage(0.75);
0241 }
0242 
0243 void ImagePainter::scaleImage(double factor)
0244 {
0245     if (m_filepath != "") {
0246         m_scaleH *= factor;
0247         m_scaleW *= factor;
0248 
0249         QPixmap image(m_filepath);
0250         QPixmap scaledImage;
0251 
0252         scaledImage = image.scaledToHeight(int(image.height() * m_scaleH));
0253         scaledImage = image.scaledToWidth(int(image.width() * m_scaleW));
0254 
0255         image = scaledImage;
0256 
0257         m_parent->scene()->removeItem(m_currentItem);
0258         QGraphicsPixmapItem* pixmapItem = m_parent->scene()->addPixmap(image);
0259 
0260         int x_scene = int(m_parent->scene()->width() / 2);
0261         int y_scene = int(m_parent->scene()->height() / 2);
0262         int x_image = int(image.width() / 2);
0263         int y_image = int(image.height() / 2);
0264 
0265         pixmapItem->setPos(x_scene - x_image, y_scene - y_image);
0266         m_currentItem = pixmapItem;
0267 
0268         repaint();
0269     }
0270 }