How many lines can Qt draw on-screen? - qt

I am currently working on a Qt application to draw maps. I am trying to draw 400,000+ lines and it crashes after using ~2GB but I still have memory left on my machine. I am wondering if I am hitting some limit inside of Qt that is causing the problem. Anyone know if there is a limit to the number of things you can draw or if you can change this limit?
If it is helpful, I am coding in C++ with a class that has a member function to draw the lines. The code is roughly as follows
QPointF fromPoint;
QPointF toPoint;
fromPoint = foo( x );
toPoint = foo( y );
m_Painter.drawLine(fromPoint, toPoint );
//m_Painter is a QPainter
Edit: Turns out the problem was somewhere else in the code. It had to do with the custom caching that was being done. Though I am still interested if there is a limit to how many lines Qt can draw. Does anyone know?

QPainter executes its underlying graphics through QPaintEngine, which has several implementations (like qpaintengine_mac.cpp, qpaintengine_x11.cpp, or qpaintengine_preview.cpp).
Some devices are raster...and are likely drawing each line into an image buffer and throwing away the endpoints after that drawing is done. There should be no limit to the number of lines you can draw in that case.
If the target device is OpenGL, or to a printer that is doing some kind of PostScript-like output, then the limitations of that particular paint engine may well be a factor. You'd have to look at the specific one.
For example: if you trace down the X11 implementation of drawLine you'll see it passes through to drawPolygon() down through strokePolygon_dev()...and bottoms out at a call to XDrawLines:
XDrawLines(dpy, hd, gc, pts, numberPoints, CoordModeOrigin);
So there you have another abstraction layer...and so the question becomes whether the XWindows display parameter is guaranteed to be raster. (My guess would be that it is.)
Anyway, so the answer is "unlimited if raster. may depend otherwise--but the limitations (if any) are probably coming from the underlying device for the paint engine, not Qt."

Related

Real time graph plotting using Processing

I have to plot a graph in processing by the feedback from encoder motors of the bot. so I have two variables basically left motor encoder and right motor encoder. I planned to vary on in x-axis and another in y-axis. While I went through some of the code on internet I found that, almost everyone has written the graph part code in serial event itself?
So my first doubt is why do they write it in serial event() function rather than void draw()? Another thing is when I tried to write my code for graph in void draw() it had a pseudo code something like this:
xpos1=0,ypos1=height;
void draw():
line(xpos1,ypos1,xpos,height-ypos);// obviously the data(xpos,ypos) is mapped with the width and height of the processing ide window.
xpos1=xpos;
ypos1=height-ypos;
if(xpos1>=width)
{
xpos1=0;
}
if(ypos1>=height)
{
ypos1=0;
}
So I get to see only a small dot traversing on processing ide window and I cannot see the older path that my line has travelled which in the case of the sites which I described when wrote the similar piece of code in serial event() they had a whole graph getting made on the processing window.
Where am I getting wrong? Also is there any alternative to plot the graph using void draw()? I want to vary both xpos as well as ypos as i get two feedbacks form left motor and right motor.
Screenshot of my attempted graph in different frames!
Image
Screenshot of one of the graphs made by somewhat the similar code displayed above but written in the serial event() available on the internet:
As stated in the comments, there are too many subquestions here.
Regarding the question relative to the code, there is one main line that is making the code much more complex than it has to be. You are trying to draw a line between each and every couple of numbers received by the two encoders. There is no need to do that. When plotting a graph, I personally use the point(x,y) function. It's much easier to implement for prototyping purposes, and adjusting the frameRate() at which the sketch is running, you won't notice the difference.
void draw() {
point(encoder1, encoder2);
if (encoder1 >= width) {
encoder1 = encoder1 - width;
}
if (encoder2 >= height) {
encoder2 = encoder2 - height;
}
}
A simple sketch like this one will do the job.
The other thing that is not quite clear is the initialisation of the variables. Usually you initialise a variable if it's continuously increasing, like time, but from your description you want to plot on the X axis one encoder, and on the Y axis the other encoder. So wouldn't it be better to map the values to start with in order not to have them go out of the canvas range?
Please edit the question so that the code is clear and concise, following these guidelines, and try to ask one question per post.

How can I transform my canvas in PlayN?

Application screenshot: http://i.imgur.com/0uVKZiL.png
Source file: http://pastie.org/private/rcgm6o7qso8y0vz8nfjn0w
My application draws curves and I would like to be able to zoom in and out. When I apply a scale and translate transformation, the mapCanvasImage.canvas().gfx.transform changes accordingly, but nothing changes on the screen.
I used to have a different render approach (source code) in which the transformation did work, but there I could not get the layer to clear after each paint (results from previous paint iterations were still visible).
Perhaps (or likely) I am doing something fundamentally wrong. :) Any advice?
The Canvas offers nice high-level functions to draw Bézier curves, but is apparently flawed. My current plan is to abandon the Canvas and write my own code to convert Bézier curves to line segments. This is really easy and gives the added benefit of using less CPU power, since the Canvas is not hardware accelerated.

Image Plots components

At page 136 of the user manual of ILNumerics CTP (RCh), there is a mention to an Image Plot, in the "future section".
Is this the name of a new coming component similar two the TwoDMode of a 3D surface in a PlotCube, but optimized for 2D rendering or so? Could you describe its use case/functionalities?
(I would appreciate to have the possibility to quickly draw image plots (like Matlab imagesc) even with GDI backend. Currently GDI is to slow to render 700x700 ILSurface objects in a PlotCube with TwoDMode=true.)
imagesc - as you noticed - can be realized by a common surface plot in 2D mode. A 'real' imagesc plot would hardly do anything else. If the GDI renderer is too slow on your hardware, I'd suggest to
switch to an OpenGL driver, or
decrease the size of the rendering output, or
prevent from transparent colors (Wireframe or Fill), or
decrease the number of grid columns / rows in the surface
Note, the GDI renderer is mostly provided as fallback for OpenGL and for offscreen rendering. It utilizes decent scanline / z-buffer rendering. But naturally, it is not able to deliver the same speed as hardware accelerated OpenGL driver. However, 700x700 output should work even with GDI - on recent hardware (at least a couple of frames per second, I would guess).

Qt/PyQt - frequently drawing pixmap to widget, partly not drawing correctly

I'm working on a Qt based application (actually in PyQt but I don't think that's relevant here), part of which involves plotting a potentially continuous stream of data onto a graph in real time.
I've implemented this by creating a class derived from QWidget which buffers incoming data, and plots the graph every 30ms (by default). In __init__(), a QPixmap is created, and on every tick of a QTimer, (1) the graph is shifted to the left by the number of pixels that the new data will take up, (2) a rectangle painted in the space, (3) the points plotted, and (4) update() called on the widget, as follows (cut down):
# Amount of pixels to scroll
scroll=penw*len(points)
# The first point is not plotted now, so don't shift the graph for it
if (self.firstPoint()):
scroll-=1
p=QtGui.QPainter(pm)
# Brush setup would be here...
pm.scroll(0-scroll, 0, scroll, 0, pm.width()-scroll, pm.height())
p.drawRect(pm.width()-scroll, 0, scroll, pm.height())
# pen setup etc happens here...
offset=scroll
for point in points:
yValNew = self.graphHeight - (self.scalePoint(point))
# Skip first point
if (not(self.firstPoint())):
p.drawLine(pm.width()-offset-penw, self.yVal, pm.width()-offset, yValNew)
self.yVal = yValNew
offset-=penw
self.update()
Finally, the paintEvent simply draws the pixmap onto the widget:
p = QtGui.QPainter(self)
p.drawPixmap(0, 0, self.graphPixmap)
As far as I can see, this should work correctly, however, when data is received very fast (i.e. the entire graph is being plotted on each tick), and the widget is larger than a certain size (approx 700px), everything to the left of the 700px area lags considerably. This is perhaps best demonstrated in this video: http://dl.dropbox.com/u/1362366/keep/Graph_bug.swf.html (the video is a bit laggy due to the low frame rate, but the effect is visible)
Any ideas what could be causing this or things I could try?
Thanks.
I'm not 100% sure if this is the problem or not, but I thought I might make at least some contribution.
self.update() is an asynchronous call, which will cause a paint event at some point later when the main event loop is reached again. So it makes me wonder if your drawing is having problems because of the sync issue between when you are modifying your pixmap vs when its actually getting used in the paintEvent. Almost seems like what you would need for this exact code to work is a lock in your paintEvent, but thats pretty naughty sounding.
For a quick test, you might try forcing the event loop to flush right after your call to update:
self.update()
QtGui.QApplication.processEvents()
Not sure that will fix it, but its worth a try.
This actually might be a proper situation to be using repaint() and causing a direct paint event, since you are doing an "animation" using a controlled framerate: self.repaint()
I noticed a similar question to yours, by someone trying to graph a heart monitor in real time: http://qt-project.org/forums/viewthread/10677
Maybe you could try restructuring your code similar to that. Instead of splitting the painting into two stages, he is using a QLabel as the display widget, setting the pixmap into the QLabel, and painting the entire graph immediately instead of relying on calls to the widget.update()

Using Qt To Draw the Graph of Sin(x)

I'm experimenting with ways to draw a sinusoidal graph.
My widget is only expecting to get passed in a few arbitrary data points. I have to fit these data points to a sinusoidal line curve:
So far, I've tried a few methods using QPainterPath.
QPainterPath::lineTo - I tried using this function to plot the curve by taking my data points and creating so many points BETWEEN them, that the line actually smooths out a bit. This is a little too computationally intensive though, I feel.
QPainterPath::cubicTo - From what I gathered from RTFM, this is the best way to go. The only problem is that I'm not sure how to plot my control points at spots where it will consistently and programmatically smooth out the curve the way I want it to. I was unable to get the desired result with this function.
After some googling, I came across a few forum posts that were using Qwt for curve plotting. It would be great if I could use Qwt, but it's not an option since I'm restricted to only using Qt.
Does anyone have helpful feedback/suggestions?
I am doing a very similar thing currently with painting the bode sweep of a parametric EQ (a long line with multiple sweeping curves). The way I'm doing it (pseudo style):
qreal yCoords[GRAPH_WIDTH];
...
QPainter Painter(this);
Painter.setRenderHint(QPainter::Antialiasing, true);
//Painter.setRenderHint(QPainter::HighQualityAntialiasing, true); //opengl specific
for(int xCoord = 0; xCoord < GRAPH_WIDTH; x++)
Path.lineTo(QPointF(xCoord, yCoord[xCoord]));
...
Painter.drawPath(Path);
The combination of the calls to setRenderHint and drawing lines with QPointF (i.e. two qreal) rather than QPoint (two int) makes the line very smooth.
We're using this on an SBC running Ubuntu and getting redraw timings (including all of the complex math to get the points in the first place) of ~80ms for a 600x300px graph. Initial tests show that enabling opengl rendering reduces this to ~8ms (clearly the processor intensive task is the painting with antialiasing), so if you can do that, I think this solution will work for you.
QCustomPlot is a free and easy to use class that can be found online. It may be better for what you are looking to do.

Resources