Slashdot Mirror


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?"

18 of 81 comments (clear)

  1. first plot by McGiraf · · Score: 2, Funny

    first plot

    hum ...

  2. Another view by Knights+who+say+'INT · · Score: 3, Interesting

    You could plot graphics that represent levels as colours. I think I invented a kind of R^2->R function plot that represents a Z value as the degree of grey (0 being black, 255 being white) corresponding to Z mod 255. The result is that the more frequent "cuts" (sudden changes from white to black) are, the highest is the derivative.

    Looky here, here and here.

  3. You sure you want to do the math? by perlionex · · Score: 3, Informative

    I looked at 3D rendering quite a while back (about 15 years ago). Believe me -- you probably don't really want to built this up from scratch.

    It sounds like you just need some sample code that doesn't rely on OpenGL or DirectX. To that end, the following (open-source) projects may be useful:

  4. MATLAB by Bob_Geldof · · Score: 4, Interesting

    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
  5. 2D contouring by jmac880n · · Score: 4, Informative

    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:

    • Computing Contours by Successive Solution of Quintic Polynomial Equations
      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!!!

    1. Re:2D contouring by jmac880n · · Score: 2, Informative

      Pardon me, I'd like to make a correction. Good 2D contour plotting from scattered point data is not easy. For contour plotting from a regular grid, the marching squares algorithm is simple, easy to implement, and works pretty well. Run it several times with different reference values to get all the contours you want.

      Uhhh... I said good 2D contouring is hard. Marching squares is by NO stretch of the imagination good, even with regular data. Easy, yes. Good, no.

      It has discontinuities. Good contouring will have smoothness at least to the 2nd derivative. TRICP uses fifth order equations to fit the derivatives on all sides of the triangulation so that the resulting curves are smooth at all points. As I pointed out, triangulation is trivial with regular gridded data.

      And subsampling using cubic interpolation will not help the discontinuities that appear with marching squares. Unless you use an algorithm that fits the derivatives at the region boundaries, you will get noticable jagged lines.

  6. Why not OpenGL? by SanityInAnarchy · · Score: 2, Interesting

    I know this doesn't help you, but I'm still curious -- under what circumstances can you not use OpenGL for this? Under what circumstances would it be easier to implement it yourself than to find/create a decent GL binding? Or maybe you could just read the software implementation from Mesa?

    --
    Don't thank God, thank a doctor!
  7. R-project by Anonymous Coward · · Score: 3, Insightful

    Check out the R-project at www.r-project.org. It is very good for that sort of thing.

    1. Re:R-project by infolib · · Score: 2, Informative

      I'm out of mod points, but this is insightful. The R programming language is GPL'ed and works on lin/win/osx (packages for major distros). It is an interpreted language (except for a few internal commands), and so the source code for the several different 3D plotters is included with the program. Some you might have to install yourself, but this can be done by the install.packages command.

      You might want to have a quick look at output from different 3D commands (persp, scatterplot3d and wireframe).

      The introductory documentation might be a bit confusing - especially since it's often written for and by statisticians, but there's a mailinglist with a huge googleable archive and I've often found that "google:r-project search term" will get me what I need.

      --
      Any sufficiently advanced libertarian utopia is indistinguishable from government.
  8. Basic Rundown by The+boojum · · Score: 4, Informative

    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.

    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" /> <!-- First line to draw -->
        <path d="M px1 py1 L px2 py2" fill="none" stroke="black" stroke-width="1" /> <!-- Second line to draw -->
        <path d="M px1 py1 L px2 py2" fill="none" stroke="black" stroke-width="1" /> <!-- Third line to draw, etc... -->
    </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.

    1. Re:Basic Rundown by Profane+MuthaFucka · · Score: 4, Interesting

      Regarding point #2 and #3, if he's just plotting points to make a graph, fancy perspective may not be needed. Just throw away the Z coordinate after rotation, and plot the X and Y in 2D.

      Also, if you're rotating the graph in real-time, don't rotate the points a degree, plot, and rotate another degree and plot, and so on.

      Save the original set of points. Rotate them one degree and plot. Throw those results away, start with the original set and rotate them two degrees and plot. Repeat, rotating only the original set each time. You'll save a lot of trouble from accumulating floating point errors.

      --
      Fascism trolls keeping me up every night. When I starts a preachin', he HITS ME WITH HIS REICH!
  9. If you're willing to have a wire-frame look... by Jamey · · Score: 2, Interesting

    dim ymax(screenwidth),ymin(screenwidth)
    For xtemp = xlower to xupper step xincr
    for ytemp = ylower to yupper step yincr
    compute z=f(xtemp,ytemp)
    (x,y)=transform(xtemp,ytemp,z)
    if yymax(x) then plot x,y : ymax(x) = y
    next ytemp, xtemp

    Adjust your viewpoint for your 3D to 2D matrix so it plots from front to back.

    Algorithm comes from an old book on doing 3D on an Apple ][ - it wasn't too hard to convert it to work on a TRS-80 Model I or a CoCo.

  10. Shouldn't be too tough... by ClassMyAss · · Score: 2, Informative

    I just looked at the GNUPlot page, and regardless of what anyone else says, I don't think it should be too difficult to code at all, at least the grid stuff like near the top of that page. The reason - it's all drawn without perspective, which means a little vector math tells you where to put each point. You might be a bit foolish to try to hand-code something substantial with perspective, but orthogonal projections are straightforward.

    Here's what you need to do. First, figure out what a unit in the X, Y, and Z axes corresponds to in screen coordinates. In the examples on the GNUPlot page, I'd estimate that a unit in the X direction is about 10 pixels to the right and 2 pixels down in screen coordinates, or (10, -2). Similarly, a unit in the Y direction is about (3, 3), and a unit in the Z direction is (0, 1). Now, to find the screen location of a point given in 3D, say (x,y,z), we start at the screen coordinate of the origin (wherever you want to put (0,0,0)). To this, we add x times the vector (10, -2), y times the vector (3, 3), and z times the vector (0, 1). For example, the point (10, 3, 6), with an origin at (100, 100), would show up at (100, 100) + (100, -20) + (9, 9) + (0, 6) = (209, 95).

    In other words, if we call the unit vectors in the X, Y and Z directions (given in screen coordinates) Xhat, Yhat, and Zhat, then the point (x,y,z) should be plotted at (origin + x*Xhat+y*Yhat+z*Zhat).

    I presume that from here you should be able to figure out how to draw the grid lines - just sample a bunch of points, and draw straight lines between neighbors. If you want to fill in the tiles (like the pictures near the bottom of the GNUPlot page), you'll need to be clever about the order you fill them in so that the ones in front are filled last. For this, you can sort the tiles by the appropriate combination of x and y coordinates (in "real" space, not screen space) - in our example, Xhat - 3.333Yhat points straight down, so you would sort by the combination x - 3.333y and draw in that order.

    This should at least get you on your way. I'm sure there are subtleties to consider, but hey - it's your project, not mine, so I'll leave it at that!

  11. Read a book by jlarocco · · Score: 4, Informative

    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.

    1. Re:Read a book by sglow · · Score: 2, Informative

      Here's the best book on the subject that I've come across.

      Mathematical Elements for Computer Graphics
      http://www.nar-associates.com/nar-publishing/mecg2 nd.htm

  12. See what you can come up with by Geccie · · Score: 2, Insightful

    If its a very small part of a larger program, then look for some good examples and try to trudge through getting it to work. Otherwise, start writing code and examine the visual output of the screen. Look for algorithms and methods for producing the output you want. When you begin to understand them, you can integrate the concepts into your solution.

    Unfortunately, even if you have an API, you still have to understand what it does and how to interact with it. Many people believe that modular programming simply means using code alrealy written. This is a false premise as there is no substitute for some degree of understanding.

    In the end, you may wish to use a public library because it is highly accurate, optimized, well researched, or portable, but by that time you will have the knowledge to understand why you are selecting the particular library.

  13. Marching cubes by Hillman · · Score: 2, Informative

    You can use the marching cubes algorithm. You can go from a cloud of points to a 3d object that you can transform like you want. I think they use that in MRI imaging. I used the 2d version (marching squares) to optimize a metablob routine a long time ago.

    see: http://www.exaflop.org/docs/marchcubes/index.html

  14. Generic Mapping Tool by budgenator · · Score: 2, Interesting

    Generic Mapping Tool, will do everything you want, and a lot you have not even thought of yet. GMT produces postscript and encapsuleated postscript, so if you have a postscript viewer your good to go, runs on unix/linux, is GPL'd so there source code to analyse. There are lots of examples with generating scripts such as time-series collected along a track or a 3D perspective, artificialy illuminated, greyscale image; just reading and understanding the accompanying ducumentation should be good for college credit in cartography.

    --
    Apocalypse Cancelled, Sorry, No Ticket Refunds