Surface plot for any data

Started by
18 comments, last by Lord_Evil 14 years, 8 months ago
Hi all, I need to draw surface plot using OpenGL for the following data. X-Axis | Y-Axis | Z-Axis ========================= Jan-08 | 120.0 | 25.5 Feb-08 | 125.7 | 24.15 Mar-08 | 100.0 | 42.11 Apr-08 | 190.0 | 15.62 May-08 | 109.0 | 21.88 Jun-08 | 150.5 | 56.55 Jul-08 | 191.8 | 89.93 Aug-08 | 177.7 | 15.65 I searched in the web and found some samples all of which draw a sin function or exp functional data. But I need the surface plot for the above data. So, I am not able to figure out. Can anybody tell me an idea to do this. Thanks in advance, Regards, Srinu
Advertisement
I don't have any experience with surface plots but AFAIK you need a function that takes two arguments to plot it as a 3D surface (with the arguments generally representing the X- and Z-Axis).

Your data just resembles a bunch of points, so the most natural way would be to connect them to a line (converting the months to numbers, like Jan = 1). If you need a surface you might draw a quad/two triangles between two adjacent datasets (where each dataset has 2 points - one specified by X,Y,Z and one with one coordinate set to 0), e.g. for Jan and Feb you could use the points:

X/Y/Z
1/120.0/0
1/120.0/25.5
2/125.7/0
2/125.7/24.15

Hope that helps.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
Hi Lord,
Thanks for the response. Your idea sounds like a good one. I am going to implement it to see whether it works. But, I am stuck at converting these coordinates to OpenGL coordinates. Could you please tell me how to do this?

Thanks,
Srinu
I'm not sure where you're stuck, but you could just convert the months to January = 0.0, February = 1.0, March = 2.0 and so on (or use another scale, if you like). Then you alreay have the needed coordinates and just need to call glVertex3f(x,y,z) or - which would be better - put the coordinates into a VBO and render that.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
That`s ok. But OpenGL coords should be between -1 to 1, right? So, these coords must be converted to their equivalent opengl coords.
For example Take a 3d point - 1.0, 120.0, 25.5. We can not render this point in OpenGL window. It must be converted to OpenGL window coords. I am asking how to do this convertion?

Thanks,
Srinu
For a 2 dimensional plot, you could make the vertical axis the Y & Z variables and the horizontal the X (time), then plot the data as vectors instead of points. Or you could do something more interesting, like use the Z data to be the diameter of a circle with the X variables on the horizontal and y be the vertical. Then if you scale the axes properly, you'd have circles of diameter Z centered at height Y and the proper time X which should be spaced not to overlap. Or you could represent one of the fields as color (X makes the most sense, having exact and regular values to easily correspond to a given color). I would look at some differential equation or vector field graphs to see techniques people use for graphic 3 dimensional data in 2 dimensional graphs if thats what you want, or you could make the graph 3D if you really want.
Quote:Original post by srinivaz111
That`s ok. But OpenGL coords should be between -1 to 1, right? So, these coords must be converted to their equivalent opengl coords.
For example Take a 3d point - 1.0, 120.0, 25.5. We can not render this point in OpenGL window. It must be converted to OpenGL window coords. I am asking how to do this convertion?

Thanks,
Srinu


No, you use whatever coordinates you want and OpenGL will internally scale it.
You can use any (reasonable) number for a OpenGL coordinate. However, to get it drawn to screen you have to setup your modelview and projection matrices properly.

If you don't want to do that you'd have to convert the coordinates to range [-1,1] for x and y and to [0,1] for z. This shouldn't be too hard (e.g. if months go from 0 to 11 you can set x to month * (2.0f/11.0f) - 1.0f).

However, I'd recommend using the matrices as they would allow you to use different viewing angles.
If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!
not able to draw the plot using the method where I took 2 points for every coordinate. I got a weird graph. I am following the Contour plot method which involves defining a texture and drawing triangles and setting the texture to those triangles. Can anybody who knows the contour plot method please help me?
I am sending the code also. Please look into it.

This is the actual data for which I have to plot the graph

X-Axis | Y-Axis | Z-Axis
=========================
Jan-08 | 120.0 | 25.5
Feb-08 | 125.7 | 24.15
Mar-08 | 100.0 | 42.11
Apr-08 | 190.0 | 15.62
May-08 | 109.0 | 21.88
Jun-08 | 150.5 | 56.55
Jul-08 | 191.8 | 89.93
Aug-08 | 177.7 | 15.65

So, I have taken the following points table

float data[24][3] =
{
{1.0,120.0,0},
{1.0,120.0,0.5},
{1.0,120.0,25.5},
{2.0,125.7,0},
{2.0,125.7,0.5},
{2.0,125.7,24.15},
{3.0,100.0,0},
{3.0,100.0,0.5},
{3.0,100.0,42.11},
{4.0,190.0,0},
{4.0,190.0,0.5},
{4.0,190.0,15.62},
{5.0,109.0,0},
{5.0,109.0,0.5},
{5.0,109.0,21.88},
{6.0,150.5,0},
{6.0,150.5,0.5},
{6.0,150.5,56.55},
{7.0,191.8,0},
{7.0,191.8,0.5},
{7.0,191.8,89.93},
{8.0,177.7,0},
{8.0,177.7,0.5},
{8.0,177.7,15.65}

};


Here is the code:

void MyGraph::Generate3DData()
{
m_fWidth = 1.0f;
m_fStep = 0.05f;
int nSurface = 1;
int nVertex = nSurface + 1;

v3DVector tempVector;

for (int x=0; x<24; x+=3)
{
double ogl_x, ogl_y, ogl_z;
GetOpenGLCoords(data[x][0], data[x][1], data[x][2], &ogl_x, &ogl_y, &ogl_z);
tempVector.push_back(C3DVector(ogl_x, ogl_y, ogl_z));

GetOpenGLCoords(data[x+1][0], data[x+1][1], data[x+1][2], &ogl_x, &ogl_y, &ogl_z);
tempVector.push_back(C3DVector(ogl_x, ogl_y, ogl_z));

GetOpenGLCoords(data[x+2][0], data[x+2][1], data[x+2][2], &ogl_x, &ogl_y, &ogl_z);
tempVector.push_back(C3DVector(ogl_x, ogl_y, ogl_z));

m_vVertexNormal.push_back(tempVector);

tempVector.clear();
}

tempVector.clear();


/* int size = m_vVertexNormal.size();
std::vector<v3DVector>::iterator it;
for (it=m_vVertexNormal.begin(); it!=m_vVertexNormal.end(); it++)
{
v3DVector tVector = *it;
int vsize = tVector.size();
}
*/

// Surface Normal
for(int nX = 0; nX < 7; nX ++)
{
for(int nY(0); nY < 2; nY ++)
{
C3DVector temp3DVector(0, 0,0);
C3DVector point1 = m_vVertexNormal.at(nX).at(nY);
C3DVector point2 = m_vVertexNormal.at(nX+1).at(nY);
C3DVector point3 = m_vVertexNormal.at(nX+1).at(nY+1);

CalculateNormal(point1, point2, point3, temp3DVector);

tempVector.push_back( temp3DVector );
}
m_vSurfaceNormal.push_back(tempVector);
tempVector.clear();
}

// Vertex Normal
for(nX = 0; nX < 7; nX ++)
for(int nY(0); nY < 2; nY ++)
{
m_vVertexNormal.at(nX).at(nY) += m_vSurfaceNormal.at(nX).at(nY);
m_vVertexNormal.at(nX+1).at(nY) += m_vSurfaceNormal.at(nX).at(nY);
m_vVertexNormal.at(nX).at(nY+1) += m_vSurfaceNormal.at(nX).at(nY);
m_vVertexNormal.at(nX+1).at(nY+1) += m_vSurfaceNormal.at(nX).at(nY);
}
for(nX = 0; nX < 8; nX ++)
for(int nY(0); nY < 3; nY ++)
m_vVertexNormal.at(nX).at(nY).Average();
}

BOOL MyGraph::CalculateNormal(C3DVector& fPoint1, C3DVector& fPoint2, C3DVector& fPoint3, C3DVector& fNormal)
{
float fx = (fPoint2.GetY()-fPoint1.GetY())*(fPoint3.GetZ()-fPoint2.GetZ())-
(fPoint3.GetY()-fPoint2.GetY())*(fPoint2.GetZ()-fPoint1.GetZ());

// (y2-y1)(z3-z2)-(y3-y2)(z2-z1)

float fy = (fPoint3.GetX()-fPoint2.GetX())*(fPoint2.GetZ()-fPoint1.GetZ())-
(fPoint2.GetX()-fPoint1.GetX())*(fPoint3.GetZ()-fPoint2.GetZ());

float fz = (fPoint2.GetX()-fPoint1.GetX())*(fPoint3.GetY()-fPoint2.GetY())-
(fPoint3.GetX()-fPoint2.GetX())*(fPoint2.GetY()-fPoint1.GetY());

float fd = (float) sqrt(fx*fx + fy*fy + fz*fz);

fNormal.SetVector(fx/fd, fy/fd, fz/fd);

return TRUE;
}

void MyGraph::GetOpenGLCoords(float x, float y, float z, double *ogl_x, double *ogl_y, double *ogl_z)
{

*ogl_x = x * (2.0/11.0) - 1.0;
*ogl_y = y * (2.0/191.8) - 1.0;
*ogl_z = z/89.93;
}

void MyGraph::CreateGraph3DList(UINT nList)
{
::glNewList(nList , GL_COMPILE);
for(int x=0, int nX(0); nX < m_vSurfaceNormal.size(); nX++, x+=2)
{
double ogl_x, ogl_y, ogl_z;
GetOpenGLCoords(data[x][0], data[x][1], data[x][2], &ogl_x, &ogl_y, &ogl_z);

float fx = ogl_x; //(nX*m_fStep - 1)*m_fWidth;

::glBegin(GL_TRIANGLE_STRIP);
for(int nY(0); nY < 3/*m_vSurfaceNormal.size()*/; nY++)
{
float fNormal[3];
m_vVertexNormal.at(nX).at(nY).GetVector(fNormal);
::glNormal3fv(fNormal);
float fy = ogl_y;//(nY*m_fStep - 1)*m_fWidth;
float fz = ogl_z;//GetZ(fx, fy);
::glTexCoord1f((fz+1)/2);
::glVertex3d(fx, fy, fz/2);

m_vVertexNormal.at(nX+1).at(nY).GetVector(fNormal);
::glNormal3fv(fNormal);

GetOpenGLCoords(data[x+1][0], data[x+1][1], data[x+1][2], &ogl_x, &ogl_y, &ogl_z);

float fx2 = ogl_x;//fx+m_fStep;
fz = ogl_z;//GetZ(fx2, fy);
::glTexCoord1f((fz+1)/2);
::glVertex3d(fx2, fy, fz/2);
}
::glEnd();
}
::glEndList();
}



Please look into it and show me a way to achieve it.

Thanks in advance,

~Srinu
First, please use the source tags

Quote:Original post by srinivaz111

So, I have taken the following points table

float data[24][3] =
{
{1.0,120.0,0},
{1.0,120.0,0.5},
{1.0,120.0,25.5},
{2.0,125.7,0},
{2.0,125.7,0.5},
{2.0,125.7,24.15},
{3.0,100.0,0},
{3.0,100.0,0.5},
{3.0,100.0,42.11},
{4.0,190.0,0},
{4.0,190.0,0.5},
{4.0,190.0,15.62},
{5.0,109.0,0},
{5.0,109.0,0.5},
{5.0,109.0,21.88},
{6.0,150.5,0},
{6.0,150.5,0.5},
{6.0,150.5,56.55},
{7.0,191.8,0},
{7.0,191.8,0.5},
{7.0,191.8,89.93},
{8.0,177.7,0},
{8.0,177.7,0.5},
{8.0,177.7,15.65}

};

I just skimmed over your code but looking at your data I can make a guess:

You draw the data as a triangle strip, so you get triangles like (in your coords):

{1.0,120.0,0}/{1.0,120.0,0.5}/{1.0,120.0,25.5} -- this basically is a line and wouldn't be rendered (degenerate triangle)
{1.0,120.0,0.5}/{1.0,120.0,25.5}/{2.0,125.7,0}
{1.0,120.0,25.5}/{2.0,125.7,0}/{2.0,125.7,0.5}
{2.0,125.7,0}/{2.0,125.7,0.5}/{2.0,125.7,24.15} -- this is a line, too
...


Why are those {..,..,0.5} point in there? If you remove them, the graph should look better.
If not, I maybe misunderstood you and a screenshot would help me to get a better impression on what your graph looks like.

If I was helpful, feel free to rate me up ;)If I wasn't and you feel to rate me down, please let me know why!

This topic is closed to new replies.

Advertisement