Writing Code for Surface Plots?
MySchizoBuddy asks: "In what ways can you code plots of surface charts using a z(x,y) function or a cloud of points? I'm looking for a tutorial that explains this that doesn't use DirectX or OpenGL libraries (the language I'm using cannot use either framework anyway). How is the 3D mess generated and how can the 2D contour plots be generated as well? I'm assuming once I know that I can also use it to make torus plots as well. Remember, I'm asking for the explanation of the underlying math and an example code that does that. The GNUPlot gallery has some examples that I find helpful, but are there similar examples out there? (Remember, I am writing the plotting code as well)? Can anyone help or point me in the right direction?"
just a thought, but why not use MATLAB. You can sometimes use it to make stand-alone programs and maybe even DLLs. then add it to your code. I help develop code for a Cray X1 and all visualization (for my project) is done locally using MATLAB. It's pretty beefy, but it'll make a contour plot.
887321 = 337*2633
Good 2D contour plotting is not easy (I know!!!).
If you are not afraid of coding, then the best reference that I know of is:
by Albrecht Preusser, ACM TOMS V10#4
The code (in FORTRAN, unfortunately) is also in TOMS as:
Algorithm 626 TRICP: A Contour Plot Program Triangular Meshes
You can get ACM TOMS (Transaction on Mathematical Software) from any reasonable college library.
This might be a bit of overkill, as it is designed for irregular data sets (versus regular datasets - grids). However, the code can be separated into a separate Delaunay Triangulation step. If you have a grid (or in your case, a function f(x,y)), it is easy to generate fixed triangles.
If anybody knows of a better algorithm, I'm all ears!!!
My advice would be to pick up a decent intro book on graphics. The Foley and Van Dam is a classic, but nearly any good book on the topic tends to have a review of the basic math involved in 3d: linear algebra with 3- or 4-value vectors and 3x3 or 4x4 matrices, the perspective divide, etc. Knowing the basics will help you have a lot better idea of what to do. But for anyone curious about the most basic 3d, here's a simple way to do it that should work decently for simple wireframe plots.
" > /> <!-- First line to draw --> /> <!-- Second line to draw --> /> <!-- Third line to draw, etc... -->
1) Take each 3d point of interest and apply some set of rotations around the X, Y, and Z axis to get the view angle right. You'll probably want to just do one rotation around each axis. e.g.:
x2 = x * cos( z_angle ) + y * sin( z_angle );
y2 = x * -sin( z_angle ) + y * cos( z_angle );
x3 = x2 * cos( y_angle ) + z * sin( y_angle );
z2 = x2 * -sin( y_angle ) + z * cos( y_angle );
y3 = y2 * cos( x_angle ) + z2 * sin( x_angle );
z3 = y2 * -sin( x_angle ) + z2 * cos( x_angle );
At this point, you'll have rotated your original coordinate (x,y,z) by some angle around some axis to get (x3,y3,z3)
(To my fellow graphics geeks: yes, yes, I know full well that matrices and quaternions are better -- I'm trying keep this simple.)
2) Maybe add some distance to the z value, to move ("translate") it away from the "camera" at the origin. You'll need to add enough to make sure that all of your z-values are positive and non-zero before step 3:
z4 = z3 + z_translate
3) Do what's called the "perspective divide" to find the two dimensional coordinate of this point. e.g.:
px = x3 / z4 * scale + center_x;
py = y3 / z4 * scale + center_y;
4) Either plot a point at the (px,py) that you just got, or compute steps 1 and 2 twice for the end points of lines and then use your system's graphics primitives to draw lines between (px1,py1) and (px2,py2). If you're not using a language or a library that can do simple 2d graphics, then I'd suggest writing out a file with the lines in SVG format (and then rasterize to bitmap with a program like Batik, Inkscape, Illustrator, etc.) e.g.:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd
<svg width="4cm" height="4cm" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" version="1.1">
<path d="M px1 py1 L px2 py2" fill="none" stroke="black" stroke-width="1"
<path d="M px1 py1 L px2 py2" fill="none" stroke="black" stroke-width="1"
<path d="M px1 py1 L px2 py2" fill="none" stroke="black" stroke-width="1"
</svg>
5) If you want more than wireframe, things will be a lot more complicated. At the very least, you'll need to be able to fill polygons and sort back to front by the z-value after the rotation so that everything gets drawn in the correct order. Z-buffers would be even better.
Well, I hope all that helps. Again, if anyone's really interested, I'd suggest getting a real book on the topic. But I hope this's enough to get the curious started.
Hate to disappoint you, but you're probably not going to find a tutorial and code that conveniently meets your requirements. For starters, eliminating OpenGL and D3D is going to remove a large number of tutorials, simply because it doesn't make sense for most people to roll their own rendering code.
Your best bet would be to look through "Computer Graphics: Principles and Practice" by Foley, van Dam, Feiner and Hughes. It covers a large number of topics, in enough detail to get a good idea of how to get started and where to look for more information. Also "Real-Time Rendering" by Tomas Möller and Eric Haines. Despite the name, a large portion of the book is applicable to almost all computer graphics, not just real-time. Also, a book on linear algebra would probably be helpful.
Maybe not