AVPRG Home / Members / Akira Kageyama / VFIVE / manual

VFIVE User's Manual

Change log


What is VFIVE?

VFIVE (Vector Field Interactive Visualization Environment) is a general purpose visualization software to analyze 3-D data for CAVE VR systems. The main purpose of this software is to analyze 3-D vector fields with complex structures in 3-D space provided by the CAVE system. We have incorporated various visualization modules, which take advantage of CAVE's immersivity and interactivity, in VFIVE. User can change visualization methods by MENU function intuitively and easily. VFIVE can display curves and surfaces specified by user in advance with visualized objects such as isosurface and stream lines. This function is useful when user wants to display, for example, borderlines simultaneously

VFIVE is originally for visualizing the results of computer simulations, however, it can visualize other kind of data such as results of experiments.

Data

VFIVE can visualize 3-D rectangular data in Cartesian coordinate (x,y,z). It is not necessary for the grid spacing to be uniform.

The data required by VFIVE are as follows. The format of each data is described later.

     
  1. [required] Coordinate data (a series of x,y,z values of each axis)
  2.  
  3. [required] Vector data (at least one vector field must be inputted.)
  4.  
  5. [required] Scalar data (at least one scalar field must be inputted.)
  6.  
  7. [optional] Curves data (user can display curves.)
  8.  
  9. [optional] Surfaces data (user can display surfaces.)

User must prepare a text file specifying the names of coordinate data files, and the names of vector and scalar data files. Following is an example of the text file for visualizing two vector data and two scalar data by VFIVE. (The file extension is not needed to be 'v5'.)


+------------------------------------------------------------------+
|                    Beginning of input file                    

% cat test.v5

# test.v5    (The line beginning by '#' is a comment line.)
#
# "Keyword"   some space  "value"
# 
n1          60
n2         70
n3          80
nvec        2
nscal       2
scale       1.0
shift_x     0.0
shift_y     0.0
shift_z     0.0
xfile       /home/guest/test/test-coord.x
yfile       /home/guest/test/test-coord.y
zfile       /home/guest/test/test-coord.z
vect0_label MAGNETIC\nField
vect0x      /home/guest/test/test-magnetic.x
vect0y      /home/guest/test/test-magnetic.y
vect0z      /home/guest/test/test-magnetic.z
vect1_label VELOCITY\nField
vect1x      /home/guest/test/test-velocity.x
vect1y      /home/guest/test/test-velocity.y
vect1z      /home/guest/test/test-velocity.z
scal0_label PRESSURE
scal0       /home/guest/test/test-pressure
scal1_label DENSITY
scal1       /home/guest/test/test-density

|                    end of input file                    
+------------------------------------------------------------------+

which means,


+------------------------------------------------------------------+
|           beginning of input file with comments               

# test.v5    (The line beginning by '#' is a comment line.)
#
# ... the number of grids in x-direction
n1         60
# ... the number of grids in y-direction
n2         70
# ... the number of grids in z-direction
n3         80
# ... the number of vector fields
nvec       2
# ... the number of scalar fields
nscal      2
# ... factor of scale (coordinates specified by coordinates data are magnified by this parameter. 
#     after magnification, the values of the coordinates are regarded as in "meter".)
scale     1.0
# ... distance of parallel translation in x-direction (the origin is translated in x-direction before the magnification.)
shift_x   0.0
# ... for y-direction
shift_y   0.0
shift_z   0.0
# ... x-coordinate file
xfile      /home/guest/test/test-coord.x
# ... y-cooridnate file
yfile      /home/guest/test/test-coord.y
# ... z-coodinate file
zfile      /home/guest/test/test-coord.z
# ... the name of the 1st vector field(the name appears in the menu panel.). '\n' means 'new line'.
vect0_label MAGNETIC\nField
# ... data file of the x element of the 1st vector field.
vect0x     /home/guest/test/test-magnetic.x
# ... data file of the y element of the 1st vector field.
vect0y     /home/guest/test/test-magnetic.y
# ... data file of the z element of the 1st vector field.
vect0z     /home/guest/test/test-magnetic.z
# ... the name of the 2nd vector field.
vect1_label VELOCITY\nField
# ... data file of the x element of the 2nd vector field.
vect1x     /home/guest/test/test-velocity.x
# ... data file of the y element of the 2nd vector field.
vect1y     /home/guest/test/test-velocity.y
# ... data file of the z element of the 2nd vector field.
vect1z     /home/guest/test/test-velocity.z
# ... the name of the 1st scalar field.
scal0_label PRESSURE
# ... data file of the 1st scalar field.
scal0      /home/guest/test/test-pressure
# ... the name of the 2nd scalar field.
scal1_label DENSITY
# ... data file of the 2nd scalar field.
scal1      /home/guest/test/test-density
# --

|           end of input file with comments               
+------------------------------------------------------------------+

Coordinate data

Coordinate data for VFIVE (in "test.v5" they are /home/guest/test/test-coord.x and .....) must be

  1. Fortran's unformatted output (VFIVE skips the first 4 bytes)
  2. real number of double precision (double in C/C++ language)

Sample program to make them is as follows.

+------------------------------------------------------+     
| Beginning of program (Fortran) 

      implicit none
      integer nx, ny, nz
      parameter(nx=60,ny=70,nz=80)
      integer i, j, k
      real*8 xpos(nx), ypos(ny), zpos(nz)
      character*50 xfile, yfile, zfile
c
      xfile = "/home/guest/test/test-coord.x"
      yfile = "/home/guest/test/test-coord.y"
      zfile = "/home/guest/test/test-coord.z"
c
      do i = 1 , nx
        xpos(i) = definition of x-coordinate
      end do
c     (spacing is not needed to be uniform)
c
      do j = 1 , ny
        ypos(j) = definition of y-coordinate
      end do
c
      do k = 1 , nz
        zpos(k) = definition of z-coordinate
      end do
c
      open(11,file=xfile,form='unformatted')
      open(12,file=yfile,form='unformatted')
      open(13,file=zfile,form='unformatted')
        write(11) xpos
        write(12) ypos
        write(13) zpos
      close(13)
      close(12)
      close(11)
c
      stop
      end

| end of program (Fortran)
+------------------------------------------------------+
+----------------------------------------------------+
| beginning of program (C language) 

#include <stdio.h>
#include <stdlib.h>

const int nx = 60;
const int ny = 70;
const int nz = 80;

int
main(int argc, char **argv)
{
      int i, j, k;
      double xpos[nx], ypos[ny], zpos[nz];
      char dummy[4];
      FILE *fp;

      char xfile[] = "/home/guest/test/test-coord.x";
      char yfile[] = "/home/guest/test/test-coord.y";
      char zfile[] = "/home/guest/test/test-coord.z";

      for(i = 0; i < nx ; i++){
        xpos[i] = definition of x-coodinate;
	/* spacing is not needed to be uniform */
      }

      for(j = 0; j < ny; j++){
        ypos[j] = definition of y-coodinate;
      }

      for(k = 0; k < nz; k++){
        zpos[k] = definition of z-coodinate;
      }

      if((fp=fopen(xfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(xpos, sizeof(double), nx, fp);
      fclose(fp);

      if((fp=fopen(yfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(ypos, sizeof(double), ny, fp);
      fclose(fp);

      if((fp=fopen(zfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(zpos, sizeof(double), nz, fp);
      fclose(fp);

   return 0;

}

| end of program (C language)
+----------------------------------------------------+

Data of vector and scalar data

As well as the coordinate data, the vector and scalar data must be

  1. Fortran's unformatted output
  2. real number of double precision

Sample program to make them is as follows

+--------------------------------------------------------+     
| beginning of program (Fortran)   

   implicit none
   integer nx, ny, nz
   parameter(nx=60,ny=70,nz=80)
   integer i,j,k
   real*8 xmag(nx,ny,nz), ymag(nx,ny,nz), zmag(nx,ny,nz)
   real*8 xvel(nx,ny,nz), yvel(nx,ny,nz), zvel(nx,ny,nz)
   real*8 pres(nx,ny,nz), dens(nx,ny,nz)

   character*50 xmfile, ymfile, zmfile
   character*50 xvfile, yvfile, zvfile
   character*50 psfile, dnfile
c
   xmfile = "/home/guest/test/test-magnetic.x"
   ymfile = "/home/guest/test/test-magnetic.y"
   zmfile = "/home/guest/test/test-magnetic.z"
   xvfile = "/home/guest/test/test-velocity.x"
   yvfile = "/home/guest/test/test-velocity.y"
   zvfile = "/home/guest/test/test-velocity.z"
   psfile = "/home/guest/test/test-pressure.z"
   dnfile = "/home/guest/test/test-density.z"
c
   do k = 1 , nz
     do j = 1 , ny
       do i = 1 , nx
         xmag(i,j,k) = definition of x element of magnetic field
         ymag(i,j,k) = definition of y element of magnetic field
         zmag(i,j,k) = definition of z element of magnetic field
         xvel(i,j,k) = definition of x element of velocity
         yvel(i,j,k) = definition of y element of velocity
         zvel(i,j,k) = definition of z element of velocity
         pres(i,j,k) = definition of pressure
         dens(i,j,k) = definition of density
       end do
     end do
   end do
c
   open(11,file=xmfile,form='unformatted')
   open(12,file=ymfile,form='unformatted')
   open(13,file=zmfile,form='unformatted')
   open(21,file=xvfile,form='unformatted')
   open(22,file=yvfile,form='unformatted')
   open(23,file=zvfile,form='unformatted')
   open(31,file=psfile,form='unformatted')
   open(32,file=dnfile,form='unformatted')
     write(11) xmag
     write(12) ymag
     write(13) zmag
     write(21) xvel
     write(22) yvel
     write(23) zvel
     write(31) pres
     write(32) dens
   close(32)
   close(31)
   close(23)
   close(22)
   close(21)
   close(13)
   close(12)
   close(11)
c
   stop
   end

| end of program (Fortran)
+--------------------------------------------------------+
+--------------------------------------------------------+
| beginning of parogram (C language)

#include <stdio.h>
#include <stdlib.h>

const int nx = 60;
const int ny = 70;
const int nz = 80;

int
main(int argc, char **argv)
{
   int i,j,k;
   double xmag[nz][ny][nx], ymag[nz][ny][nx], zmag[nz][ny][nx];
   double xvel[nz][ny][nx], yvel[nz][ny][nx], zvel[nz][ny][nx];
   double pres[nz][ny][nx], dens[nz][ny][nx];

   char dummy[4];
   FILE *fp;

   char xmfile[] = "/home/guest/test/test-magnetic.x";
   char ymfile[] = "/home/guest/test/test-magnetic.y";
   char zmfile[] = "/home/guest/test/test-magnetic.z";
   char xvfile[] = "/home/guest/test/test-velocity.x";
   char yvfile[] = "/home/guest/test/test-velocity.y";
   char zvfile[] = "/home/guest/test/test-velocity.z";
   char psfile[] = "/home/guest/test/test-pressure.z";
   char dnfile[] = "/home/guest/test/test-density.z";

   for(k = 0; k < nz; k++){
     for(j = 0; j< ny; j++){
       for(i = 0; i < nx; i++){
         xmag[k][j][i] = definition of x element of magnetic field;
         ymag[k][j][i] = definition of y element of magnetic field;
         zmag[k][j][i] = definition of z element of magnetic field;
         xvel[k][j][i] = definition of x element of velocity field;
         yvel[k][j][i] = definition of y element of velocity field;
         zvel[k][j][i] = definition of z element of magnetic field;
         pres[k][j][i] = definition of pressure;
         dens[k][j][i] = definition of density;
       }
     }
   }

   if((fp=fopen(xmfile,"wb")) == NULL){
     fputs("Error\n",stderr);
     exit(1);
   }
    fwrite(dummy, 1, 4, fp);
    fwrite(xmag, sizeof(double), nx * ny * nz, fp);
   fclose(fp);

   .........(some lines were omitted).........

  return 0;
}

| end of program (C  language)
+--------------------------------------------------------+

Single precision data

Multi-threaded version of VFIVE can handle single precision data too. If your data is single precision, you need to change the lines 56 and 57 of vfive.h as follows,

typedef float ffloat_
//typedef double ffloat_

and compile VFIVE again. You need to prepare single precision coordinate data.

Time Developing data (Animation Function)

Ver.3.72a of VFIVE(multi thread version) can handle time-developing data. When usign function of animation, input file is as follows,
+----------------------------
n1        256
n2        128
n3        128
ntime       5
nvec        1
nscal       2
scale        1.000
shift_x     -6.500
shift_y     -3.000
shift_z     -3.000
xfile   /home/guest/data/coord_x.dat
yfile   /home/guest/data/coord_y.dat
zfile   /home/guest/data/coord_z.dat

vect0_label  vel
vect0xt0  /home/guest/data/velx200.dat
vect0yt0  /home/guest/data/vely200.dat
vect0zt0  /home/guest/data/velz200.dat

vect0xt1  /home/guest/data/velx205.dat
vect0yt1  /home/guest/data/vely205.dat
vect0zt1  /home/guest/data/velz205.dat

vect0xt2  /home/guest/data/velx210.dat
vect0yt2  /home/guest/data/vely210.dat
vect0zt2  /home/guest/data/velz210.dat

vect0xt3  /home/guest/data/velx215.dat
vect0yt3  /home/guest/data/vely215.dat
vect0zt3  /home/guest/data/velz215.dat

vect0xt4  /home/guest/data/velx220.dat
vect0yt4  /home/guest/data/vely220.dat
vect0zt4  /home/guest/data/velz220.dat



vectmax0  0.06
vectmin0  0.0


scal0_label pressure
scal0t0   /home/guest/data/pre200.dat
scal0t1   /home/guest/data/pre205.dat
scal0t2   /home/guest/data/pre210.dat
scal0t3   /home/guest/data/pre215.dat
scal0t4   /home/guest/data/pre220.dat



scalmax0 -11.0
scalmin0 -20.0


scal1_label density
scal1t0   /home/guest/data/den200.dat
scal1t1   /home/guest/data/den205.dat
scal1t2   /home/guest/data/den210.dat
scal1t3   /home/guest/data/den215.dat
scal1t4   /home/guest/data/den220.dat



scalmax1 -5.0
scalmin1 -16.0

+----------------------------
which means
+----------------------------
n1        256
n2        128
n3        128
ntime       5
# number of time step
nvec        1
nscal       2
scale        1.000
shift_x     -6.500
shift_y     -3.000
shift_z     -3.000
xfile   /home/guest/data/coord_x.dat
yfile   /home/guest/data/coord_y.dat
zfile   /home/guest/data/coord_z.dat

vect0_label  vel

vect0xt0  /home/guest/data/velx200.dat
# ... data file of x-element of the 0th vector field of the 0th time
vect0yt0  /home/guest/data/vely200.dat
# ... data file of y-element of the 0th vector field of the 0th time
vect0zt0  /home/guest/data/velz200.dat
# ... data file of z-element of the 0th vector field of the 0th time

vect0xt1  /home/guest/data/velx205.dat
# ... data file of x-element of the 0th vector field of the 1st time
vect0yt1  /home/guest/data/vely205.dat
# ... data file of y-element of the 0th vector field of the 1st time
vect0zt1  /home/guest/data/velz205.dat
# ... data file of z-element of the 0th vector field of the 1st time

vect0xt2  /home/guest/data/velx210.dat
# ... data file of x-element of the 0th vector field of the 2nd time
vect0yt2  /home/guest/data/vely210.dat
# ... data file of y-element of the 0th vector field of the 2nd time
vect0zt2  /home/guest/data/velz210.dat
# ... data file of z-element of the 0th vector field of the 2nd time

vect0xt3  /home/guest/data/velx215.dat
# ... data file of x-element of the 0th vector field of the 3rd time
vect0yt3  /home/guest/data/vely215.dat
# ... data file of y-element of the 0th vector field of the 3rd time
vect0zt3  /home/guest/data/velz215.dat
# ... data file of z-element of the 0th vector field of the 3rd time

vect0xt4  /home/guest/data/velx220.dat
# ... data file of x-element of the 0th vector field of the 4th time
vect0yt4  /home/guest/data/vely220.dat
# ... data file of y-element of the 0th vector field of the 4th time
vect0zt4  /home/guest/data/velz220.dat
# ... data file of z-element of the 0th vector field of the 4th time



vectmax0  0.06
#max magnitude of 0th vector 
vectmin0  0.0
#min magnitude of 0th vector 


scal0_label pressure

scal0t0   /home/guest/data/pre200.dat
# ... data file of the 0th scalar field of the 0th time
scal0t1   /home/guest/data/pre205.dat
# ... data file of the 0th scalar field of the 1st time
scal0t2   /home/guest/data/pre210.dat
# ... data file of the 0th scalar field of the 2nd time
scal0t3   /home/guest/data/pre215.dat
# ... data file of the 0th scalar field of the 3rd time
scal0t4   /home/guest/data/pre220.dat
# ... data file of the 0th scalar field of the 4th time




scalmax0 -11.0
#max value of the 0th scalar field
scalmin0 -20.0
#min value of the 0th scalar field


scal1_label density

scal1t0   /home/guest/data/den200.dat
# ... data file of the 1st scalar field of the 0th time
scal1t1   /home/guest/data/den205.dat
# ... data file of the 1st scalar field of the 1st time
scal1t2   /home/guest/data/den210.dat
# ... data file of the 1st scalar field of the 2nd time
scal1t3   /home/guest/data/den215.dat
# ... data file of the 1st scalar field of the 3rd time
scal1t4   /home/guest/data/den220.dat
# ... data file of the 1st scalar field of the 4th time



scalmax1 -5.0
#max value of the 1st scalar field
scalmin1 -16.0
#min value of the 1st scalar field

+----------------------------

Running VFIVE

The command is "vfive". For example, you can run VFIVE by typing

% vfive test.v5
When your OS is Windows, you may type those words on 'Command Prompt'

Option

There are two options.

  1. Curves specified by user (-l 'the file name')
  2. Surfaces specified by user (-s 'the file name')

Example 1: Displaying curves

% vfive test.v5 -l test-lines.v5

Example 2: Displaying surfaces

% vfive test.v5 -s test-surfaces.v5

Example 3: Displaying curves and surfaces

% vfive test.v5 -l test-lines.v5 -s test-surfaces.v5

How to make the data of curves and surfaces is described later.

After starting VFIVE

A rectangular box composed of 12 line segments, which indicates the border of data, appears in your CAVE. The red line segments are parallel to x-direction, the greens are parallel to y-direction and the blues are parallel to z-direction.

Usages

Buttons

VFIVE is equipped with several visualization methods and the basic usages of buttons are standardized as follows,

  1. While user keeps pressing the left button of the wand, Menu panels are displayed and wand emits a laser beam.
  2. When user selects a panel by the laser beam, Sub-Menu panels are displayed at the right side, if any.
  3. When user releases the left button, if the laser beam is penetrating the panel which user wants to select at the moment, the selection is completed.
  4. The selected visualization method is operated by the middle button of the Wand. For example, in the case of Field Lines, by pressing and releasing the middle button user can set the starting point of the field line.
  5. Pressing the right button eliminates the visualized objects which were visualized by the method being selected now.

Joystick

Joystick of the Wand is used for navigation (translation and rotation).
  1. Shifting the joystick forward moves user towards the direction pointed by the Wand in the virtual space.
  2. Shifting the joystick backward moves user towards the opposite direction.
  3. Shifting the joystick right and left rotates user in the virtual space.

Main Menu

Vector Select vector_select Selecting vector field
Scalar Select scalar_select Selecting scalar field
Object Select object_select Displaying or eliminating objects: curves (specified by -l option) and surfaces (specified by -s option)
Animation animation Play(Animation), 1step forward, backward. While this animation function is activated, user can change the speed of it by vertical motion of the wand while pressing the middle button. By pressing right button user can stop animation. This function is available on VFIVE of more than ver.3.72a.
Scale Changer scalechanger Changing the size of visualized objects (using glScalef)
Snapshot snapshot Saving the image projected to the front screen (PPM format). After selecting this panel, everytime user presses the middle button, an image is saved.
Quit quit Quitting VFIVE

Modules for visualizing vector fields

Field Lines field_lines While pressing the middle button, a virtual laser beam is emitted from the wand. When releasing the button, a ball is launched and it starts drawing the field line. The Runge-Kutta calculation is performed in both directions. The order of Runge-Kutta is 6th.
Particle Tracer particle_tracer Unlike "Field Lines", the Runge-Kutta calculation is performed only positive direction. And "Field Lines" uses only tangential vector in calculation but this method takes also the magnitude of the vector into account.
Local Arrows local_arrows When user presses the middle button, wand emits laser beam and many arrows in an invisible sphere appear. Each arrow indicates the vector field there. The radius of the sphere is 1 feet and its center is at the tip of the beam. User can move the center of the sphere by moving the wand while he or she keeps pressing the middle button.
Snow in Spotlight spotlighted_snow When user presses the middle button, the wand changes into a spotlight and the vector field in the light (cone-shaped region) is visualized by 5,000 white particles moving along the field. User can move the region by moving the wand while he or she keeps pressing the middle button.
Hotaru hotaru 10,000 yellow particles move along the vector field. The particles are scattered in the whole region of data. 'Hotaru' means firefly.
Probe probe While user is pressing the middle button, the wand emits a laser beam and display the local magnitude of the vector field. User can move the position of it by moving the wand while he or she keeps pressing the middle button. This visualization method is available when you use the multi-thread version.

Modules for visualizing scalar field

Isosurface isosurface When user presses the middle button, a virtual object appears in front of him or her. User can change the isosurface level by vertical motion of the wand while the middle button is being pressed. And when user releases the button, the level is determined. The radius of the cylinder indicates absolute value of the scalar.
Local Slicer local_slicer When user presses the middle button of the wand, the wand emits a laser beam and small square slice appears. The color of this slice indicates the distribution of the scalar values there. The red means maximum value and blue means minimum value. User can move the position of the slice by moving the wand while he or she keeps pressing the middle button. The normal vector of this slice is parallel to the first vector field.
Ortho Slicer ortho_slicer This method has three submenus, "x-y plane", "y-z plane" and "z-x plane". The slice indicates the distribution of the scalar values on the plane. User can change the position of the slice by moving the wand while he or she keeps pressing the middle button. For example, in case of "x-y plane" user can change the position by the vertical motion of the wand.
Volume Rendering volumerendering This volume rendering is performed by using texture mapping of OpenGL. User can edit the transfer functions by pressing the middle button of the wand. This visualization method is available when you use the multi-thread version.
Probe probe While user is pressing the middle button, the wand emits a laser beam and display the local magnitude of the scalar field. User can move the position of it by moving the wand while he or she keeps pressing the middle button. This visualization method is available when you use the multi-thread version.

Displaying Objects

Displaying Surfaces

If data is a result of computer simulation of the flow velocity around an obstacle, it is convenient to display the obstacle in some form with data. VFIVE can display surfaces as mentioned before. If user wants to use this function, he or she has to prepare a text file as well as surface data.

% cat test-surf.v5

+------------------------------------------------+
| beginning of text file for surfaces

# vfive sample surface data
surfaceObj:nmen      2
surfaceObj:ni_max    30
surfaceObj:nj_max    50
surfaceObj:xfile     /home/guest/test/test.surf.x
surfaceObj:yfile     /home/guest/test/test.surf.y
surfaceObj:zfile     /home/guest/test/test.surf.z

| end of text file
+------------------------------------------------+

The keywords in the above text file are

 
      The number of surfaces                                               nmen 
      The number of vertices which composes a surface                      ni_max * nj_max
      The x-coordinate data file of vertices which composes surfaces       xfile
      The y-coordinate data file of vertices which composes surfaces       yfile
      The z-coordinate data file of vertices which composes surfaces       zfile

The coordinate files (data) must be

  1. Fortran's unformatted output
  2. real number of single precision (float in C/C++ language)

VFIVE assumes that a surface is smooth everywhere and calculates the normal vector automatically. Therefore if user wants to display squarish (or angular) surface, he or she has to divide it to several surfaces. For example, if user wants to display a cube, user has to inputs 6 surfaces.

A surface is defined with 2 integers (for example, i and j), and surfaces are distinguished by the 3rd parameter.

Example:

   The 1st surface is a rectangle: 
                 x(i,j,1) = i*dx          (dx is constant)
                 y(i,j,1) = j*dy          (dy is constant)
                 z(i,j,1) = 0.0

   The 2nd surface is a cylinder (without lids):  
                 x(i,j,2) = cos(j*dphi)   (dphi is constant)
                 y(i,j,2) = sin(j*dphi)
                 z(i,j,2) = i*dz

   The 3rd surface is a sphere:
                 x(i,j,3) = sin(j*dtht)*cos(i*dphi)  (dtht and dphi are constant)
                 y(i,j,3) = sin(j*dtht)*sin(i*dphi)
                 z(i,j,3) = cos(j*dtht)

The differences among them are only the boundary conditions. VFIVE judges the topologies automatically. For example, if val(i=1,j) == val(i=imax,j) (val=x,y,z), then VFIVE regards the surface as a cylinder.

When user wants to display several surfaces, the maximum values of parameters such as i and j don't need to be the same. For example, when user wants to display 2 rectangles (100x200 and 80x120), user declares variables as follows,

    real*4 x(100,200,2), y(100,200,2), z(100,200,2)

and copy dummy data (999.) in needless arrays.

The following is a sample program to make coordinate data of a torus and a part of sphere, and text file.

torus
+----------------------------------------------------------+   
| beginning of program (Fortran)

      parameter(nmen=2,nimax=30,njmax=50)
      parameter(pi=3.141593,twopi=2*pi)
      parameter(huge=999.0)

      character*50 xfile, yfile, zfile, v5file

      real*4 x(nimax, njmax, nmen)
      real*4 y(nimax, njmax, nmen)
      real*4 z(nimax, njmax, nmen)

      xfile = "/home/guest/test/test.surf.x"
      yfile = "/home/guest/test/test.surf.y"
      zfile = "/home/guest/test/test.surf.z"
      v5file = "/home/guest/test/test-surf.v5"

c     Torus
      rmajor = 10.0
      rminor = 2.0
      x0 = 32.0
      y0 = 32.0
      z0 = 32.0
      dphi = twopi / (nimax-1)
      dtht = twopi / (njmax-1)
      do j = 1 , njmax
	tht = dtht*(j-1)
	do i = 1 , nimax
	  phi = dphi*(i-1)
	  if (i.eq.nimax) phi = 0.0
	  if (j.eq.njmax) tht = 0.0
	  x(i,j,1) = x0 + (rmajor+rminor*cos(tht))*cos(phi)
	  y(i,j,1) = y0 + (rmajor+rminor*cos(tht))*sin(phi)
	  z(i,j,1) = z0 + rminor*sin(tht)
        end do
      end do

c     Psudo-sphere
      x0 = 10.0
      y0 = 10.0
      z0 = 10.0
      rad = 10.0
      niwork = nimax/2
      njwork = njmax/2
      dphi = twopi / (niwork-1)
      thtmin = pi*(2/6.)
      thtmax = pi*(4/6.)
      dtht = (thtmax-thtmin) / (njwork-1)
      do j = 1 , njwork
	tht = thtmax - dtht*(j-1)
	do i = 1 , niwork
	  phi = dphi*(i-1)
	  if (i.eq.niwork) phi = 0.0
	  x(i,j,2) = x0 + rad*sin(tht)*cos(phi)
	  y(i,j,2) = y0 + rad*sin(tht)*sin(phi)
	  z(i,j,2) = z0 + rad*cos(tht)
        end do
      end do

      x(niwork+1,1,2) = huge
      y(niwork+1,1,2) = huge
      z(niwork+1,1,2) = huge
      x(1,njwork+1,2) = huge
      y(1,njwork+1,2) = huge
      z(1,njwork+1,2) = huge


      open(11,file=xfile,form='unformatted')
      open(12,file=yfile,form='unformatted')
      open(13,file=zfile,form='unformatted')
	write(11) x
	write(12) y
	write(13) z
      close(13)
      close(12)
      close(11)

      open(10,file=v5file)
	write(10,8000) "# vfive sample surface data
	write(10,8001) "surfaceObj:nmen ", nmen
	write(10,8001) "surfaceObj:ni_max ", nimax
	write(10,8001) "surfaceObj:nj_max ", njmax
	write(10,8002) "surfaceObj:xfile ",  xfile
	write(10,8002) "surfaceObj:yfile ",  yfile
	write(10,8002) "surfaceObj:zfile ",  zfile
      close(10)

 8000 format(a)
 8001 format(a, i5)
 8002 format(a, a)

      stop
      end

| end of program (Fortran)
+----------------------------------------------------------+
+----------------------------------------------------------+
| beginning of program (C++ language)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

const int nmen = 2;
const int nimax = 30;
const int njmax = 50;

const double pi = 3.141593;
const double twopi = 2.0*pi;
const float huge = 999.0;

int main(int argc, char **argv){

int i,j;

float x[nmen][njmax][nimax];
float y[nmen][njmax][nimax];
float z[nmen][njmax][nimax];

char xfile[]  = "/home/guest/test/test.surf.x";
char yfile[]  = "/home/guest/test/test.surf.y";
char zfile[]  = "/home/guest/test/test.surf.z";
char v5file[] = "/home/guest/test/test-surf.v5";

//	Torus
      float rmajor = 10.0;
      float rminor = 2.0;
      float x0 = 32.0;
      float y0 = 32.0;
      float z0 = 32.0;
      double dphi = twopi / (nimax-1);
      double dtht = twopi / (njmax-1);
      for(j = 0; j< njmax; j++){
	double tht = dtht*j;
	for(i = 0; i< nimax; i++){
	  double phi = dphi*i;
	  if (i == nimax -1) phi = 0.0;
	  if (j == njmax -1) tht = 0.0;
	  x[0][j][i] = x0 + (rmajor+rminor*cos(tht))*cos(phi);
	  y[0][j][i] = y0 + (rmajor+rminor*cos(tht))*sin(phi);
	  z[0][j][i] = z0 + rminor*sin(tht);
        }
      }

//     Psudo-sphere
      x0 = 10.0;
      y0 = 10.0;
      z0 = 10.0;
      float rad = 10.0;
      int niwork = nimax/2;
      int njwork = njmax/2;
      dphi = twopi / (niwork-1);
      double thtmin = pi*(2/6.);
      double thtmax = pi*(4/6.);
      dtht = (thtmax-thtmin) / (njwork-1);
      for(j = 0; j<njwork;j++){
	double tht = thtmax - dtht*j;
	for(i = 0; i < niwork;i++){
	  double phi = dphi*i;
	  if (i == niwork-1) phi = 0.0;
	  x[1][j][i] = x0 + rad*sin(tht)*cos(phi);
	  y[1][j][i] = y0 + rad*sin(tht)*sin(phi);
	  z[1][j][i] = z0 + rad*cos(tht);
        }
      }

      x[1][0][niwork] = huge;
      y[1][0][niwork] = huge;
      z[1][0][niwork] = huge;
      x[1][njwork][0] = huge;
      y[1][njwork][0] = huge;
      z[1][njwork][0] = huge;

      char dummy[4];
      FILE *fp;
      if((fp=fopen(xfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(&x[0][0][0], sizeof(float), nmen*nimax*njmax, fp);
      fclose(fp);

	.........(some lines were omitted).........

      if((fp=fopen(v5file,"w")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
	fprintf(fp, "# vfive sample surface data\n");
	fprintf(fp, "surfaceObj:nmen %d\n", nmen);
	fprintf(fp, "surfaceObj:ni_max %d\n", nimax);
	fprintf(fp, "surfaceObj:nj_max %d\n", njmax);
	fprintf(fp, "surfaceObj:xfile %s\n", xfile);
	fprintf(fp, "surfaceObj:yfile %s\n", yfile);
	fprintf(fp, "surfaceObj:zfile %s\n", zfile);
      fclose(fp);

return 0;
}

| end of program (C++ language)
+----------------------------------------------------------+

Displaying Curves

If user wants to display curves, he or she has to prepare a text file as well as curve data.

% cat test-lines.v5

+------------------------------------------------------------------+
| beginning of text file

# vfive sample curve data
curveObj:nhon      3
curveObj:ntenmax   100
curveObj:xfile /home/guest/test/test-lines.x         
curveObj:yfile /home/guest/test/test-lines.y         
curveObj:zfile /home/guest/test/test-lines.z         
curveObj:cfile /home/guest/test/test-lines.c

| end of text file
+------------------------------------------------------------------+

The above example defines 3 curves. A curve is composed of 100 vertices at most, and the coordinate data files of the vertices are xfile, yfile and zfile. Present version of VFIVE reads cfile but does not use it at all. User has to prepare cfile whose size is the same as xfile (yfile and zfile). These coordinate data must be

  1. Fortran's unformatted output
  2. real number of single precision (float in C/C++ language)

The numbers of vertex which compose curves is not needed to be the same. In that case user has to copy dummy data (999.0) in the needless arrays as well as the case of surface data.

The following is a sample program to make coordinate data of 3 curves and text file.

lines
+--------------------------------------------------------+
| beginning of program (Fortrn)                 
      implicit none

      integer ntenmx, nhon
      parameter(ntenmx=100,nhon=3)

      real*4 x(ntenmx,nhon),y(ntenmx,nhon),z(ntenmx,nhon)
      real*4 c(ntenmx,nhon)
      real*4 pi, twopi, theta, phase
      integer i,j

      character*50 xfile, yfile, zfile, cfile, v5file

c     xfile = "/home/guest/test/test-lines.x"
      yfile = "/home/guest/test/test-lines.y"
      zfile = "/home/guest/test/test-lines.z"
      cfile = "/home/guest/test/test-lines.c"
      v5file = "/home/guest/test/test-lines.v5"

      pi = atan(1.)*4
      twopi = pi*2

c     ... Define triple helix.
      do j = 1 , nhon
	phase = twopi / nhon * (j-1)
	do i = 1 , ntenmx
	  theta = twopi*float(i-1)/ntenmx
	  x(i,j) = 5.0*cos(theta + phase) 
	  y(i,j) = 5.0*sin(theta + phase)
	  z(i,j) = 20.0 / ntenmx * (i-1)
	  c(i,j) = 0.0
	end do
      end do

c     ... The 3rd line is short.
      x(ntenmx/2,3) = 999.
      y(ntenmx/2,3) = 999.
      z(ntenmx/2,3) = 999.
      c(ntenmx/2,3) = 999.

c     ... Make binary data file
      open(11,file=xfile,form='unformatted')
      open(12,file=yfile,form='unformatted')
      open(13,file=zfile,form='unformatted')
      open(14,file=cfile,form='unformatted')
	write(11) x
	write(12) y
	write(13) z
	write(14) c
      close(14)
      close(13)
      close(12)
      close(11)

c     make text data file
      open(10,file=v5file)
	write(10,8000) "# vfive sample curve data"
	write(10,8001) "curveObj:nhon ", nhon
	write(10,8001) "curveObj:ntenmax ", ntenmx
	write(10,8002) "curveObj:xfile ",  xfile
	write(10,8002) "curveObj:yfile ",  yfile
	write(10,8002) "curveObj:zfile ",  zfile
	write(10,8002) "curveObj:cfile ",  cfile
      close(10)

 8000 format(a)
 8001 format(a, i5)
 8002 format(a, a)

      stop
      end


| end of program (Fortran)
+--------------------------------------------------------+
+--------------------------------------------------------+
| beginning of program (C++ language)          
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

const int ntenmx = 100;
const int nhon = 3;

int main(int argc, char **argv){

  float x[nhon][ntenmx],y[nhon][ntenmx],z[nhon][ntenmx];
  float c[nhon][ntenmx];
  double pi, twopi, theta, phase
  int i,j;

  char xfile[]  = "/home/guest/test/test-lines.x";
  char yfile[]  = "/home/guest/test/test-lines.y";
  char zfile[]  = "/home/guest/test/test-lines.z";
  char cfile[]  = "/home/guest/test/test-lines.c";
  char v5file[] = "/home/guest/test/test-lines.v5";

  pi = 3.14159;
  twopi = pi*2.0;

//     ... Define triple helix.
      for(j = 0; j < nhon; j++){
	phase = twopi / nhon * j;
	for(i = 0; i < ntenmx; i++){
	  theta = twopi*(double)i/ntenmx;
	  x[j][i] = 5.0*cos(theta + phase);
	  y[j][i] = 5.0*sin(theta + phase);
	  z[j][i] = 20.0 / ntenmx * i;
	  c[j][i] = 0.0;
	}
      }

//     ... The 3rd line is short.
      x[2][ntenmx/2] = 999.;
      y[2][ntenmx/2] = 999.;
      z[2][ntenmx/2] = 999.;
      c[2][ntenmx/2] = 999.;

//     ... Make binary data file

      char dummy[4];
      FILE *fp;
      if((fp=fopen(xfile,"wb")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
       fwrite(dummy, 1, 4, fp);
       fwrite(&x[0][0], sizeof(float), ntenmx*nhon, fp);
      fclose(fp);

      ..........(some lines were omitted).........

//     make text data file
      if((fp=fopen(v5file,"w")) == NULL){
        fputs("Error\n",stderr);
        exit(1);
      }
	fprintf(fp, "# vfive sample curve data\n");
	fprintf(fp, "curveObj:nhon %d\n", nhon);
	fprintf(fp, "curveObj:ntenmax %d\n", ntenmx);
	fprintf(fp, "curveObj:xfile %s\n", xfile);
	fprintf(fp, "curveObj:yfile %s\n", yfile);
	fprintf(fp, "curveObj:zfile %s\n", zfile);
	fprintf(fp, "curveObj:cfile %s\n", cfile);
      fclose(fp);

return 0;
}

| end of program (C++ language)
+--------------------------------------------------------+

Acknowledgement

We thanks Dr. Toyokazu Sato, who worked at NIFS as COE researcher, for developing the functions which make texture data of menu panels.

References

  1. Akira Kageyama, Yuichi Tamura, and Tetsuya Sato,
    Visualization of Vector Field by Virtual Reality,
    Progress of Theoretical Physics Supplement, No.138 (2000)

Last Update:2010.03.25
Akira Kageyama and Nobuaki Ohno, Advanced Visualization and Perception Research Group, Earth Simulator Center, JAMSTEC