Converting between coordinate systems
-
wrote on 23 Oct 2024, 20:07 last edited by
I have a mouse position in screen coordinates. It is passed to me from hoverEnterEvent, event->screenPos()
I have an object on the screen that derives from QGraphicsObject
I have a point in that object in the item coordinate system.
I am trying to compare themMy understanding is that
myQGraphicsObject->mapToScene(pointInItemCoordinates)
should return something in screen coordinates
What I get out of mapToScene is the exact value that I put into mapToSceneclearly, this isn't the way to do what I need. How can I convert between the coordinate systems
-
I have a mouse position in screen coordinates. It is passed to me from hoverEnterEvent, event->screenPos()
I have an object on the screen that derives from QGraphicsObject
I have a point in that object in the item coordinate system.
I am trying to compare themMy understanding is that
myQGraphicsObject->mapToScene(pointInItemCoordinates)
should return something in screen coordinates
What I get out of mapToScene is the exact value that I put into mapToSceneclearly, this isn't the way to do what I need. How can I convert between the coordinate systems
wrote on 23 Oct 2024, 20:27 last edited by@james-b-s
So for youmyQGraphicsObject->mapToScene(0, 0)
always (regardless of object position on the scene) returns(0, 0)
? -
I have a mouse position in screen coordinates. It is passed to me from hoverEnterEvent, event->screenPos()
I have an object on the screen that derives from QGraphicsObject
I have a point in that object in the item coordinate system.
I am trying to compare themMy understanding is that
myQGraphicsObject->mapToScene(pointInItemCoordinates)
should return something in screen coordinates
What I get out of mapToScene is the exact value that I put into mapToSceneclearly, this isn't the way to do what I need. How can I convert between the coordinate systems
wrote on 24 Oct 2024, 03:25 last edited by Pl45m4@james-b-s said in Converting between coordinate systems:
My understanding is that
myQGraphicsObject->mapToScene(pointInItemCoordinates)
should return something in screen coordinatesWhat I get out of mapToScene is the exact value that I put into mapToScene
Your understanding is close, but not 100% correct :)
The devil is in the detail:
CallingmapToScene
from yourmyQGraphicsObject
instance, will use the item as "root" and start the transformation from its POV.
So mapping a point in some item coordinates to the item's scene coordinate, does nothing, as you've discovered already because from scene's perspective, the item and the point are in the same coordinate system :)What you need to do instead:
Map the global/screen coordinate to your scene coordinate
and the item coordinate also to scene coordinate
(or vice versa)
Then you can compare them. -
wrote on 24 Oct 2024, 13:33 last edited by james b-s
I have a position in my graphics object and click on it.
The position in screen coordinates is 950, 413
The position in graphics object coordinates is 134, 36- Calling mapToScene on the graphics object and passing in the graphics object coordinates yields 134, 36 (unchanged)
- Calling mapToScene on the graphics view and passing in the graphics object coordinates yields approx -178, 53
- Calling mapToScene on the graphics object and passing in the position in screen coordinates 950, 413 (unchanged)
- Calling mapToScene on the graphics view and passing in the position in screen coordinates yields approx 1513, 835
My understanding is that I should be comparing 2 and 4. Maybe the graphics view is the wrong thing to call mapToScene on?
QPointF mousePosInSceneCoordinates = nodeGraphicsObject->mapToScene(mousePositionInScreenCoordinates); QPointF otherPointInSceneCoordinates = m_pGraphicsView->mapToScene(otherPointInNodeCoordinates); QPointF mousePosInSceneCoordinates2 = m_pGraphicsView->mapToScene(QPoint(mousePositionInScreenCoordinates.x(), mousePositionInScreenCoordinates.y())); QPointF otherPointInSceneCoordinates2 = nodeGraphicsObject->mapToScene(otherPointInNodeCoordinates);
-
I have a position in my graphics object and click on it.
The position in screen coordinates is 950, 413
The position in graphics object coordinates is 134, 36- Calling mapToScene on the graphics object and passing in the graphics object coordinates yields 134, 36 (unchanged)
- Calling mapToScene on the graphics view and passing in the graphics object coordinates yields approx -178, 53
- Calling mapToScene on the graphics object and passing in the position in screen coordinates 950, 413 (unchanged)
- Calling mapToScene on the graphics view and passing in the position in screen coordinates yields approx 1513, 835
My understanding is that I should be comparing 2 and 4. Maybe the graphics view is the wrong thing to call mapToScene on?
QPointF mousePosInSceneCoordinates = nodeGraphicsObject->mapToScene(mousePositionInScreenCoordinates); QPointF otherPointInSceneCoordinates = m_pGraphicsView->mapToScene(otherPointInNodeCoordinates); QPointF mousePosInSceneCoordinates2 = m_pGraphicsView->mapToScene(QPoint(mousePositionInScreenCoordinates.x(), mousePositionInScreenCoordinates.y())); QPointF otherPointInSceneCoordinates2 = nodeGraphicsObject->mapToScene(otherPointInNodeCoordinates);
wrote on 24 Oct 2024, 13:39 last edited by@james-b-s said in Converting between coordinate systems:
Maybe the graphics view is the wrong thing to call mapToScene on?
This is the first time you have mentioned graphics view, I don't see that anywhere earlier? Have you read QPointF QGraphicsView::mapToScene(const QPoint &point) const
Returns the viewport coordinate point mapped to scene coordinates.
Note viewport. That is not the same as scene. I believe you need to clarify why you are involving the
QGraphicsView
here? -
wrote on 24 Oct 2024, 14:11 last edited by
I am involving graphicsView because it is the only object that I know of to call mapToScene on other than the graphics object. What object should I be calling mapToScene on?
And I'm a bit shocked to discover that mapToScene of a Graphics item maps to the scene, but that mapToScene on a graphicsView maps to something else.
But it still boils down to what objects should I be calling mapToScene on?
-
I am involving graphicsView because it is the only object that I know of to call mapToScene on other than the graphics object. What object should I be calling mapToScene on?
And I'm a bit shocked to discover that mapToScene of a Graphics item maps to the scene, but that mapToScene on a graphicsView maps to something else.
But it still boils down to what objects should I be calling mapToScene on?
wrote on 24 Oct 2024, 14:33 last edited by JonB@james-b-s
I am sorry but I don't have time now to answer, and I have to think about this stuff too! But there are 3 types of coordinates:QGraphicsItem
co-ordinates are relative to the the graphics item. (0.0) is the top left of the item.QGraphicsScene
co-ordinates are relative to the scene. (0,0) is the center of the scene.QGraphicsView
co-ordinates are relative to the view's viewport. (0,0) is the top-left of the view. The view may be scrolled or scaled, and I am unsure how that affects them. (0,0) may be the top-left of the "screen" as you look at it, or it may be changed by any scrolling etc.
I asked you earlier, from what I understood you to be saying ("What I get out of mapToScene is the exact value that I put into mapToScene"), whether
So for you
myQGraphicsObject->mapToScene(0, 0)
always (regardless of object position on the scene) returns(0, 0
)?I would not expect that to be the case unless your object is placed at (0,0) on the scene.
Sorry, gotta go, maybe someone will help you more. Have a play with various values/calls while you get the hang of it!
-
wrote on 24 Oct 2024, 14:54 last edited by
I have not tried it specifically passing 0, 0 to mapToScene. The graphics object in question is at position 0,0 in the scene. I am clicking into a known position within that graphics object. When I do, I have two known values. The mouse position in "screen" coordinates and that known position in graphics objects coordinates.
-
I have not tried it specifically passing 0, 0 to mapToScene. The graphics object in question is at position 0,0 in the scene. I am clicking into a known position within that graphics object. When I do, I have two known values. The mouse position in "screen" coordinates and that known position in graphics objects coordinates.
wrote on 24 Oct 2024, 14:58 last edited by JonB@james-b-s said in Converting between coordinate systems:
The graphics object in question is at position 0,0 in the scene.
Then of course
myQGraphicsObject->mapToScene(0, 0)
will return (0, 0) for the scene coordinate, and (100, 100) would equally return (100,100)! But if the item/object is not at (0,0) on the scene then it will return a different value.I think for a mouse position on the view you would use
QGraphicsView->mapToScene()
to get the scene coordinate. This has nothing to do with anyQGraphicsItem
. Map that to scene too if you want to compare. @Pl45m4 may have said this earlier. Perhaps he can sort you out :) -
I have not tried it specifically passing 0, 0 to mapToScene. The graphics object in question is at position 0,0 in the scene. I am clicking into a known position within that graphics object. When I do, I have two known values. The mouse position in "screen" coordinates and that known position in graphics objects coordinates.
wrote on 25 Oct 2024, 03:55 last edited by Pl45m4@james-b-s said in Converting between coordinate systems:
When I do, I have two known values. The mouse position in "screen" coordinates and that known position in graphics objects coordinates.
And where do you want to compare them?
In your item, in your scene or in a different place?Usually the task is simple, but can be quite confusing as I've mentioned in my reply before.
You have six options:
-
when you compare in your item class (directly in
hoverEnterEvent
, for example):- use
map
From
Scene( event->scenePos() )
and compare with your raw item point
OR - use
map
To
Scene( itemPoint )
on your item point and compare withevent->scenePos()
- use
-
when comparing in your custom scene or view class:
- get your event point to the scene class somehow (e.g. send via signal), then
- map both to scene coords... using the source as origin, e.g.
item->mapToScene
orthis->mapToScene
OR - map scene's sceneCoords to item's coordinate system using
item->mapFromScene( scenePoint)
, then compare with your raw item point in item coords.
- map both to scene coords... using the source as origin, e.g.
- get your event point to the scene class somehow (e.g. send via signal), then
-
when comparing globally (in
MainWindow
):- use
event->screenPos()
in the item's event handler, send it to your destination and usemapToGlobal( point )
for the other point in your widget... then you can compare them both in screen coords.
OR - access the view/scene from there and let them transform the global point in scene coords with
mapToScene
(this might need amapFromGlobal
on the point before), then compare them in scene coords
- use
(Had an example ready where it was easy to add)
The item is 100x100 with top-left being (0 / 0).
Inner rect (red box) is 50x50, starting at (50 / 50) in item coordinates.As you can tell from the ItemPos and ScenePos point, the item's top-left (0 / 0) is at (5 / 66), which is the offset for this item in the scene.
Screen position should be clear ( = actual position in my device's screen coordinate system)void myObj::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { QPoint screenPoint = event->screenPos(); QPointF scenePoint = event->scenePos(); QPointF itemPoint = event->pos(); qDebug() << "HoverEnter ScenePos: " << scenePoint; qDebug() << "HoverEnter ScreenPos: " << screenPoint; qDebug() << "HoverEnter ItemPos: " << itemPoint; // innerRect = QRectF(50, 50, 50, 50) if (innerRect.contains( mapFromScene(scenePoint) )) qDebug() << "HoverEnter hits Rect"; else qDebug() << "Rect not hit"; // OR // local item point (1, 25) mapped to scene and compared with scene event coords // if (mapToScene(1, 25) == scenePoint) // qDebug() << "Match single point (1, 25)"; // else // qDebug() << "No hit on (1, 25)"; QGraphicsItem::hoverEnterEvent(event); }
-
-
wrote on 25 Oct 2024, 08:07 last edited by JonB
@james-b-s
Hopefully @Pl45m4's excellent reply resolves everything for you. I think you are in the first situation he mentions. I would be tempted to usemapToScene()
and then do everything in scene coordinates, easiest to conceptualize.Just going back to your original post, in case it helps sort you out:
My understanding is that
myQGraphicsObject->mapToScene(pointInItemCoordinates)
should return something in screen coordinates
What I get out of mapToScene is the exact value that I put into mapToScenemapToScene()
returns scene coordinates. They are not the same as screen coordinates. (Screen coordinates always involveQGraphicsView
, even if implicitly.)- You only happen to get
myQGraphicsObject->mapToScene(pointInItemCoordinates) == pointInItemCoordinates
because yourmyQGraphicsObject->pos() == QPointF(0, 0)
ANDmyQGraphicsObject->parent() == nullptr
or equivalentlymyQGraphicsObject->scenePos() == QPointF(0, 0)
. If your item is not at (0,0) on the scene you would not get this identity result.
1/11