Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsItem resize with keeping aspect ratio

QGraphicsItem resize with keeping aspect ratio

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 2 Posters 828 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    angeleyes
    wrote on last edited by angeleyes
    #1

    Hello.
    I took the code from the @KillerSmath 's answer. Corrected a little for displaying pictures.
    if anyone knows, tell me how to calculate the position of the MovableCircle so that the initial aspect ratio is preserved

    class MovableCircle : public QGraphicsObject
    {
        Q_OBJECT
    public:
        enum ECirclePos {
            eTopLeft = 0,
            eTopRight,
            eBottomRight,
            eBottomLeft,
        };
    
        explicit MovableCircle(ECirclePos cp, double ar, QGraphicsItem *parent = 0);
    
    private:
        QRectF boundingRect() const;
        QPainterPath shape() const;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
        void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
        void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
        QPointF _shiftMouseCoords;
    
    private:
        double aspectRatio_;
        ECirclePos circlePos_;
    signals:
        void circleMoved();
    };
    

    I want to calculate position of the MovableCircle here:

    void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        auto pos = mapToScene(event->pos() + _shiftMouseCoords);
    //    pos.setX(qMin(pos.x(), pos.y()));
    //    pos.setY(qMin(pos.x(), pos.y()));
    
        LOG_WARNING(logger, "Circle Pos: ", circlePos_, ", ", pos.x(), " ", pos.y());
        setPos(pos);
        emit circleMoved();
    }
    

    MoveItem.h:

    class MoveItem : public QObject, public QGraphicsItem
    {
        Q_OBJECT
        Q_INTERFACES(QGraphicsItem)
    public:
        explicit MoveItem(uint64_t& zc, QGraphicsItem *parent = 0);
        ~MoveItem();
    
    signals:
    protected:
        QRectF boundingRect() const override;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
    
    private:
        QPointF shiftMouseCoords_;
        QImage qimage_;
        QPixmap pixmap_;
        uint64_t& zCounter_;
        MovableCircle *_topLeftCircle, *_topRightCircle, *_bottomLeftCircle, *_bottomRightCircle;
        QSizeF _size;
    public slots:
    };
    

    MoveItem.cpp:

    MoveItem::MoveItem(uint64_t& zc, QGraphicsItem *parent) :
        QGraphicsItem(parent), zCounter_(zc)
    {
        setZValue(zCounter_);
        qimage_ = QImage("cat.png");
        pixmap_ = QPixmap::fromImage(qimage_);
        _size = pixmap_.size();
    
        setAcceptHoverEvents(true);
        setFlag(QGraphicsItem::ItemIsMovable, true);
    
         double ar = _size.width() / _size.height();
         // Top Left
         _topLeftCircle = new MovableCircle(MovableCircle::eTopLeft, ar, this);
         _topLeftCircle->setPos(0, 0);
         // Top Right
         _topRightCircle = new MovableCircle(MovableCircle::eTopRight, ar, this);
         _topRightCircle->setPos(_size.width(), 0);
         // Bottom Right
         _bottomRightCircle = new MovableCircle(MovableCircle::eBottomRight, ar, this);
         _bottomRightCircle->setPos(_size.width(), _size.height());
         // Bottom Left
         _bottomLeftCircle = new MovableCircle(MovableCircle::eBottomLeft, ar, this);
         _bottomLeftCircle->setPos(0, _size.height());
    
         // Signals
         connect(_topLeftCircle, &MovableCircle::circleMoved, this, [this](){
             _bottomLeftCircle->setPos( _topLeftCircle->pos().x(), _bottomLeftCircle->pos().y());
             _topRightCircle->setPos(_topRightCircle->pos().x(), _topLeftCircle->pos().y());
             update(); // force to Repaint
         });
    
         connect(_topRightCircle, &MovableCircle::circleMoved, this, [this](){
             _topLeftCircle->setPos(_topLeftCircle->pos().x(), _topRightCircle->pos().y());
             _bottomRightCircle->setPos(_topRightCircle->pos().x(), _bottomRightCircle->pos().y());
             update(); // force to Repaint
         });
    
         connect(_bottomLeftCircle, &MovableCircle::circleMoved, this, [this](){
             _topLeftCircle->setPos(_bottomLeftCircle->pos().x(), _topLeftCircle->pos().y());
             _bottomRightCircle->setPos(_bottomRightCircle->pos().x(), _bottomLeftCircle->pos().y());
             update(); // force to Repaint
         });
    
         connect(_bottomRightCircle, &MovableCircle::circleMoved, this, [this](){
             _bottomLeftCircle->setPos(_bottomLeftCircle->pos().x(), _bottomRightCircle->pos().y());
             _topRightCircle->setPos(_bottomRightCircle->pos().x(), _topRightCircle->pos().y());
             update(); // force to Repaint
         });
    }
    
    QRectF MoveItem::boundingRect() const
    {
        qreal distX = sqrt(pow(_topLeftCircle->x() - _topRightCircle->x(),2) +
                           pow(_topLeftCircle->y() - _topRightCircle->y(),2)); // eucledian distance
    
        qreal distY = sqrt(pow(_topLeftCircle->x() - _bottomLeftCircle->x(),2) +
                           pow(_topLeftCircle->y() - _bottomLeftCircle->y(),2)); // eucledian distance
    
    
        return QRectF(qMin(_topLeftCircle->pos().x(), _topRightCircle->pos().x()) ,
                      qMin(_topLeftCircle->pos().y(), _bottomLeftCircle->pos().y()),
                      distX, distY);
    }
    
    void MoveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
         painter->drawImage(boundingRect(), qimage_);
        Q_UNUSED(widget);
    }
    

    gif example:
    tenor.gif

    regards, max

    Pl45m4P A 2 Replies Last reply
    0
    • A angeleyes

      Hello.
      I took the code from the @KillerSmath 's answer. Corrected a little for displaying pictures.
      if anyone knows, tell me how to calculate the position of the MovableCircle so that the initial aspect ratio is preserved

      class MovableCircle : public QGraphicsObject
      {
          Q_OBJECT
      public:
          enum ECirclePos {
              eTopLeft = 0,
              eTopRight,
              eBottomRight,
              eBottomLeft,
          };
      
          explicit MovableCircle(ECirclePos cp, double ar, QGraphicsItem *parent = 0);
      
      private:
          QRectF boundingRect() const;
          QPainterPath shape() const;
          void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
          void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
          void mousePressEvent(QGraphicsSceneMouseEvent *event);
          void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
          QPointF _shiftMouseCoords;
      
      private:
          double aspectRatio_;
          ECirclePos circlePos_;
      signals:
          void circleMoved();
      };
      

      I want to calculate position of the MovableCircle here:

      void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
      {
          auto pos = mapToScene(event->pos() + _shiftMouseCoords);
      //    pos.setX(qMin(pos.x(), pos.y()));
      //    pos.setY(qMin(pos.x(), pos.y()));
      
          LOG_WARNING(logger, "Circle Pos: ", circlePos_, ", ", pos.x(), " ", pos.y());
          setPos(pos);
          emit circleMoved();
      }
      

      MoveItem.h:

      class MoveItem : public QObject, public QGraphicsItem
      {
          Q_OBJECT
          Q_INTERFACES(QGraphicsItem)
      public:
          explicit MoveItem(uint64_t& zc, QGraphicsItem *parent = 0);
          ~MoveItem();
      
      signals:
      protected:
          QRectF boundingRect() const override;
          void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
      
      private:
          QPointF shiftMouseCoords_;
          QImage qimage_;
          QPixmap pixmap_;
          uint64_t& zCounter_;
          MovableCircle *_topLeftCircle, *_topRightCircle, *_bottomLeftCircle, *_bottomRightCircle;
          QSizeF _size;
      public slots:
      };
      

      MoveItem.cpp:

      MoveItem::MoveItem(uint64_t& zc, QGraphicsItem *parent) :
          QGraphicsItem(parent), zCounter_(zc)
      {
          setZValue(zCounter_);
          qimage_ = QImage("cat.png");
          pixmap_ = QPixmap::fromImage(qimage_);
          _size = pixmap_.size();
      
          setAcceptHoverEvents(true);
          setFlag(QGraphicsItem::ItemIsMovable, true);
      
           double ar = _size.width() / _size.height();
           // Top Left
           _topLeftCircle = new MovableCircle(MovableCircle::eTopLeft, ar, this);
           _topLeftCircle->setPos(0, 0);
           // Top Right
           _topRightCircle = new MovableCircle(MovableCircle::eTopRight, ar, this);
           _topRightCircle->setPos(_size.width(), 0);
           // Bottom Right
           _bottomRightCircle = new MovableCircle(MovableCircle::eBottomRight, ar, this);
           _bottomRightCircle->setPos(_size.width(), _size.height());
           // Bottom Left
           _bottomLeftCircle = new MovableCircle(MovableCircle::eBottomLeft, ar, this);
           _bottomLeftCircle->setPos(0, _size.height());
      
           // Signals
           connect(_topLeftCircle, &MovableCircle::circleMoved, this, [this](){
               _bottomLeftCircle->setPos( _topLeftCircle->pos().x(), _bottomLeftCircle->pos().y());
               _topRightCircle->setPos(_topRightCircle->pos().x(), _topLeftCircle->pos().y());
               update(); // force to Repaint
           });
      
           connect(_topRightCircle, &MovableCircle::circleMoved, this, [this](){
               _topLeftCircle->setPos(_topLeftCircle->pos().x(), _topRightCircle->pos().y());
               _bottomRightCircle->setPos(_topRightCircle->pos().x(), _bottomRightCircle->pos().y());
               update(); // force to Repaint
           });
      
           connect(_bottomLeftCircle, &MovableCircle::circleMoved, this, [this](){
               _topLeftCircle->setPos(_bottomLeftCircle->pos().x(), _topLeftCircle->pos().y());
               _bottomRightCircle->setPos(_bottomRightCircle->pos().x(), _bottomLeftCircle->pos().y());
               update(); // force to Repaint
           });
      
           connect(_bottomRightCircle, &MovableCircle::circleMoved, this, [this](){
               _bottomLeftCircle->setPos(_bottomLeftCircle->pos().x(), _bottomRightCircle->pos().y());
               _topRightCircle->setPos(_bottomRightCircle->pos().x(), _topRightCircle->pos().y());
               update(); // force to Repaint
           });
      }
      
      QRectF MoveItem::boundingRect() const
      {
          qreal distX = sqrt(pow(_topLeftCircle->x() - _topRightCircle->x(),2) +
                             pow(_topLeftCircle->y() - _topRightCircle->y(),2)); // eucledian distance
      
          qreal distY = sqrt(pow(_topLeftCircle->x() - _bottomLeftCircle->x(),2) +
                             pow(_topLeftCircle->y() - _bottomLeftCircle->y(),2)); // eucledian distance
      
      
          return QRectF(qMin(_topLeftCircle->pos().x(), _topRightCircle->pos().x()) ,
                        qMin(_topLeftCircle->pos().y(), _bottomLeftCircle->pos().y()),
                        distX, distY);
      }
      
      void MoveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
      {
           painter->drawImage(boundingRect(), qimage_);
          Q_UNUSED(widget);
      }
      

      gif example:
      tenor.gif

      regards, max

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #2
      This post is deleted!
      1 Reply Last reply
      0
      • A angeleyes

        Hello.
        I took the code from the @KillerSmath 's answer. Corrected a little for displaying pictures.
        if anyone knows, tell me how to calculate the position of the MovableCircle so that the initial aspect ratio is preserved

        class MovableCircle : public QGraphicsObject
        {
            Q_OBJECT
        public:
            enum ECirclePos {
                eTopLeft = 0,
                eTopRight,
                eBottomRight,
                eBottomLeft,
            };
        
            explicit MovableCircle(ECirclePos cp, double ar, QGraphicsItem *parent = 0);
        
        private:
            QRectF boundingRect() const;
            QPainterPath shape() const;
            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
            void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
            void mousePressEvent(QGraphicsSceneMouseEvent *event);
            void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
            QPointF _shiftMouseCoords;
        
        private:
            double aspectRatio_;
            ECirclePos circlePos_;
        signals:
            void circleMoved();
        };
        

        I want to calculate position of the MovableCircle here:

        void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
        {
            auto pos = mapToScene(event->pos() + _shiftMouseCoords);
        //    pos.setX(qMin(pos.x(), pos.y()));
        //    pos.setY(qMin(pos.x(), pos.y()));
        
            LOG_WARNING(logger, "Circle Pos: ", circlePos_, ", ", pos.x(), " ", pos.y());
            setPos(pos);
            emit circleMoved();
        }
        

        MoveItem.h:

        class MoveItem : public QObject, public QGraphicsItem
        {
            Q_OBJECT
            Q_INTERFACES(QGraphicsItem)
        public:
            explicit MoveItem(uint64_t& zc, QGraphicsItem *parent = 0);
            ~MoveItem();
        
        signals:
        protected:
            QRectF boundingRect() const override;
            void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
        
        private:
            QPointF shiftMouseCoords_;
            QImage qimage_;
            QPixmap pixmap_;
            uint64_t& zCounter_;
            MovableCircle *_topLeftCircle, *_topRightCircle, *_bottomLeftCircle, *_bottomRightCircle;
            QSizeF _size;
        public slots:
        };
        

        MoveItem.cpp:

        MoveItem::MoveItem(uint64_t& zc, QGraphicsItem *parent) :
            QGraphicsItem(parent), zCounter_(zc)
        {
            setZValue(zCounter_);
            qimage_ = QImage("cat.png");
            pixmap_ = QPixmap::fromImage(qimage_);
            _size = pixmap_.size();
        
            setAcceptHoverEvents(true);
            setFlag(QGraphicsItem::ItemIsMovable, true);
        
             double ar = _size.width() / _size.height();
             // Top Left
             _topLeftCircle = new MovableCircle(MovableCircle::eTopLeft, ar, this);
             _topLeftCircle->setPos(0, 0);
             // Top Right
             _topRightCircle = new MovableCircle(MovableCircle::eTopRight, ar, this);
             _topRightCircle->setPos(_size.width(), 0);
             // Bottom Right
             _bottomRightCircle = new MovableCircle(MovableCircle::eBottomRight, ar, this);
             _bottomRightCircle->setPos(_size.width(), _size.height());
             // Bottom Left
             _bottomLeftCircle = new MovableCircle(MovableCircle::eBottomLeft, ar, this);
             _bottomLeftCircle->setPos(0, _size.height());
        
             // Signals
             connect(_topLeftCircle, &MovableCircle::circleMoved, this, [this](){
                 _bottomLeftCircle->setPos( _topLeftCircle->pos().x(), _bottomLeftCircle->pos().y());
                 _topRightCircle->setPos(_topRightCircle->pos().x(), _topLeftCircle->pos().y());
                 update(); // force to Repaint
             });
        
             connect(_topRightCircle, &MovableCircle::circleMoved, this, [this](){
                 _topLeftCircle->setPos(_topLeftCircle->pos().x(), _topRightCircle->pos().y());
                 _bottomRightCircle->setPos(_topRightCircle->pos().x(), _bottomRightCircle->pos().y());
                 update(); // force to Repaint
             });
        
             connect(_bottomLeftCircle, &MovableCircle::circleMoved, this, [this](){
                 _topLeftCircle->setPos(_bottomLeftCircle->pos().x(), _topLeftCircle->pos().y());
                 _bottomRightCircle->setPos(_bottomRightCircle->pos().x(), _bottomLeftCircle->pos().y());
                 update(); // force to Repaint
             });
        
             connect(_bottomRightCircle, &MovableCircle::circleMoved, this, [this](){
                 _bottomLeftCircle->setPos(_bottomLeftCircle->pos().x(), _bottomRightCircle->pos().y());
                 _topRightCircle->setPos(_bottomRightCircle->pos().x(), _topRightCircle->pos().y());
                 update(); // force to Repaint
             });
        }
        
        QRectF MoveItem::boundingRect() const
        {
            qreal distX = sqrt(pow(_topLeftCircle->x() - _topRightCircle->x(),2) +
                               pow(_topLeftCircle->y() - _topRightCircle->y(),2)); // eucledian distance
        
            qreal distY = sqrt(pow(_topLeftCircle->x() - _bottomLeftCircle->x(),2) +
                               pow(_topLeftCircle->y() - _bottomLeftCircle->y(),2)); // eucledian distance
        
        
            return QRectF(qMin(_topLeftCircle->pos().x(), _topRightCircle->pos().x()) ,
                          qMin(_topLeftCircle->pos().y(), _bottomLeftCircle->pos().y()),
                          distX, distY);
        }
        
        void MoveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
        {
             painter->drawImage(boundingRect(), qimage_);
            Q_UNUSED(widget);
        }
        

        gif example:
        tenor.gif

        regards, max

        A Offline
        A Offline
        angeleyes
        wrote on last edited by
        #3

        I've implemented part of the algorithm for eBottomRight and eTopLeft, but it still works very bad and doesn't work for BottomLeft and TopRight points. If i find a solution and it will be look like Krita or PureRef resize behaviour I will post here.

        void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
        {
            auto pos = mapToScene(event->pos() + _shiftMouseCoords);
        
            qreal xl = (pos.x() == 0) ? .1 : pos.x();
            qreal yl = (pos.y() == 0) ? .1 : pos.y();
        
            qreal arl = qAbs(xl / yl);
        
            if (circlePos_ == eBottomRight) {
                if (arl > aspectRatio_) {
                    pos.setX(yl * aspectRatio_);
                } else {
                    pos.setY(xl / aspectRatio_);
        
                }
            }
        
            if (circlePos_ == eTopLeft) {
                LOG_WARNING(logger, "Circle Pos: ", circlePos_, ", ", pos.x(), " ", pos.y());
                LOG_WARNING(logger, "Init Aspect Ratio: ", aspectRatio_, ", Current AspectRatio:", arl);
                if (arl > aspectRatio_) {
                    LOG_DEBUG(logger, "> Before: ", pos.x(), ", ", pos.y());
                    pos.setY(xl / aspectRatio_);
                    LOG_DEBUG(logger, "> After: ", pos.x(), ", ", pos.y());
                } else {
                    LOG_DEBUG(logger, "< Before: ", pos.x(), ", ", pos.y());
                    pos.setX(yl * aspectRatio_);
                    LOG_DEBUG(logger, "< After: ", pos.x(), ", ", pos.y());
                }
            }
        
            setPos(pos);
            emit circleMoved();
        }
        

        example gif:
        https://media.giphy.com/media/7XBNv61efV7S9DbgJO/giphy.gif

        Pl45m4P 1 Reply Last reply
        0
        • A angeleyes

          I've implemented part of the algorithm for eBottomRight and eTopLeft, but it still works very bad and doesn't work for BottomLeft and TopRight points. If i find a solution and it will be look like Krita or PureRef resize behaviour I will post here.

          void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
          {
              auto pos = mapToScene(event->pos() + _shiftMouseCoords);
          
              qreal xl = (pos.x() == 0) ? .1 : pos.x();
              qreal yl = (pos.y() == 0) ? .1 : pos.y();
          
              qreal arl = qAbs(xl / yl);
          
              if (circlePos_ == eBottomRight) {
                  if (arl > aspectRatio_) {
                      pos.setX(yl * aspectRatio_);
                  } else {
                      pos.setY(xl / aspectRatio_);
          
                  }
              }
          
              if (circlePos_ == eTopLeft) {
                  LOG_WARNING(logger, "Circle Pos: ", circlePos_, ", ", pos.x(), " ", pos.y());
                  LOG_WARNING(logger, "Init Aspect Ratio: ", aspectRatio_, ", Current AspectRatio:", arl);
                  if (arl > aspectRatio_) {
                      LOG_DEBUG(logger, "> Before: ", pos.x(), ", ", pos.y());
                      pos.setY(xl / aspectRatio_);
                      LOG_DEBUG(logger, "> After: ", pos.x(), ", ", pos.y());
                  } else {
                      LOG_DEBUG(logger, "< Before: ", pos.x(), ", ", pos.y());
                      pos.setX(yl * aspectRatio_);
                      LOG_DEBUG(logger, "< After: ", pos.x(), ", ", pos.y());
                  }
              }
          
              setPos(pos);
              emit circleMoved();
          }
          

          example gif:
          https://media.giphy.com/media/7XBNv61efV7S9DbgJO/giphy.gif

          Pl45m4P Offline
          Pl45m4P Offline
          Pl45m4
          wrote on last edited by
          #4

          @angeleyes said in QGraphicsItem resize with keeping aspect ratio:

          I've implemented part of the algorithm for eBottomRight and eTopLeft, but it still works very bad and doesn't work for BottomLeft and TopRight points

          How should it look like? What should your circles do? Resize or move the image?
          Like here (https://youtu.be/4tsL3wJtNqQ?t=182)?

          You current version (the gif) doesn't look too bad except these "jumps".

          If you just want to resize while keeping the aspect ratio why don't you save the ratio and set it to your width or height respectively while moving your circle in X or Y direction? You don't need to calculate the position of every single circle... Or am I missing something?

          1 Reply Last reply
          0
          • A Offline
            A Offline
            angeleyes
            wrote on last edited by angeleyes
            #5

            @Pl45m4 said in QGraphicsItem resize with keeping aspect ratio:

            Like here (https://youtu.be/4tsL3wJtNqQ?t=182)?

            exactly(resize with shift modificator)

            You current version (the gif) doesn't look too bad except these "jumps".

            I think my code and algorithm is not correct.

            If you just want to resize while keeping the aspect ratio why don't you save the ratio and set it to your width or height respectively while moving your circle in X or Y direction? You don't need to calculate the position of every single circle... Or am I missing something?

            Yes I calculate only pressed circle

            thanks for reply

            1 Reply Last reply
            0
            • A Offline
              A Offline
              angeleyes
              wrote on last edited by
              #6

              I found a solution using vector math.(thanks to my colleague Dima Chernikov)

              ABCD - our picture.

              K' - cursor point.

              D2 - the point we are looking for(new position of D)

              gif example: https://media.giphy.com/media/uffXKjNNy5ykzpvsR2/giphy.gif

              (circlePos_ == eBottomLeft) in code
              1488.jpg

              code: (I will most likely redo it later using templates. but now it is more clear for understanding)

              void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
              {
                  auto pos = mapToScene(event->pos() + _shiftMouseCoords);
              
                  qreal xl = pos.x();
                  qreal yl = pos.y();
                  auto rect = parentItem()->boundingRect();
              
                  QPointF a(rect.x(), rect.y());
                  QPointF b(rect.x() + rect.width(), rect.y());
                  QPointF c(rect.x() + rect.width(), rect.y() + rect.height());
                  QPointF d(rect.x(), rect.y() + rect.height());
              
              
                  if (circlePos_ == eTopRight) {
                      Vec2d dc(c.x()-d.x(), c.y()-d.y());
                      Vec2d cb(b.x()-c.x(), b.y()-c.y());
                      Vec2d db(b.x()-d.x(), b.y()-d.y());
                      Vec2d dk(pos.x()-d.x(), pos.y()-d.y());
              
                      auto dc_len = dc.length();
                      auto cb_len = cb.length();
                      auto db_len = db.length();
                      auto dk_len = dk.length();
              
                      auto dkdb_dot = Vec2d<qreal>::dot(db, dk);
                      auto cos_kdb = dkdb_dot/(db_len*dk_len);
                      auto dd2_len = dk_len * cos_kdb;
              
                      auto x =(dd2_len * dc_len) / (std::sqrt(cb_len * cb_len + dc_len * dc_len));
                      auto y = std::sqrt(dd2_len * dd2_len - x * x);
              
                      if (x < 10 || y < 10) return;
                      pos.setX(d.x()+x);
                      pos.setY(d.y()-y);
                  }
              
                  if (circlePos_ == eBottomRight) {
                      Vec2d ad(d.x()-a.x(), d.y()-a.y());
                      Vec2d dc(c.x()-d.x(), c.y()-d.y());
                      Vec2d ac(c.x()-a.x(), c.y()-a.y());
                      Vec2d ak(pos.x()-a.x(), pos.y()-a.y());
              
                      auto ad_len = ad.length();
                      auto dc_len = dc.length();
                      auto ac_len = ac.length();
                      auto ak_len = ak.length();
              
                      auto akac_dot = Vec2d<qreal>::dot(ac, ak);
                      auto cos_kac = akac_dot/(ac_len*ak_len);
                      auto ad2_len = ak_len * cos_kac;
              
                      auto x =(ad2_len * dc_len) / (std::sqrt(ad_len * ad_len + dc_len * dc_len));
                      auto y = std::sqrt(ad2_len * ad2_len - x * x);
              
                      if (x < 10 || y < 10) return;
                      pos.setX(a.x()+x);
                      pos.setY(a.y()+y);
                  }
              
                  if (circlePos_ == eTopLeft) {
                      qDebug()<<this->parentItem()->boundingRect();
                      Vec2d cb(b.x()-c.x(), b.y()-c.y());
                      Vec2d ba(a.x()-b.x(), a.y()-b.y());
                      Vec2d ca(a.x()-c.x(), a.y()-c.y());
                      Vec2d ck(pos.x()-c.x(), pos.y()-c.y());
              
                      auto cb_len = cb.length();
                      auto ba_len = ba.length();
                      auto ca_len = ca.length();
                      auto ck_len = ck.length();
              
                      auto ckca_dot = Vec2d<qreal>::dot(ca, ck);
                      auto cos_kca = ckca_dot/(ca_len*ck_len);
                      auto cd2_len = ck_len * cos_kca;
              
                      auto y =(cd2_len * cb_len) / (std::sqrt(ba_len * ba_len + cb_len * cb_len));
                      auto x = std::sqrt(cd2_len * cd2_len - y * y);
              
                      if (x < 10 || y < 10) return;
                      pos.setX(c.x()-x);
                      pos.setY(c.y()-y);
                  }
              
                  if (circlePos_ == eBottomLeft) {
                      qDebug()<<this->parentItem()->boundingRect();
                      Vec2d ba(a.x()-b.x(), a.y()-b.y());
                      Vec2d ad(d.x()-a.x(), d.y()-a.y());
                      Vec2d bd(d.x()-b.x(), d.y()-b.y());
                      Vec2d bk(pos.x()-b.x(), pos.y()-b.y());
              
                      auto ba_len = ba.length();
                      auto ad_len = ad.length();
                      auto bd_len = bd.length();
                      auto bk_len = bk.length();
              
                      auto bkbd_dot = Vec2d<qreal>::dot(bd, bk);
                      auto cos_kdb = bkbd_dot/(bd_len*bk_len);
                      auto bd2_len = bk_len * cos_kdb;
              
                      auto x =(bd2_len * ba_len) / (std::sqrt(ad_len * ad_len + ba_len * ba_len));
                      auto y = std::sqrt(bd2_len * bd2_len - x * x);
              
                      if (x < 10 || y < 10) return;
                      pos.setX(b.x()-x);
                      pos.setY(b.y()+y);
                  }
              
                  setPos(pos);
                  emit circleMoved();
              }
              
              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved