2D plot of position and angle in Qt - c++

I have made a controller for a car and I am currently trying to make a GUI for the controller in Qt.
The only thing I am lacking now is a visualization of the car's position and angle relative to its starting point.
I want to make something like this:
where the circle represents the car and the line in it represents its heading/angle.
An added bonus feature would be to have a fading trace of its path as it moves, but if I got the basics down, I should be able to sort that out myself.
I have tried looking at some plot examples, but couldn't extrapolate what I needed to solve my problem.
How would you recommend going about the implementation of something like this?

You say:
I have all the measurements
So let's assume that you have Euler angles such that you can filter out changes in roll and only consider changes in φ.
To do this you'll be looking to extend a QWidget adding a member φ, we'll name it: m_phi. We'll also need to add your QPixMap as a member, we'll call it m_px. And you'll be overriding the QWidget::paintEvent.
paintEvent(qPaintEvent* /*event*/) {
if(!m_px.isNull()) {
QPainter* p;
p.setRenderHint(QPainter::Antialiasing);
p.translate(width() / 2.0, height() / 2.0);
p.save();
p.rotate(m_phi);
QRect r = m_px.rect();
r.moveCenter(QPoint());
p.drawPixmap(r, m_px);
p.restore();
}
}

Related

Qt QGraphicView and QGraphicScene mouse position

I have project which display inner structure of ELF binary files. I use QGraphicsView and QGraphicsScene. So I can display blocks on graphics scene, but I need after mouse click on single block display content of this block. I am trying use function:
void MainWindow::mousePressEvent(QMouseEvent* event)
{
ui->textEdit->append(QString("x = %1, y = %2").arg(event->Pos().x()).arg(event->Pos().y()));
}
But position is tracking in whole window. Problem is, that width and height of window is dynamical and height of QGraphicsScene may be greater than window's. So I can't track single block.
I tryed some function like:
mapFromScene, mapToScene, mapFromGlobal, ... but I don't know, how theese functions works, but position what I get wasn't right.
It occurred to me that position should be calculated by scrollbar of QGraphicalView and size of window, but it's hard to calculated precisely and it's not correct solution.
Some idea, how get true position on graphic scene? Thanks for any help.
QGraphics, like other graphics frameworks, uses multiple coordinate systems and you need to consider which system you're working in when dealing with coordinates.
We can think of a QGraphicsSceneas a world, within which there are objects that are represented by QGraphicsItems ( or QGraphicsObject's. if you want them to use signals and slots).
To view an area of the world, we use one or more QGraphicsViews.
In order to map between the different coordinate systems, Qt provides the useful mapTo and mapFrom functions.
Starting at the top, with a QGraphicsView, we can convert a coordinate and use QGraphicsView::mapToScene to get the coordinate in the scene's coordinate system. From this, if an item resides at that coordinate, we can get the coordinate relative to the item, using QGraphicsItem::mapFromScene.
So, with the three levels (view, scene and item) think about which system the coordinate is in and where you want to be dealing with it.
how get true position on graphic scene?
Hopefully you should now be thinking that the coordinate you have been provided in the MainWindow is in the view's coordinate system and you can map to the scene's coordinate system.
QPointF scenePoint = mapToScene(event->Pos());
However, this is overcomplicating things and you'll find it easier to work directly with the scene and the items it contains, by overloading the item's own mouseMove/Press/Release events, which provide QGraphicsScene coordinates.
I solved this problem with make my object, which inherit QGraphicView (MyQGraphicView) and then I declared function mousePressedEvent for this object. This help me.

Qt - Using a QTransform (or similar), scale inner QRect to/from QGraphics

Some background -
Say you have QGraphicsScene, and only one view, which is a 1-1 scale with the scene.
You have a QRect A, which is represents an external view of the scene, with a pre-defined pixel size.
You have a QRect A1 which is a smaller rect inside of A.
How do you translate A1 to the scene, such that it is scaled correctly (i.e. if it's 1/4 of rect A, it will occupy 1/4 of the scene), and then undo that transform to scale a rect created in the scene to fit in rect A correctly?
I can do all this brute force, but I'm wondering if there's a way using Qt's built in classes...
After looking over some examples to try and find similar uses, I realized I'm totally missing the point - I can just set A/A1 directly to the scene, and scale the view (via the totally obvious but somehow completely overlooked until now QGraphicsView::fitInView(..)) to fit the rects inside. No rect transforms necessary. Total 'duh' moment. :)
I will need to transform mouse clicks and points in the view when interacting with it, but there is a whole nice set of mapTo* mapFrom* that will handle that nicely.
TL;DR - Use fitInView()

QGraphicsItem setTransformOriginPoint seems to be ignored

I want to transform a QGraphicsItem by its Qt::YAxis, what works very well.
QTransform trans;
trans.rotate (value, Qt::YAxis);
item->setTransformOriginPoint (0,0);
//item->setTransformOriginPoint (500, 250);
item->setTransform (trans);
The problem i have is that the setTransformOriginPoint seems to be ignored 'cause it dont work. Everytime my item transforms at its left-side. But i want to transform it by its right-side and i think i am affected by this bug:
https://bugreports.qt-project.org/browse/QTBUG-13378?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel
Can someone confirm a similar problem like this?
Or what i can do to transform my item at its right-side?
Edit: Sorry i forgot to say that i not use an animation like described at this bug-report!
A QTransform has everything about the transformation, include the origins where you want the transform to happen. setTransformOriginPoint() only affect simple functions like rotate() that does not specify the origins.
Try adding translate to your QTransform before adding rotate().
QTransform trans;
trans.translate(500, 250).rotate(value, Qt::YAxis);
item->setTransform(trans);
Edit:
Yes, QTransform in QGraphicsItem is not very straightforward to use. It's also really limited on what you can do. Starting with Qt 4.6, QGraphicsTransform can be used for higher level of control on the transformation. That may be what you are looking for.

QGraphicsPolygonItem drawing a open(not closed) polygon

I am using a QGraphicsPolygonItem and I have noticed that it always connects the end-point with the start-point.
I know that the polygon terms means exactly that, and what I am looking for is "polyline" or "polygonal chain". I didnt found nothing like that in QGraphicsItem subclasses.
How do I draw a polygonal chain in QGraphics Framework? Is there a property of QGraphicsPolygonItem or a class that does that?
I had a similar problem, and I solved it by using the QGraphicsPathItem class. In the following code, polygon is a non-closed QPolygonF object (i.e. a QPolygonF which start-point is different from its end-point):
QPainterPath path = new QPainterPath();
path.addPolygon(polygon);
QGraphicsPathItem contour = new QGraphicsPathItem(path);
contour.setPen(new QPen(QColor.black));
When displaying this QGraphicsPathItem object, the start-point is (in theory) disconnected from its end-point.
I'm sorry this example code is in Java; but the mechanisms should be the same as in C++.
You can use QPainterPath and use lineTo method to input yors polyline points, then just use QGraphicsPathItem to make it graphics item.
Alternatively you also might think about combining several QGraphicsLineItem into one QGraphicsItemGroup, but that's more difficult as you need to pay attention to aligning lines together.
Is this what you are looking for?
EDIT:
QPainterPath is apparently closing paths, then you are left with group of lines only.
EDIT2:
Sorry for confusing you, but HostileFork seem to be right - you just use QPainterPath and call pathItem->setBrush(QBrush(Qt::transparent)); to keep your path unfilled.

QGraphicsItem::setTransformOriginPoint bug when trying to scale image

I have created my own class by extending QGraphicsItem and I want to make it so that when someone does a wheel even while over this item, it scales.
This way, i can have multiple items in a scene, and scale each of them in and out as I please.
The problem is, I want the item to scale under the mouse cursor, much like google maps does. That is, a move forward will keep panning the image and scaling it, so taht the area in the vicinity around my mouse pointer is always in view.
void ImagePixmapItem::wheelEvent ( QGraphicsSceneWheelEvent * event ){
update();
qreal factor = 1.2;
if (event->delta() < 0)
factor = 1.0 / factor;
scale(factor, factor);
scaleFactor *=factor;
this->scene()->setSceneRect(0,0,this->boundingRect().width(), this->boundingRect().height());
}
This is the code I am using to do the scale. The problem is, it always seems to be scaling from the top left corner. Well, this is undesirable, beacuse if I scale in or out too much, eventually my area of interest around the mouse pointer has moved off the screen, and I have to either scroll manually or pan to the location, zoom, pan, etc, until i get to the desired level.
I tried to use the QGraphicsItem::setTransformOriginPoint, but no matter what values I put in there, it still seems to scale and such from the top left.
What can I add to that code I posted to get the desired effect?
I have achieved similar functionality in my Image-Manipulation application (scaling the view and having the area under my mouse stay in place and visible) but I scale the whole graphics-view not a specific item, so I don't know if this code can solve your problem.
Anyway, this is what I do in the constructor of my subclassed QGraphicsView (after I set the scene):
setTransformationAnchor(AnchorUnderMouse);
setResizeAnchor(AnchorViewCenter);
I also use the above functions, after each call to:
MyGraphicsView->setTransform(transform);
I'm not sure if this can help you, but I hope so.