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. boundingRect and boundingRegion oddness during rotation
Forum Update on Monday, May 27th 2025

boundingRect and boundingRegion oddness during rotation

Scheduled Pinned Locked Moved General and Desktop
boundingrect
10 Posts 3 Posters 5.4k 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.
  • C Offline
    C Offline
    CraigBakalian
    wrote on 29 Jul 2015, 14:29 last edited by
    #1

    I have been doing a lot of testing with rotation of a basic triangle in a QGraphicsPolygonItem. The boundingRect() of a QGraphicsPolygonItem does not "bound" when it is rotated all the time. Oddly, if you draw the boundingRect() of the QGraphicsPolygonItem it will create space to the upper right corner where it is not needed. The same is true for the boundingRegion. However, if I get the boundingRect() of the polygon(), all is well. But this is not good when you use setPos() or the wonderful override of itemChanged().

    If anyone has a solution for this, I will gladly appreciate it.

    Craig Bakalian

    1 Reply Last reply
    0
    • C Offline
      C Offline
      CraigBakalian
      wrote on 29 Jul 2015, 14:52 last edited by
      #2

      Well, I guess overriding the boundingRect() is the solution. I hope it works! Why I have to do this is beyond me.

      1 Reply Last reply
      0
      • C Offline
        C Offline
        CraigBakalian
        wrote on 31 Jul 2015, 12:38 last edited by
        #3

        Okay, it appears that I am talking to myself about this wonderful issue, that really is a bug, and it is a lousy bug.

        When you rotate an QGraphicsItem it must adjust its boundingRect() to fulfill the shape's coordinates so that the shape does not get clipped. And, yes indeed the boundRect() does update its size to fulfill the requirements of that shape; the robot called Qt does this, not very well, but it does it. However, what does not get updated is the pos(), so the upper left side of the boundingRect() does not equal the pos(). If a QGraphicsItem is being dragged around a QGraphicsScene without being rotated, all is well, however, after being rotated its pos() checking is incorrect. Furthermore there is no way to correct the pos() without using setPos() to the boundingRect().topLeft() which causes the robot called Qt to go crazy.

        Anyone out there? Please help me.

        Craig Bakalian

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mchinand
          wrote on 31 Jul 2015, 14:10 last edited by
          #4

          Can you show some example images/screenshots?

          C 1 Reply Last reply 31 Jul 2015, 14:56
          0
          • M mchinand
            31 Jul 2015, 14:10

            Can you show some example images/screenshots?

            C Offline
            C Offline
            CraigBakalian
            wrote on 31 Jul 2015, 14:56 last edited by CraigBakalian
            #5

            Well, no. I don't have a web site or a cloud to post files. Can you imagine this, I am checking the polygon boundingRect() to restrain it to a QGraphicsScene. The QGraphicsPolygonItem is restrained to the scene if there is no rotation, however, after rotating the item the piece is not restrained properly; too much restraint, or not enough restraint. After hours of debugging I found that the->

            QVariant PuzzlePiece::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
            {
                if (change == ItemPositionChange && scene())
                {
                    QPointF newPos = value.toPointF();
                    QRectF rect = scene()->sceneRect();
                    //tangramShape = mapToScene(polygon()); used to debug position of item, but now I use it to keep proper scene position.
                    //setTangramPosition(pos()); used to debug position of item
            
                   //must bound the width of the item to the right and bottom of scene
                    rect.setWidth(rect.width() - boundingRect().width());
                    rect.setHeight(rect.height() - boundingRect().height());
                    if (!rect.contains(newPos))
                    {
                        newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
                        newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
                        return newPos;
                    }
                 }
                if (change == ItemRotationChange)
                {
                     //Santa Claus can tell me what to put in here!
                }
                return QGraphicsItem::itemChange(change, value);
            }
            
            

            very important value.toPointF(); brings into the itemChanged override a QPointF that is from the "non rotated" boundingRect().topLeft(). I know this is complex. I know this is a bug. The question is, is there a way around it? Possibly with a QTransform?

            Craig Bakalian

            1 Reply Last reply
            0
            • E Offline
              E Offline
              egan
              wrote on 31 Jul 2015, 15:39 last edited by
              #6

              Sorry, my English is bad, but I looked probably understood your question.After first you create the polygon, needs to adjust Item the local coordinate.Usually the local coordinate's origin point is the Item center .I have a method to be possible adjust Item pos and the origin point to the Item center.Did not know that can solve your problem.

              QPointF pt1,pt2,delta;
              QPolygonF pts = mapToScene(m_points);
              {
                  pt1 = mapToScene(transformOriginPoint());
                  pt2 = mapToScene(boundingRect().center());
                  delta = pt1 - pt2;
              
                  for (int i = 0; i < pts.count() ; ++i )
                      pts[i]+=delta;
                  prepareGeometryChange();
                  m_points = mapFromScene(pts);
                  setTransform(transform().translate(delta.x(),delta.y()));
                  setTransformOriginPoint(boundingRect().center());
                  moveBy(-delta.x(),-delta.y());
                  setTransform(transform().translate(-delta.x(),-delta.y()));
              }
              
              C 2 Replies Last reply 31 Jul 2015, 16:11
              0
              • E egan
                31 Jul 2015, 15:39

                Sorry, my English is bad, but I looked probably understood your question.After first you create the polygon, needs to adjust Item the local coordinate.Usually the local coordinate's origin point is the Item center .I have a method to be possible adjust Item pos and the origin point to the Item center.Did not know that can solve your problem.

                QPointF pt1,pt2,delta;
                QPolygonF pts = mapToScene(m_points);
                {
                    pt1 = mapToScene(transformOriginPoint());
                    pt2 = mapToScene(boundingRect().center());
                    delta = pt1 - pt2;
                
                    for (int i = 0; i < pts.count() ; ++i )
                        pts[i]+=delta;
                    prepareGeometryChange();
                    m_points = mapFromScene(pts);
                    setTransform(transform().translate(delta.x(),delta.y()));
                    setTransformOriginPoint(boundingRect().center());
                    moveBy(-delta.x(),-delta.y());
                    setTransform(transform().translate(-delta.x(),-delta.y()));
                }
                
                C Offline
                C Offline
                CraigBakalian
                wrote on 31 Jul 2015, 16:11 last edited by
                #7

                @egan
                I don't know if this will work. I do have the transformOriginPoint() set to the center of the item creating a normal looking rotate. But, the transformOriginPoint is specifically for rotation. I don't think I can delta from the transformOriginPoint() in the itemChanged override, I think weird stuff will happen. But, I get the translate thing. That might work. But, then it will look weird when rotating. I gotta eat lunch first. Go for a bicycle ride and think more.

                1 Reply Last reply
                0
                • E egan
                  31 Jul 2015, 15:39

                  Sorry, my English is bad, but I looked probably understood your question.After first you create the polygon, needs to adjust Item the local coordinate.Usually the local coordinate's origin point is the Item center .I have a method to be possible adjust Item pos and the origin point to the Item center.Did not know that can solve your problem.

                  QPointF pt1,pt2,delta;
                  QPolygonF pts = mapToScene(m_points);
                  {
                      pt1 = mapToScene(transformOriginPoint());
                      pt2 = mapToScene(boundingRect().center());
                      delta = pt1 - pt2;
                  
                      for (int i = 0; i < pts.count() ; ++i )
                          pts[i]+=delta;
                      prepareGeometryChange();
                      m_points = mapFromScene(pts);
                      setTransform(transform().translate(delta.x(),delta.y()));
                      setTransformOriginPoint(boundingRect().center());
                      moveBy(-delta.x(),-delta.y());
                      setTransform(transform().translate(-delta.x(),-delta.y()));
                  }
                  
                  C Offline
                  C Offline
                  CraigBakalian
                  wrote on 31 Jul 2015, 17:53 last edited by CraigBakalian
                  #8

                  @egan

                  Wait! I get it. This might work. Does the code you have given create a large square around the shape and place the polygon in the middle so that the polygon's rotation does not effect the boundingRect()? If so this may actually work! Now I gotta implement this. Crossing fingers. Actually, I never knew of the boundingRect().center() function. That may solve the whole issue. Thank you!

                  E 1 Reply Last reply 1 Aug 2015, 00:33
                  0
                  • C CraigBakalian
                    31 Jul 2015, 17:53

                    @egan

                    Wait! I get it. This might work. Does the code you have given create a large square around the shape and place the polygon in the middle so that the polygon's rotation does not effect the boundingRect()? If so this may actually work! Now I gotta implement this. Crossing fingers. Actually, I never knew of the boundingRect().center() function. That may solve the whole issue. Thank you!

                    E Offline
                    E Offline
                    egan
                    wrote on 1 Aug 2015, 00:33 last edited by
                    #9

                    @CraigBakalian

                    QRectF PolygonItem::boundingRect() const
                    {
                    return shape().controlPointRect();
                    }

                    QPainterPath PolygonItem::shape() const
                    {
                    QPainterPath path;
                    path.addPolygon(m_points);
                    path.closeSubpath();
                    return path;
                    }
                    void PolygonItem::updateCoordinate()
                    {

                    QPointF pt1,pt2,delta;
                    QPolygonF pts = mapToScene(m_points);
                    if (parentItem()==NULL)
                    {
                        pt1 = mapToScene(transformOriginPoint());
                        pt2 = mapToScene(boundingRect().center());
                        delta = pt1 - pt2;
                    
                        for (int i = 0; i < pts.count() ; ++i )
                            pts[i]+=delta;
                    
                        prepareGeometryChange();
                    
                        m_points = mapFromScene(pts);
                    
                        setTransform(transform().translate(delta.x(),delta.y()));
                        setTransformOriginPoint(boundingRect().center());
                        moveBy(-delta.x(),-delta.y());
                        setTransform(transform().translate(-delta.x(),-delta.y()));
                       }
                    

                    }

                    The updateCoordinate() can called after you create or ratotion polygons.

                    C 1 Reply Last reply 2 Aug 2015, 16:00
                    0
                    • E egan
                      1 Aug 2015, 00:33

                      @CraigBakalian

                      QRectF PolygonItem::boundingRect() const
                      {
                      return shape().controlPointRect();
                      }

                      QPainterPath PolygonItem::shape() const
                      {
                      QPainterPath path;
                      path.addPolygon(m_points);
                      path.closeSubpath();
                      return path;
                      }
                      void PolygonItem::updateCoordinate()
                      {

                      QPointF pt1,pt2,delta;
                      QPolygonF pts = mapToScene(m_points);
                      if (parentItem()==NULL)
                      {
                          pt1 = mapToScene(transformOriginPoint());
                          pt2 = mapToScene(boundingRect().center());
                          delta = pt1 - pt2;
                      
                          for (int i = 0; i < pts.count() ; ++i )
                              pts[i]+=delta;
                      
                          prepareGeometryChange();
                      
                          m_points = mapFromScene(pts);
                      
                          setTransform(transform().translate(delta.x(),delta.y()));
                          setTransformOriginPoint(boundingRect().center());
                          moveBy(-delta.x(),-delta.y());
                          setTransform(transform().translate(-delta.x(),-delta.y()));
                         }
                      

                      }

                      The updateCoordinate() can called after you create or ratotion polygons.

                      C Offline
                      C Offline
                      CraigBakalian
                      wrote on 2 Aug 2015, 16:00 last edited by CraigBakalian 8 Feb 2015, 16:01
                      #10

                      @egan

                      Well, I re-implemented the whole mouse moving the puzzle shape thing. I am not using itemChanged() override anymore. The fact that the item's position x and y was not the same as the boundingRect().topLeft() x and y after rotating was an issue that was too problematic. A tangram shape; a right triangle with a hypotenuse that equaled the leg * the square root of 2 being contained by a bounding rectangle during rotation produced too many effects. So, I got it working, and very well, but I ended up using

                      void PuzzlePiece::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
                      {
                          
                          QRectF rect = scene()->sceneRect();
                          float mx = event->scenePos().x() - xbeta;
                          float my = event->scenePos().y() - ybeta;
                          setTangramPositionAndShape();  
                          \\ sets the boundingRect to the bounds of the actual polygon points 
                          if(rect.contains(boundingRect()))
                          {
                              setPos(mx, my);
                              setTangramPositionAndShape();
                          }
                      }
                      

                      And yes, the shape stops moving when it goes out of the scene, but a mouseDown sets it position back inside the scene and all is good.

                      I made a tangram puzzle application way back when I was a young man. I used Cocoa/Objective C on a Mac. The thing was downloaded over 8 million times in a week. People from Japan would call me up and ask me about it. It was crazy. And yeah, it was free, so I am not a millionaire; my wife yelled at me for weeks for making it free. It was this small window about the size of an smart phone screen.

                      Cocoa does not have a simple implementation to make an graphic item movable with some easy setFlag(QGraphicsItem::ItemIsMovable). It was much more difficult to implement back then. So, I am basically using the same bounds checking and resetting the object the same way as I did 25 years ago.

                      My son is about to go to college for software engineering. I am teaching C++ with the implementation of this simple puzzle.

                      Thanks for your help. Your posts kept me thinking!

                      Craig

                      1 Reply Last reply
                      0

                      10/10

                      2 Aug 2015, 16:00

                      • Login

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