Customizing QwtPlot's scale and grid lines - c++

I'm confused with using QwtPlot class to draw a customized coordinate system.
My goal is to draw a coordinate system with customized scale, and draw grid line on these customized scales. Here are the values of the scales:
x-axis and y-axis scale:
x1=-0.642455
x2=0
x3=0.642455
y1=-0.642455
y2=0
y3=0.642455
I read the user's guide of QwtPlot class and QwtPlotGrid class. I found a function in QwtPlotGrid class called setxDiv and seemed that it could help, So I wrote the following code:
QList<double> doubleListmin;//min scale
QList<double> doubleListmed;//medium scale
QList<double> doubleListmaj;//major scale
doubleListmin.append(0.1);
doubleListmed.append(0.3);
doubleListmaj.append(0.642455);
QList<double> doubleList[3];
doubleList[0] = doubleListmin;
doubleList[1] = doubleListmed;
doubleList[2] = doubleListmaj;
QwtScaleDiv *xDiv = new QwtScaleDiv(-0.642455, 0.642455, doubleList);
//lowerbound is -0.642455, upperbound is 0.642455, doubleList customizes the scale
QwtPlotGrid *grid = new QwtPlotGrid();
grid->setXDiv(*xDiv);
//grid->updateScaleDiv(*xDiv, *xDiv);
grid->attach(this);
But it turned out to have no influence on the new QwtPlotGrid, it doesn't change its scale system.
I think there's another way: draw a several lines in the QwtPlot. But I don't know how to do it.
Somebody help me please!!!
Thank you in advance~

As you said "draw severalk lines" is not good approach because you can't do this lines infinity. To do this there is special class QwtPlotMarker which is more suitable here. Maybe not the best thing in the world, but works as you want:
QwtPlotMarker *m1=new QwtPlotMarker;
m1->setLinePen(QPen(Qt::gray));
m1->setLineStyle(QwtPlotMarker::VLine);
m1->setValue(0,0);
m1->attach(ui->qwtPlot);
QwtPlotMarker *m2=new QwtPlotMarker;
m2->setLinePen(QPen(Qt::gray));
m2->setLineStyle(QwtPlotMarker::HLine);
m2->setValue(0,0);
m2->attach(ui->qwtPlot);
QwtPlotMarker *m3=new QwtPlotMarker;
m3->setLinePen(QPen(Qt::gray));
m3->setLineStyle(QwtPlotMarker::HLine);
m3->setValue(0,-0.642455);
m3->attach(ui->qwtPlot);
QwtPlotMarker *m4=new QwtPlotMarker;
m4->setLinePen(QPen(Qt::gray));
m4->setLineStyle(QwtPlotMarker::HLine);
m4->setValue(0,0.642455);
m4->attach(ui->qwtPlot);
QwtPlotMarker *m5=new QwtPlotMarker;
m5->setLinePen(QPen(Qt::gray));
m5->setLineStyle(QwtPlotMarker::VLine);
m5->setValue(-0.642455,0);
m5->attach(ui->qwtPlot);
QwtPlotMarker *m6=new QwtPlotMarker;
m6->setLinePen(QPen(Qt::gray));
m6->setLineStyle(QwtPlotMarker::VLine);
m6->setValue(0.642455,0);
m6->attach(ui->qwtPlot);

Better create your own QwtScaleDiv object setting the ticks manually and assign them using QwtPlot::setAxisScaleDiv(). Update of the grid will happen automatically ( as long as you didn't decouple it explicitly ).
When you also need to manage the tick positions when zooming you have to derive your own scale engine instead - overloading the QwtScaleEngine::divideScale() method.

Related

Setting the position of a vtkLegendScaleActor object

I've defined my vtkLegendScaleActor like this:
vtkSmartPointer<vtkLegendScaleActor> legendScaleActor = vtkSmartPointer<vtkLegendScaleActor>::New();
legendScaleActor->GetLegendLabelProperty()->SetColor(0,0,0);
legendScaleActor->GetLegendTitleProperty()->SetColor(0,0,0);
legendScaleActor->SetBottomAxisVisibility(0);
legendScaleActor->SetTopAxisVisibility(0);
legendScaleActor->SetRightAxisVisibility(0);
legendScaleActor->SetLeftAxisVisibility(0);
legendScaleActor->GetLegendLabelProperty()->SetFontSize(legendScaleActor->GetLegendLabelProperty()->GetFontSize() * 2);
legendScaleActor->GetLegendTitleProperty()->SetFontSize(legendScaleActor->GetLegendTitleProperty()->GetFontSize() * 2);
I wanted to increase the font size in both label and title, and hide all the axis.
The result is:
Where I can see the geometry with the scale rule, but it is cropped by the limits of the window.
I would like to move up the legend, but I could find the right attribute of the given class. Any idea about how to do it?
EDIT
I've continued working on this issue and what I've done is to add a negative offset to the label and the title of the vtkLegendScaleActor object, with:
legendScaleActor->GetLegendTitleProperty()->SetLineOffset(-25);
legendScaleActor->GetLegendLabelProperty()->SetLineOffset(-25);
Having as a result:
Nevertheless, I cannot move the ruler, neither the whole set together... that's why I imagine that there should be a better solution.
Subclass the vtkLegendScaleActor. Then reimplement the BuildRepresentation method and modify the Coordinates of the LabelActors. With this you have full control of the representation, since all Actors and Mappers are protected and therefore modifieable.

2D plot of position and angle in Qt

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();
}
}

Tool tip to show plot values in Qwt

I have a qwt plot in my application. I want to show a small tool tip to show the value of the point at which mouse is pointed on the curve. I found that I have to use QwtPlotPicker for this, but couldn't find any proper example to implement this in my code. I am new to Qwt so it would be great if anyone could help me solve this problem.
Thanks, Rakesh.
The author himself says here:
A QwtPlotPicker gives you the current position of the mouse ( in screen and plot coordinates ). Then you need to find the closest points of your curves. You can use QwtPlotCurve::closestPoint(), but in most cases you can find a much faster implementation depending on the characteristics of your data.
When you need to compare the mouse position with the lines between the points you need the pixel position of these points ( use QwtPlot::canvasMap ).
Maybe looking at the CanvasPicker of the eventfilter example helps.
I implemented it in my own class, which is a subclass of QwtPlot. In the constructor I have the following:
QwtPlotPicker* plotPicker = new QwtPlotPicker(this->xBottom, this->yLeft, QwtPicker::CrossRubberBand, QwtPicker::AlwaysOn, this->canvas());
QwtPickerMachine* pickerMachine = new QwtPickerClickPointMachine();
plotPicker->setStateMachine(pickerMachine);
connect(plotPicker, SIGNAL(selected(const QPointF&)), this, SLOT(onSelected(const QPointF&)));
Now in my class (where the this pointer refers to) I should implement the slot onSelected(const QPointF&) which will give the plot coordinates.

Qt GUI Development - Displaying a 2D grid using QGraphicsView

I'm new to Qt development so I've being trying to research a solution to a user interface I need to design. My project is to simulate players in an online game moving around a global map. To represent the map I need to display a 2D grid, with each space in the grid representing a region of a map. I then need to display the location of each player in the game. The back-end is all fully working, with the map implemented as a 2D array. I'm just stuck on how to display the grid.
The research I have done has led me to believe a QGraphicsView is the best way to do this, but I can't seem to find a tutorial relevant to what I need. If anyone has any tips on how to implement this it would be much appreciated.
Thanks, Dan
A 2D Grid is nothing more than a set of horizontal and vertical lines. Suppose you have a 500x500 map and you want to draw a grid where the distance between the lines in both directions is 50. The sample code that follows shows you how you can achieve it.
// create a scene and add it your view
QGraphicsScene* scene = new QGraphicsScene;
ui->view->setScene(scene);
// Add the vertical lines first, paint them red
for (int x=0; x<=500; x+=50)
scene->addLine(x,0,x,500, QPen(Qt::red));
// Now add the horizontal lines, paint them green
for (int y=0; y<=500; y+=50)
scene->addLine(0,y,500,y, QPen(Qt::green));
// Fit the view in the scene's bounding rect
ui->view->fitInView(scene->itemsVBoundingRect());
You should check the QGraphicsView and the QGraphicsScene documentation as well as the corresponding examples. Also you can watch the graphics view training videos or some graphics view related videos from the Qt developer days.
Well if you have a constant grid size or even a limited number of grid sizes what i like to do is to draw a grid block in gimp or any other program and then set that as the background brush (draw only bottom and right side of the block) qt will repeat the image and will give you a full grid. I think this is good for performance too.
This is the grid image i used in one of my programs it's 10x10 pixels.
Then call QGraphicsScene setBackgroundBrush as the follwing:
scene->setBackgroundBrush(QBrush(QPixmap(":/grid/grid10.png")));
The more native way is this:
scene = self.getScene() # Your scene.
brush = QBrush()
brush.setColor(QColor('#999'))
brush.setStyle(Qt.CrossPattern) # Grid pattern.
scene.setBackgroundBrush(brush)
borderColor = Qt.black
fillColor = QColor('#DDD')
rect = QRectF(0.0, 0.0, 1280, 720) # Screen res or whatever.
scene.addRect(rect,borderColor,fillColor) # Rectangle for color.
scene.addRect(rect,borderColor,brush) # Rectangle for grid.
Sorry by PyQt...
Suppose a scene is set to the graphicsview then simply below one line will show the grid.
ui->graphicsView->scene()->setBackgroundBrush(Qt::CrossPattern);
There several other values can be passed for ex: Qt::Dense7Pattern
These are members of enum BrushStyle, just click on any used value in Qt creator and it will take you to the enum declaration where you can see all other possible values.
PS:
A scene can be set like this:
ui->graphicsView->setScene(new QGraphicsScene());

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.