Qt - QCustomPlot painting graph - qt

I have a problem with drawing the graph in QCustomPlot library. I would like to draw a logarithm graph but I use drawing on the interval <-3;3>. Because logarithm is not defined from -3 to 0, I tried to do nothing while drawing on this interval.
I have this code:
QVector<double> x(10001), y(10001);
QVector<double> x1(10001), y1(10001);
double t=-3; //cas
double inkrement = 0.0006;
for (int i=0; i<10001; i++)//kvadraticka funkcia
{
x[i] = t;
y[i] = (-1)*t*t-2;
t+=inkrement;
}
int g=0;
for(double l=-3;l<3; l+=inkrement) {
if(l<=0.0) continue;
else {
//QMessageBox::warning(this, tr("note"), tr("l=%1\n").arg(l), QMessageBox::Ok);
x1[g] = l;
y1[g] = log10(l)/log10(exp(1.0));
//QMessageBox::warning(this, tr("note"), tr("x1=%1\ny1=%2").arg(x1[g]).arg(y1[g]), QMessageBox::Ok);
//break;
g++;
}
}
customPlot->addGraph();
customPlot->graph(0)->setData(x, y);
customPlot->addGraph();
customPlot->graph(1)->setData(x1, y1);
customPlot->xAxis->setLabel("x");
customPlot->yAxis->setLabel("y");
customPlot->xAxis->setRange(-3, 3);
customPlot->yAxis->setRange(-10, 5);
customPlot->replot();
where x1 and y1 are QVectors... But the graph is like the first point is in [0,0]. So I have then a line that connects point [0,0] with the logarithm graph and I dont know why :(
When I put l=0.0006 before the cycle, everything is OK. Can you help me with that please?

It seems that you set count of x1 and y1 before this loop. QVector is initialized with zeros. So if you don't set any value for some items then x1 and y1 will contain zero values at their end.
You should use empty QVector's and add new values if g is OK:
QVector<double> x1, y1;
//...
x1 << l;
y1 << log10(l)/log10(exp(1.0));
g variable can be removed then. And I think it's better to remove i variable and use for(double l = -3; l <= 3; l+=increment) loop.

Related

QCustomPlot vertical line at axis

I am working QCustomPlot with Qt and need to change the color of a particular vertical grid line within the graph please let us know how we can change that I attached the image of my requirement.
The bleo code solve the issue
GraphTesting(QCustomPlot * customPlot)
{
// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i = 0; i < 101; ++i)
{
x[i] = i; //i / 50.0 - 1; // x goes from -1 to 1
y[i] = x[i]/2; // let's plot a quadratic function
}
// create graph and assign data to it:
customPlot->addGraph();
customPlot->graph(0)->setData(x, y);
// give the axes some labels:
customPlot->xAxis->setLabel("x");
customPlot->yAxis->setLabel("y");
customPlot->rescaleAxes();
QCPItemLine *step = new QCPItemLine(customPlot);
step->setPen(QPen(QColor(140, 0, 0)));
double begin = 25;
double first = customPlot->yAxis->range().lower;
double end = customPlot->yAxis->range().upper; //example values
step->start->setCoords(begin, first);
step->end->setCoords(begin, end);
customPlot->replot();
}

Calculate no of elements in a matrix

I am solving a problem in programming where I have a matrix and given two positions I need to find the elements in between including the elements given
So for example a matrix with 1000 rows and 1000 columns initial position is [499,499] and final position is [500,500] the number of elements are 4
I wanted to know if there is any mathematical formula that can be applied on any matrix
Well to get the number of elements it would be (500-499+1)*(500-499+1) or (x2-x1+1)*(y2-y1+1) which could be used for possible memory allocation depending on what programming language you are using. Then to access the elements of the matrix, you could create a matrix of size calculated with the values provided and return that.
Matrix getSubMatrix(Matrix matrix, int x1, int y1, int x2, int y2) {
// This is assuming matrixes can be created this way
// x2-x1+1 and y2-y1+1 should provide the correct dimensions for the values
// to be extracted from the provided matrix
Matrix submatrix = new Matrix(x2-x1+1, y2-y1+1);
// Now we will itterate through both dimensions of the original matrix
// and the new matrix
for (int i = 0; i < x2-x1+1; i++) {
for (int j = 0; j < y2-y1+1; j++) {
// The new matrix can be accessed with i and j, but the original matrix
// requires the offset of x1 and y1
subMatrix[i][j] = matrix[i+x1][j+y1];
}
}
return submatrix;
}
Note that you could also use arrays instead of Objects for the input parameters and return value. As matt did with his answer
As SergGr pointed out the case where x1 > x2 or y1 > y2 to fix that and not assume that x1 < x2 and y1 < y2. You can replace the x1 in the method with min(x1,x2), x2 with max(x1,x2) and the same for y1 and y2.
Sure just do it with two for loops:
int[][] matrix = new int[1000][1000];
populateMatrix(matrix); // populate the matrix with some values, somehow
int pos_1_X = 499;
int pos_1_Y = 499;
int pos_2_X = 500;
int pos_2_Y = 500;
int numElements = 0;
for(int x = pos_1_X; x <= pos_2_X; x++) {
for(int y = pos_1_Y; y <= pos_2_Y; y++) {
numElements++; // increment the counter
System.out.printf("matrix[%d][%d] = %d", x, y, matrix[x][y]); // print the element
}
}
System.out.println("Number of elements: " + numElements);

OpenCL function calls

I'm working on an openCL kernel that loads up some points, decides which is the highest, and returns it. All good there, but I want to add a calculation before the highest evaluation. This compares the point to a pair of lines. I have it written and working to a degree, as follows:
size_t i = group_id * group_stride + local_id;
while (i < n){
//load up a pair of points using the index to locate them within a massive dataSet
int ia = LOAD_GLOBAL_I1(input, i);
float4 a = LOAD_GLOBAL_F4(dataSet, ia);
int ib = LOAD_GLOBAL_I1(input, i + group_size);
float4 b = LOAD_GLOBAL_F4(dataSet, ib);
//pre-assess the points relative to lines
if(pass == 0){
float px = a.x;
float py = a.y;
int checkAnswer;
//want to write this section as a function
float x1 = tri_input[0].x; float y1 = tri_input[0].y;
float x2 = tri_input[2].x; float y2 = tri_input[2].y;
float check = sign((x1-x2) * (py-y1) - (y2-y1) * (px-x1));
if(check != tri_input[3].x){ //point is outside line 1
checkAnswer = 1;
}
else{
x1 = tri_input[2].x; y1 = tri_input[2].y;
x2 = tri_input[1].x; y2 = tri_input[1].y;
check = sign((x1-x2)*(py-y1) - (y2-y1)*(px-x1));
if(check != tri_input[3].y){ //point is outside line 2
checkAnswer = 2;
}
else{
checkAnswer = 0; //point is within both lines
}}}
//later use the checkAnswer result to change the following
//find the highest of the pair
float4 result;
if(a.z>b.z) result = a;
else result = b;
//load up the previous highest result locally
float4 s = LOAD_LOCAL_F4(shared, local_id);
//if the previous highest beat this, stick, else twist
if(s.z>result.z){ STORE_LOCAL_F4(shared, local_id, s);}
else{ STORE_LOCAL_F4(shared, local_id, result);}
i += local_stride;
}
What I would like to do is call the line check twice as a function, i.e the code becomes:
size_t i = group_id * group_stride + local_id;
while (i < n){
//load up a pair of points using the index to locate them within a massive dataSet
int ia = LOAD_GLOBAL_I1(input, i);
float4 a = LOAD_GLOBAL_F4(dataSet, ia);
int ib = LOAD_GLOBAL_I1(input, i + group_size);
float4 b = LOAD_GLOBAL_F4(dataSet, ib);
//pre-assess the points relative to lines
if(pass == 0){
float px = a.x;
float py = a.y;
int checkA = pointCheck( px, py, tri_input);
px = b.x;
py = b.y;
int checkB = pointCheck( px, py, tri_input);
}
//later use the checkAnswer result to change the following
//find the highest of the pair
float4 result;
if(a.z>b.z) result = a;
else result = b;
//load up the previous highest result locally
float4 s = LOAD_LOCAL_F4(shared, local_id);
//if the previous highest beat this, stick, else twist
if(s.z>result.z){ STORE_LOCAL_F4(shared, local_id, s);}
else{ STORE_LOCAL_F4(shared, local_id, result);}
i += local_stride;
}
In this instance the function is:
int pointCheck( float *px, float *py, float2 *testLines){
float x1 = testLines[0].x; float y1 = testLines[0].y;
float x2 = testLines[2].x; float y2 = testLines[2].y;
float check = sign((x1-x2) * (py-y1) - (y2-y1) * (px-x1));
if(check != testLines[3].x){ //point is outside line 1
return 1;
}
else{
x1 = testLines[2].x; y1 = testLines[2].y;
x2 = testLines[1].x; y2 = testLines[1].y;
check = sign((x1-x2)*(py-y1) - (y2-y1)*(px-x1));
if(check != testLines[3].y){ //point is outside line 2
return 2;
}
else{
return 0; //point is within both lines
}}}
Whilst the longhand version runs fine and returns a normal 'highest point' result, the function version returns an erroneous result (not detecting the highest point I have hidden in the data set). It produces a wrong result even though the function as yet has no overall effect.
What am I doing wrong?
S
[Update]:
This revised function works as far as the commented out line, then hangs on something:
int pointCheck(float4 *P, float2 *testLines){
float2 *l0 = &testLines[0];
float2 *l1 = &testLines[1];
float2 *l2 = &testLines[2];
float2 *l3 = &testLines[3];
float x1 = l0->x; float y1 = l0->y;
float x2 = l2->x; float y2 = l2->y;
float pX = P->x; float pY = P->y;
float c1 = l3->x; float c2 = l3->y;
//float check = sign((x1-x2) * (pY-y1) - (y2-y1) * (pX-x1)); //seems to be a problem with sign
// if(check != c1){ //point is outside line 1
// return 1;
// }
// else{
// x1 = l2->x; y1 = l2->y;
// x2 = l1->x; y2 = l1->y;
// check = sign((x1-x2) * (pY-y1) - (y2-y1) * (pX-x1));
// if(check != c2){ //point is outside line 2
// return 2;
// }
// else{
// return 0; //point is within both lines
// }}
}
One immediate issue is how you pass the parameters to the called function:
int checkA = pointCheck( px, py, tri_input);
whereas the function itself expects pointers for px and py. You should instead call the function as:
int checkA = pointCheck(&px, &py, tri_input);
It is surprising that OpenCL does not give build errors for this kernel.
In my experience, some OpenCL runtimes do not like multiple return statements in a single function. Try to save the return value into a local variable and use a single return statement at the end of the function. This is because OpenCL does not support real function calls, but rather inlines all functions directly into the kernel. A best practice is therefore to mark all non __kernel functions as inline, and treat them as such (i.e. make it easier for the compiler to inline your function by not using multiple return statements).

How do I optimize displaying a large number of quads in OpenGL?

I am trying to display a mathematical surface f(x,y) defined on a XY regular mesh using OpenGL and C++ in an effective manner:
struct XYRegularSurface {
double x0, y0;
double dx, dy;
int nx, ny;
XYRegularSurface(int nx_, int ny_) : nx(nx_), ny(ny_) {
z = new float[nx*ny];
}
~XYRegularSurface() {
delete [] z;
}
float& operator()(int ix, int iy) {
return z[ix*ny + iy];
}
float x(int ix, int iy) {
return x0 + ix*dx;
}
float y(int ix, int iy) {
return y0 + iy*dy;
}
float zmin();
float zmax();
float* z;
};
Here is my OpenGL paint code so far:
void color(QColor & col) {
float r = col.red()/255.0f;
float g = col.green()/255.0f;
float b = col.blue()/255.0f;
glColor3f(r,g,b);
}
void paintGL_XYRegularSurface(XYRegularSurface &surface, float zmin, float zmax) {
float x, y, z;
QColor col;
glBegin(GL_QUADS);
for(int ix = 0; ix < surface.nx - 1; ix++) {
for(int iy = 0; iy < surface.ny - 1; iy++) {
x = surface.x(ix,iy);
y = surface.y(ix,iy);
z = surface(ix,iy);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix + 1, iy);
y = surface.y(ix + 1, iy);
z = surface(ix + 1,iy);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix + 1, iy + 1);
y = surface.y(ix + 1, iy + 1);
z = surface(ix + 1,iy + 1);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
x = surface.x(ix, iy + 1);
y = surface.y(ix, iy + 1);
z = surface(ix,iy + 1);
col = rainbow(zmin, zmax, z);color(col);
glVertex3f(x, y, z);
}
}
glEnd();
}
The problem is that this is slow, nx=ny=1000 and fps ~= 1.
How do I optimize this to be faster?
EDIT: following your suggestion (thanks!) regarding VBO
I added:
float* XYRegularSurface::xyz() {
float* data = new float[3*nx*ny];
long i = 0;
for(int ix = 0; ix < nx; ix++) {
for(int iy = 0; iy < ny; iy++) {
data[i++] = x(ix,iy);
data[i++] = y(ix,iy);
data[i] = z[i]; i++;
}
}
return data;
}
I think I understand how I can create a VBO, initialize it to xyz() and send it to the GPU in one go, but how do I use the VBO when drawing. I understand that this can either be done in the vertex shader or by glDrawElements? I assume the latter is easier? If so: I do not see any QUAD mode in the documentation for glDrawElements!?
Edit2:
So I can loop trough all nx*ny quads and draw each by:
GL_UNSIGNED_INT indices[4];
// ... set indices
glDrawElements(GL_QUADS, 1, GL_UNSIGNED_INT, indices);
?
1/. Use display lists, to cache GL commands - avoiding recalculation of the vertices and the expensive per-vertex call overhead. If the data is updated, you need to look at client-side vertex arrays (not to be confused with VAOs). Now ignore this option...
2/. Use vertex buffer objects. Available as of GL 1.5.
Since you need VBOs for core profile anyway (i.e., modern GL), you can at least get to grips with this first.
Well, you've asked a rather open ended question. I'd suggest using modern (3.0+) OpenGL for everything. The point of just about any new OpenGL feature is to provide a faster way to do things. Like everyone else is suggesting, use array (vertex) buffer objects and vertex array objects. Use an element array (index) buffer object too. Most GPUs have a 'post-transform cache', which stores the last few transformed vertices, but this can only be used when you call the glDraw*Elements family of functions. I also suggest you store a flat mesh in your VBO, where y=0 for each vertex. Sample the y from a heightmap texture in your vertex shader. If you do this, whenever the surface changes you will only need to update the heightmap texture, which is easier than updating the VBO. Use one of the floating point or integer texture formats for a heightmap, so you aren't restricted to having your values be between 0 and 1.
If so: I do not see any QUAD mode in the documentation for glDrawElements!?
If you want quads make sure you're looking at the GL 2.1-era docs, not the new stuff.

RGB color bitmap and HSV bilinearly interpolated colors

I want to use the algorithm from converting an HSV color value into RGB color to compute a 200 x 200 RGB bitmap with the colors red, green, blue, and white in its corners and bilinearly interpolated HSV colors elsewhere and compute also the bitmap with bilinearly interpolated RGB colors. I have found the formula in the wikipedia but I am confused on how to do this.
Any help would be appreciated.
OK, I think I know what you are getting at. I haven't tried to run any of this, so it probably has some bugs...
First you need to work out the HSV values for red, green, blue and white. Call these, clockwise, a,b,c,d - for example, white would be [0,0,1] or something scaled like that
For a position in the grid, (x,y) with 0 <= x <= 1 The interpolation bit is something like, putting the values into the array out:
for(int i=0; i<3; i++){
out[i] = y*((x*a[i]) + ((1-x)*b[i])) + (1-y)*((x*d[i]) + ((1-x)*c[i]));
}
As finding the linearly interpolated value the a fraction of x between A and B is given by x*A + (1-x)*B. Just do it once for each direction.
Then just convert them to RGB, using the convention from the wikipedia article
void HSVtoRGB(double H, double S, double V, double[] out){
double C = S*V;
double H_prime = H/60; // a number in [0,3]
double X = C*(1 - abs((H_prime%2)-1));
// Do the big if bit
switch((int)X){
case 0:
out[0] = C;
out[1] = X;
out[2] = 0;
case 1:
out[0] = X;
out[1] = C;
out[2] = 0;
// etc etc
}
double m = V - C;
for(int i=0; i<3; i++){
out[i] += m;
}
}
That should do it, give or take. Well, should give you a rough idea at least.

Resources