Thursday, February 21, 2013

Rotatable 3D surface plot

Yesterday a customer asked me how to create a quick and dirty solution for displaying a rotatable three dimensional surface (using ChartPack). Here's the solution to it (for sake of clarity I use predefined data stored in the 12 by 14 array "Data"):
  1. Put the TPlot3D component on a form
  2. In the OnShow event add the following code:
        // suppress any redraw during the
        // construction of the plot
    P3d.SuppressPaint := true; 
        // adjust the data grid of the component 
    P3d.GridMat.Resize(14,12);  
        // fill the data grid
    for i:=1 to 14 do
      for j:=1 to 12 do
        P3d.GridMat[i,j] := Data[i,j];  
        // set the scales of the axes
    P3D.SetRange(1,14,1,12,0,35);  
        // this triggers a repaint
    P3d.SuppressPaint := false;    
    
  3. In the object inspector set the color model ("ColorCodingMode") to "cmThreeColors", the range of colors to a range of 0 to 35 (properties "ColorScaleLow" and "ColorScaleHigh"), and of course, the pivot colors ("ColorLow", "ColorMid", and "ColorHigh") according to your requirements.
As a small refinement I added a scrollbar which allows to adjust the property "ColorScaleHigh". Following is a screen shot of the mini demo:

You can download the sample program written for Delphi XE3 from here. The ZIP file contains the sources and the corresponding executable for Windows. In order to rotate the 3D plot simply click into the chart and drag the mouse holding the left mouse button down.

2 comments:

  1. If you could write a sentence or two how to allow "holes" in the mesh, that would be great too.

    Also it seems that the default is that on the edges the surface goes to the bottom, but I would rather have it stop in "mid air" so to speak. I guess it is just a special kind of "hole".

    ReplyDelete
  2. It's easy to add holes: simply use the "OnBeforeRenderPolygon" event to decide whether to render the polygon or not (set "Handled" to TRUE in order to create a hole at the particular location).

    There's a nice sample application on the SDL Web site which shows how to program a surface with a hole:

    http://www.lohninger.com/examples_part2.html

    (look for the program "plot3dhole" on this page).

    Regarding the edges: they are in no way connected to the bottom. It solely depends on the range of z-scale where the boundary of the surface appears (use, for example, "P3D.SetRange(1,14,1,12,-30,35);" in the sample code above, and the surface will appear "mid air").

    ReplyDelete