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. [Solved] Flip a QGraphicsSvgItem on its center point
QtWS25 Last Chance

[Solved] Flip a QGraphicsSvgItem on its center point

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 6.9k 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.
  • G Offline
    G Offline
    gerrysweeney
    wrote on last edited by
    #1

    Hi. I am new to Qt and evaluating its capabilities in advance of initiating a project, so I am really sorry if I post a dumb question. Does anyone know how I can flip an QGraphicsSvcItem on its horizontal or vertical centre axis. In other words, I have an SVG item displayed on the GraphicsView, its a triangle pointing upwards inside a square box, I was to flip it vertically so the triangle tip is now pointing downwards and the overall square stays in the same position on the GraphicsView. Just incase anyone suggests it, rotate(180) is not the solution, it needs to be a transformation of vertical co-ordinates, so like looking at a reflection in a mirror from the top or bottom.

    I have found a way of doing it by using the scale() function

    item->scale(-1,1);

    which works but flips it centred on the top edge so I need to do that and then re-position, its not great but it works. I have tried to use setTransformOriginPoint() as I have done elsewhere for rotating the same object which works, but the scale method above does not. I am pretty sure I should be using transformations but I don't really understand how/when/where to apply this. How I am doing it would appear very inelegant...

    Does any one have any ideas or examples I could go look at?

    Thanks,

    Gerry

    1 Reply Last reply
    0
    • G Offline
      G Offline
      gerrysweeney
      wrote on last edited by
      #2

      I managed to solve this one myself with some more detailed debugging and experimentation. Here is how I done it, someone might find this useful.

      Gerry
      @
      void MyGraphicsItem::flipHorizontal()
      {
      // Get the current transform
      QTransform transform(this->transform());

      qreal m11 = transform.m11();    // Horizontal scaling
      qreal m12 = transform.m12();    // Vertical shearing
      qreal m13 = transform.m13();    // Horizontal Projection
      qreal m21 = transform.m21();    // Horizontal shearing
      qreal m22 = transform.m22();    // vertical scaling
      qreal m23 = transform.m23();    // Vertical Projection
      qreal m31 = transform.m31();    // Horizontal Position (DX)
      qreal m32 = transform.m32();    // Vertical Position (DY)
      qreal m33 = transform.m33();    // Addtional Projection Factor
      
      // We need this in a minute
      qreal scale = m11;
      
      // Horizontal flip
      m11 = -m11;
      
      // Re-position back to origin
      if(m31 > 0)
          m31 = 0;
      else
          m31 = (boundingRect().width() * scale);
      
      // Write back to the matrix
      transform.setMatrix(m11, m12, m13, m21, m22, m23, m31, m32, m33);
      
      // Set the items transformation
      setTransform(transform);
      

      }

      void MyGraphicsItem::flipVertical()
      {
      // Get the current transform
      QTransform transform(this->transform());

      qreal m11 = transform.m11();    // Horizontal scaling
      qreal m12 = transform.m12();    // Vertical shearing
      qreal m13 = transform.m13();    // Horizontal Projection
      qreal m21 = transform.m21();    // Horizontal shearing
      qreal m22 = transform.m22();    // vertical scaling
      qreal m23 = transform.m23();    // Vertical Projection
      qreal m31 = transform.m31();    // Horizontal Position (DX)
      qreal m32 = transform.m32();    // Vertical Position (DY)
      qreal m33 = transform.m33();    // Addtional Projection Factor
      
      // We need this in a minute
      qreal scale = m22;
      
      // Vertical flip
      m22 = -m22;
      
      // Re-position back to origin
      if(m32 > 0)
          m32 = 0;
      else
          m32 = (boundingRect().height() * scale);
      
      // Write back to the matrix
      transform.setMatrix(m11, m12, m13, m21, m22, m23, m31, m32, m33);
      
      // Set the items transformation
      setTransform(transform);
      

      }
      @

      1 Reply Last reply
      0
      • A Offline
        A Offline
        Asperamanca
        wrote on last edited by
        #3

        Weird how the transformOriginPoint is seemingly ignored for scaling.

        Still, you can simplify your code. I have done a sample with a vertical flip, and used three methods to do it.

        @{
        m_pScene = new QGraphicsScene(0,0,800,480,this);

        m_pView = new QGraphicsView(m_pScene, this);
        
        m_pView->setFrameStyle(QFrame::NoFrame);
        m_pView->setGeometry(0,0,800,480);
        m_pView->setAutoFillBackground(false);
        m_pView->show();
        
        QPolygonF polygon;
        polygon << QPointF(100.0,250.0);
        polygon << QPointF(170.0, 350.0);
        polygon << QPointF(30.0, 350.0);
        QGraphicsPolygonItem* testItem = new QGraphicsPolygonItem(polygon);
        m_pScene->addItem(testItem);
        
        QGraphicsPolygonItem* transformedItem = new QGraphicsPolygonItem(polygon);
        transformedItem->setPen(QColor(Qt::red));
        m_pScene->addItem(transformedItem);
        
        
        // Here the fun starts:
        
        QPointF itemCenter = transformedItem->mapToParent(transformedItem->boundingRect().center());
        

        // // Method 1
        // QTransform transform = QTransform();
        // transform.translate(itemCenter.x(),
        // itemCenter.y());
        // transform.scale(1.0, -1.0);
        // transform.translate(-itemCenter.x(),
        // -itemCenter.y());
        // transformedItem->setTransform(transform);

        // // Method 2
        // transformedItem->setTransform(QTransform::fromTranslate(itemCenter.x(),
        // itemCenter.y()),true);
        // transformedItem->setTransform(QTransform::fromScale(1.0, -1.0),true);
        // transformedItem->setTransform(QTransform::fromTranslate(-itemCenter.x(),
        // -itemCenter.y()), true);

        // // Method 3
        // transformedItem->translate(itemCenter.x(),
        // itemCenter.y());
        // transformedItem->scale(1.0, -1.0);
        // transformedItem->translate(-itemCenter.x(),
        // -itemCenter.y());
        }@

        EDIT: used mapToScene, corrected to mapToParent

        1 Reply Last reply
        0
        • G Offline
          G Offline
          gerrysweeney
          wrote on last edited by
          #4

          HI Asperamanca,

          Thanks for the response, I don't fully understand how your solutions work but I like how tidy they look, I will try them out and see how I get on. The one thing they do not seem to cope with is if the object being flipped is already scaled (as mine are), you will see me taking care of that on line 17 and 26 in my example above, I guess will just need to do the same thing and pass that to the scale function.

          Its a real shame the QTransform class does not have options to set each value in the matrix, that would make things much easier still.

          Gerry

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

            I started typing an explanation, went back to my sample, and I must say, there's something here I don't understand either. I'll think about it.

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

              Ah, the way I remember it, you have to read combined transform operations from the last operation to the first. That is, the item is first translated (last operation) so it's center is exactly where the parent's center is (in this case, the top/left of the scene). Then it is scaled. Because it's centered, it's scaled in all directions at the same rate. And finally (first operation), you have to move it back where it belongs.

              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