Example 3

This example uses the same code to read the data file as in Example 2.  However, in Example 3, a 3D surface is plotted instead of a 2D image, plus axes are drawn on the margins of the surface.  Certain portions of the code in Example 2 have been deleted if it was not necessary to produce the surface.  A function for normalizing the scale of the surface is  located at the top of the file.

IMPORTANT:  Click here to learn how to reduce the size of your VRML file.  This example produces a VRML file 12.4 MB in size using the original array of 300 x 300, but though various reduction techniques, the file can be reduced to 266 KB.

Depending on the PlugIn that you use with your browser, you may need to turn the "headlight" on (if the headlight is off, you'll see axes, but no surface). Using Cosmoplayer on an SGI, you do this by clicking the right mouse button to call a pop-up menu.  While using the pop-up menu, you might find it more user friendly to click on "Examiner" as the Viewer.  With MS Windows, you may need to open the "preferences" and turn on the headlight by clicking on a small button in the lower right of your screen that has a checkmark on it.  Go to headlight on + examiner to see how to fix your .wrl file to default to these settings.

; The first line of the output file (``image'') is three integers

; Nx   Ny   Nz

; being respectively the number of values of x, the number
; of values of y, and the number of dependent variables
;(in this example, nz = 2, corresponding to the density
; and phase of a quantum mechanical wavefunction).  Then
; follow Nx * Ny lines, each of the form

; ix   iy   z_1  z_2  . . . z_{Nz}

; where ix and iy are the integer indices of the x and
; y coordinates, and z_i the values of the dependent variables.
; In our application the x and y values will always be
; equally spaced.

;--------------------------------------------------------------
FUNCTION NORM_COORD, range

; This function takes a range vector [min, max] as contained
; in the [XYZ]RANGE property of an object and converts it to
; a scaling vector (suitable for the [XYZ]COORD_CONV property)
; that scales the object to fit in the range [0,1].

scale = [-range[0]/(range[1]-range[0]), 1/(range[1]-range[0])]

RETURN, scale

END
;--------------------------------------------------------------

Pro surf
file1 = 'image'
openr,1,file1
i1 = 1
i2 = 1
i3 = 1
i4 = 1
i5 = 1
i6 = 1
r1 = 1.0
r2 = 1.0
r3 = 1.0
r4 = 1.0
data = fltarr(i1,i2,i3)

for j = 0,i1 -1 do begin
for k = 0,i2 -1 do begin

data(j,k,0) = r1
data(j,k,1) = r2

endfor
endfor

close,1

; dat0 is all the rows in the 1st column of data and
; dat1 is all the rows in the 2nd column of data
dat0 = data(*,*,0)
dat1 = data(*,*,1)

; The following two lines change the arrays from a single array as found in
; the data file as a single column of data to an array of specified dimensions.
; The "rebin" function interpolates the data discarding as much as is necessary
; to produce an array of the specified dimensions.  The original data formed a
; 300 x 300 array.  Thus the data file is decimated to 1/9th the original size.
; The size used must be the result of the original array divided by an integer.
test0=rebin(dat0, 100,100)
test1=rebin(dat1, 100,100)

;----------------------------------------------------------------------------
; Create object to be saved as vrml, .wrl file

; Create the palette to be used to color the surface
; Load the palette into a texture image for the surface
mypalette=OBJ_NEW('IDLgrPalette')
mypalette->LOADCT, 4  ;color table 4 is green-blue-red-yellow
mytextureimage=OBJ_NEW('IDLgrImage',BYTSCL(dat0), PALETTE=mypalette)

; Create the surface object.  Use the array dat1.  Style 2 is "filled",
; ie. solid. Other choices are 0=points, 1=wire mesh, 3= ruled XZ, etc.
; Apply the textureimage created above.
mysurface = OBJ_NEW('IDLgrSurface', dat0, Style=2, \$
texture_map=mytextureimage)

; Get the range of each axis
mysurface->GetProperty, XRANGE = xr, YRANGE = yr, ZRANGE = zr

; Normalize the coordinates of the axes by calling the function at the
; start of this file.  Normalization is required for this data set because
; the values for the z axis are so much smaller than the number of elements
; in the x and z axes.
mysurface->SetProperty, XCOORD_CONV = NORM_COORD(xr), \$
YCOORD_CONV = NORM_COORD(yr), ZCOORD_CONV = NORM_COORD(zr)

; Create the axis objects.  The 0, 1, and 2 are the convention used by IDL
; for the x, y, and z axes, respectively.  The color is red.  The range is
; gotten from the data, and the values must be normalized to correspond with
; the surface
xaxis = OBJ_NEW('IDLgrAxis', 0, COLOR=[255,0,0], RANGE=xr, \$
XCOORD_CONV = NORM_COORD(xr))
yaxis = OBJ_NEW('IDLgrAxis', 1, COLOR=[255,0,0], RANGE=yr, \$
YCOORD_CONV = NORM_COORD(yr))
zaxis = OBJ_NEW('IDLgrAxis', 2, COLOR=[255,0,0], RANGE=zr, \$
ZCOORD_CONV = NORM_COORD(zr))

; The tick lengths are set to 2% of the normalized size of the graph
xaxis->SetProperty, TICKLEN=0.02
yaxis->SetProperty, TICKLEN=0.02
zaxis->SetProperty, TICKLEN=0.02

; The "container" objects are created.  The background color of the view
; is set to black.
myvrml = OBJ_NEW('IDLgrVRML')
myview = OBJ_NEW('IDLgrView', color=0)
mymodel = OBJ_NEW('IDLgrModel')

myvrml->SetProperty, filename='vrml_0_100x100.wrl'

SET_VIEW, myview, myvrml

myvrml->Draw, myview

; Destroying the top level object destroys all that are contained within.
obj_destroy,myvrml

end

How to set the file to default to Headlight on and use Examiner:

After IDL has created the .wrl file, you can open the file in a text editor and make a couple small changes that may assist the viewer.  Near the bottom of the file there will be a statement: