[Solved] QRectF setTopLeft changing bottomRight
-
Hello everyone,
Another bit a specific problem I'm experiencing, to which google offers no solutions.
I'm in the process of creating an editable rectangle with four corner anchors and a central anchor that allow the user to change the corners of the rectangle and/or rotate it, respectively. Under a very specific circumstance I've discovered that the normal invariant where one corner's setter won't alter the opposite corner, gets broken. If I leave the rectangle unrotated and move the corners, the opposite corners stays unchanged. So, if I, for example, move the upper left corner and then apply the QGraphicsItem's setRect, the bottom right corner will remain unchanged. However, whenever I rotate the rectangle first, and then attempt to move a point, I can clearly see the bottom right corner shifting as well. for the same example, if I rotate the rect 45° to the right, and subsequently start manipulating the top left corner to make the rectangle larger, I can visibly see the lower right corner move away from the center.
Here is some code (heavily cut down, mind you!) of what I do whenever I have an anchor move, and when I rotate:@
void OnAnchorMoved(const CAnchorSubElement& sender, QGraphicsSceneMouseEvent* mouseEvent)
{
QRectF rect = m_pRectItem->rect();
rect.setTopLeft(sender.pos());
m_pBottomLeftCornerAnchor->setPos(rect.bottomLeft());
m_pTopRightCornerAnchor->setPos(rect.topRight());
m_pRectItem->setRect(rect);
// I also set the position of the rotational anchor to the local
// center of the QGraphicsItem here.
}
@@
void SetRotation(double angle, const QPointF& rotationOrigin)
{
m_RotationAngle += angle;
m_pRectItem->setTransformOriginPoint(rotationOrigin);
m_pRectItem->setRotation(m_RotationAngle);
// Here I also rotate all the anchors around their own local center,
// which works fine.
}
@I've checked and double checked the spaces of the items and everything, as far as I can tell, operates in the QGraphicsItem's space, as it should in this case, so I haven't the faintest what's causing the slight variation in the bottom right corner, which should be staying static.
Thank you in advance for any responses,
RenegadeVile -
Well, you say you can visibly see the corner moving. If you read rect().bottomRight() after setting topLeft, is the value actually changed?
If the value is still the same, but the position of the element is not, then the item is probably shown in an unexpected position for other reasons. For example, the transformation anchor might not be exactly where it should be (can't see that in your example).
-
I used qDebug() to look into the problem extensively and it does indeed get changed. But it's only visibly if I undo my rotation right before setting the position, and redoing it afterwards. Otherwise it's hidden in between updates of the Qt drawing routine. I'm almost 100% sure it has something to do with how I handle the rotation, but I can't for the life of me figure out what I'm doing wrong. Whatever the case, the jump in the center of the rectangle the instant you rotate after moving a corner of the rectangle can be visibly seen if manually undoing and redoing the rotation.
-
A small update; after some more debugging, I've found that the rotation alters the scene position slightly. This would make sense only if the object's scene position didn't correspond with its center. Right now I'm making the rectangle as (-200, -300, 400, 600) which means it's center is set to the (0, 0) origin. Then, I translate it to (800, 800) in the scene and it's QRectF stays (correctly) the same.
But, logically, if I rotate around the rectangle's center, its scene position should stay exactly the same. However, that is not the case, there's a very small shift in the coordinate when changing the rectangle after first rotating it (not when it's in its initial state, when scene pos stays the same). That causes the item to jerk into another position once I rotate and that's what causes the scene coordinate of the bottom right corner to alter despite just changing the top left corner. If the scene position changes, so do all the rectangle points.
Is there a flaw in how I'm thinking about this? What could be possible reasons for that scene position changing only AFTER I first rotate the object using the above methodology? Any suggestions can be helpful as I've essentially run out of ideas myself.
-
Another small update. I've attempted the same operation with a QGraphicsPolygonItem, with the same result. However, it seems the scene position gets changed only when the boundingRect() does. When I make a polygon with 4 vertices and move a single one, the scene position stays the same as long as I move the vertex towards the center of the polygon, thereby keeping the boundingRect the same. If I move it away, the boundingrect increases in size, it's center obviously moves, but it's scene position also shifts.
-
Have you taken a look a "this documentation":http://qt-project.org/doc/qt-4.8/graphicsview.html#the-graphics-view-coordinate-system ?
When you rotate an item, the scenePos will change in most cases, because the rotation causes the sceneBoundingRect to grow or shrink.
Additionally, you can expect some minimal changes due to floating point calculations.It would be helpful if you could post a simple but complete example: The rectangle you start with, how you translate / rotate it, the results you expect and the results you get (pos, boundingRect as well as scenePos and sceneBoundingRect), preferably also with code snippets showing how you do each step. You are providing a lot of information, but it's a mix of half-examples and descriptions that I (personally) find hard to follow.
-
I have taken an extensive look at that documentation, even before I started work on this, since I know each library has its own conventions and eccentricities when it comes to their coordinate system.
As for a complete example, I would, if I hadn't found the solution. As far as I can tell, it was a problem with the rotation origin I was passing on, I was using the center of the boundingrect(), instead of the center of the rect itself, which yielded a correct result. There's still a very minute jerk to it from time to time, but that's to be expected because, as you said, there are some rounding errors when converting those floats to integer screen pixels.
If I come across any problems with the polygon and ellipse, I'll post a full example so you can see exactly what I do. -
Good to hear this is solved.
Can you edit the original post and add "[Solved]" to the title?