I am getting streaming measurement data from an ultrasonic device moving inside a pipeline, and I want to make a sliding/realtime plot of these measurements. The Y axis would represent a gradient of the 360 degrees around the pipe, and the X axis would represent the length-wise position in millimeters. In other words, the X axis will update and move at the same rate as the scanner while new data is arriving (approx 40Hz). The value at each (x,y) coordinate represents one measurement, which should be mapped to a color in a colormap.
I am new to graphics (systems&backend guy) and I have been looking at QImage, QWT and QCustomPlot but none of them seem to straight-forward solve the problem without having to manually build a 2D matrix, draw it in a QImage, and update and shift the coordinates of each datapoint and redraw to move/scroll it. QCustomplot does this very nicely for graphs, but I don't see how it can be applied to their colormaps.
Any hints to frameworks or packages that provide primitives (or widgets) for this kind of plot would be much welcomed.
This can be done with Qwt. The trick is creating a wrapper around the series data that triggers a replot every time you add a data point. If you want to get fancy you can add a timer that removes old data from the series and triggers another replot.
See the CPU, oscilloscope, and realtime examples that come with the Qwt source code. They implement this trick.
Related
I am playing around with rgl and I have created a 3D rendering of the mouse brain, in which structures can be isolated and coloured separately.
The original data is a 3D array containing evenly spaced voxels.
Every voxel is coded with a structure ID.
Every structure is rendered separately as a mesh by marching cubes, and smoothed using Laplacian smoothing as implemented by Rvcg.
Some of these structures can be quite small, and it would make sense to look at them within the context of the whole brain structure.
One of the options is to create a low-threshold mesh of the whole set of voxels, so that only the outer surface of the brain is included in the mesh.
This surface can be smoothed and represented using a low alpha in rgl::shade3d colouring faces. This however seems to be quite taxing for the viewport as it slows down rotation etc especially when alpha levels are quite low.
I was wondering if there is any way to implement some sort of cel shading in rgl, e.g. outlining in solid colours the alpha hull of the 2D projection to the viewport in real time.
In case my description was not clear, here's a photoshopped example of what I'd need.
Ideally I would not render the gray transparent shell, only the outline.
Cel shading example
Does anybody know how to do that without getting deep into OpenGL?
Rendering transparent surfaces is slow because OpenGL requires the triangles making them up to be sorted from back to front. The sort order changes as you rotate, so you'll be doing a lot of sorting.
I can't think of any fast way to render the outline you want. One thing that might work given that you are starting from evenly spaced voxels is to render the outside surface using front="points", back="points", size = 1. Doing this with the ?surface3d example gives this fake transparency:
If that's not transparent enough, you might be able to improve it by getting rid of lighting (lit = FALSE), plotting in a colour close to the background (color = "gray90"), or some other thing like that. Doing both of those gives this:
You may also be able to cull your data so the surface has fewer vertices.
I'm currently rendering a 3D model (Wavefront .obj format) in my Qt program. Right now, I'm rendering the model using Scene3D in QML, and I'm able to get it to display in the viewing area. What I would like to do is have a user click on the model and generate a 2D cross section of the slice that I would like to plot on a different window. I'm quite new to 3D rendering, and a lot of Qt documentation isn't very descriptive. I've been reading Qt documentation, experimenting, and searching online with no luck. How can I create 2D slices of a 3D object Model in Qt 3D, preferably in QML? What Qt libraries or classes can I use to achieve this?
Unfortunately, the fact that models are stored as a set of surfaces makes this hard. QT probably doesn't have a built in method for this.
Consider, for example, that a model made of faces might be missing a face. What now? can you interpolate across that gap consistently from different angles? What about the fact that a cross-section probably won't contain any vertices?
But, of course, it can be solved. First, just don't allow un-closed surfaces (meshes with holes). Second, for finding the vertices of your cross-section, perform an intersection between every edge in your model and the plane you're using, and if there's an intersection, there's a point there. Third, to find the edges, look at the list of vertices, and any two that are from an edge on the same polygon in the mesh should be connected by an edge in the cross section. To find which direction the edge should go, project the normal of the polygon onto the plane your using. For filling, I don't really know what to do. I guess that's whatever you want it to be.
I am trying to enlarge a point cloud data set. Suppose I have a point cloud data set consisting of 100 points & I want to enlarge it to say 5 times. Actually I am studying some specific structure which is very small, so I want to zoom in & do some computations. I want something like imresize() in Matlab.
Is there any function to do this? What does resize() function do in PCL? Any idea about how can I do it?
Why would you need this? Points are just numbers, regardless whether they are 1 or 100, until all of them are on the same scale and in the same coordinate system. Their size on the screen is just a visual representation, you can zoom in and out as you wish.
You want them to be a thousandth of their original value (eg. millimeters -> meters change)? Divide them by 1000.
You want them spread out in a 5 times larger space in that particular coordinate system? Multiply their coordinates with 5. But even so, their visual representations will look exactly the same on the screen. The data remains basically the same, they will not be resized per se, they numeric representation will change a bit. It is the simplest affine transform, just a single multiplication.
You want to have finer or coarser resolution of your numeric representation? Or have different range? Change your data type accordingly.
That is, if you deal with a single set.
If you deal with different sets, say, recorded with different kinds of sensors and the numeric representations differ a bit (there are angles between the coordinate systems, mm vs cm scale, etc.) you just have to find the transformation from one coordinate system to the other one and apply it to the first one.
Since you want to increase the number of points while preserving shape/structure of the cloud, I think you want to do something like 'upsampling'.
Here is another SO question on this.
The PCL offers a class for bilateral upsampling.
And as always google gives you a lot of hints on this topic.
Beside (what Ziker mentioned) increasing allocated memory (that's not what you want, right?) or zooming in in visualization you could just rescale your point cloud.
This can be done by multiplying each points dimensions with a constant factor or using an affine transformation. So you can e.g switch from mm to m.
If i understand your question correctly
If you have defined your cloud like this
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
in fact you can do resize
cloud->points.resize (cloud->width * cloud->height);
Note that doing resize does nothing more than allocate more memory for variable thus after resizing original data remain in cloud. So if you want to have empty resized cloud dont forget to add cloud->clear();
If you just want zoom some pcd for visual puposes(i.e you cant see what is shape of cloud because its too small) why dont you use PCL Visualization and zoom by scrolling up/down
I'm plotting three 3D vector fields in one row in Maple 14:
> with(plots);
> A := Array(1 .. 3):
> A[1] := fieldplot3d(...):
> A[2] := fieldplot3d(...):
> A[3] := fieldplot3d(...):
> display(A);
Here are the three plots arranged like this: [plot1] [plot2] [plot3]
Now I can rotate each of them individually to explore the vector fields.
Is it possible to link other two plots so they will rotate to the same orientation automatically? It will be fine if this will be possible only when rotating just one of them (leftmost, for example).
For example, in MatLab there is linkprop function that can link properties of two axes so changes in one of them (rotation, scale, range, etc.) will be applied to other one too.
I don't believe that this can be done in current Maple using either the usual left-click-drag on the 3D plots or by adjusting the three orientation boxes in the plot menubar (which appears at the GUI's top, when you left-click to place the cursor focus on any of the individual 3D plots).
But you can set the plots in one or more Plot Components, and create three Sliders whose underlying Action code causes a redisplay. The three sliders could thus control the three orientation angles. This is not as pleasing as using the mouse cursor to rotate freehand. But at least it allows plots in several Plot Components (or, in your case an Array plot in a single Plot Component) to be rotated in unison.
One convenient way to set up the above in Maple 17, if you are unfamiliar with programming embedded components, is to use its enhanced Explore command.
In Maple 17 a simple example, which you might replace with calls to plots:-fieldplot, could be,
A:=Array(1..3):
A[1]:=plot3d(x^3*y,x=-10..10,y=-10..10):
A[2]:=plot3d(sin(x)*y,x=-10..10,y=-10..10):
A[3]:=plot3d(x*y^2,x=-10..10,y=-10..10):
Explore(plots:-display(A,orientation=[theta,phi,psi]),
parameters=[theta=-180..180,phi=-180..180,psi=-180..180]);
In Maple 16 the Explore command does not support the above call, but the three Sliders and the Plot Component are not difficult to hook together to get the same effect of unified reorientation and redisplay.
The above approach is not very memory efficient, as it entails recreation and communication of very many whole 3D plot structures from engine to GUI. That's in contrast to the kind of rotation obtained by freehand click-dragging of the mouse cursor over a 3D plot, which just involves the GUI alone and presumably just efficient OpenGL redisplay. Any kind of memory leak, even a small one for each passed 3D plot (as Maple 16's Standard GUI appears to have) and this approach could cause the Standard Java GUI to slowly consume memory and eventually grind to a halt.
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.