Linked Rings Visualization


proof of concept: population data trends from villages on the Big Island of Hawaii

Process

Visualization process in italics.

Technical process in normal text.

My mission in this project was to produce prototype "proof of concept" visualizations of data gathered in Hawaii and San Diego. The Hawaii data is public health information about villages on the north coast of the Big Island. Initially this data was not available in enough quantity to work with. As an alternative data source, we began collecting inormation on potential bioloical terrorism targets in San Diego. However, it quickly became obvious that this data was sensistive and could not be shared at conferences, etc., and so some publicly available data was selected with many of the same characteristsics.

For this we chose information about the nutritional content of breakfasts from fast food reatsurants in the "golden triangle," (the region within a mile of the triangle formed bi I-5, I-805 and Cal-52 San Deigo, La Jolla and Del Mar).

We had previoulsy visualized the location of these retaurants as colored spheres against a satellite photo.


fast food restaurants in the golden triangle (degreees and minutes only)
white = Jack in the Box, blue=Burger King, Yellow=Carl's Jr, orange=McDonald's

This was done using the program latlon_to_sphere.

If you notice a grid-like appearance to the spacing, it is becasue the latitude/longitude parser at this point did not yet read seconds, only degrees and minutes, so the grid is on minute boundaries. (In contrast, USGS uses a 7.5 minute grid.)

Our sponsors had shown interest in the torus visualizations we were working on, so it was decided to do this research using mostly the torus primitive.

We had previously used a single torus for each fast food breakfast to show only a total nutritional score.


fast food restaurants in the golden triangle
ring diameter = nutritional score for breakfast

This was done using the programs latlon_to_sphere and vect_to_meshes.

As a representation of nutritional data we chose linked rings, with constant inner radius and the outer radius displaying a quantity.

iLeft to right, the six rings linked with each base ring represent:

They are scaled uniformly by being in units of per cent of USDA recommended minimum daily requirements.

In my first experiment with real data and linked rings (15 Feb 2002) I learned that if neighboring sets of rings get too close together they interlink and visually interfere.

In this test I laid the base rings directly on the map, and colored them orange for contrast.


linked rings, first test

To get to this point required several tools. The program mkTorus created torus shapes in a variety of file formats, including AVS .polyh (polyhdedron) and .mesh (quad mesh), for the building blocks of the scene.

The program xf (transform) performs geometric transformations on several file formats, including AVS the .polyh and mesh formats. (The abbreviation 'xf' for 'transfrom' dates from analog electronic engineers; my father was trained as one of these in the early 1950s.) Using this program I was able place rings at different locations and with different orientations, based on matrix files, each containing a 4 by 4 matrix.

The program mkMatrix creates the matrix files used by xf. For example, this is a matrix to translate 5 units in the X direction:

        1.000000 0.000000 0.000000 0.000000
        0.000000 1.000000 0.000000 0.000000
        0.000000 0.000000 1.000000 0.000000
        5.000000 0.000000 0.000000 1.000000
(For more information on the format of 4x4 homogenious coordinates, see Fundamentals of Interactive Computer Graphics, by Foley and Van Dam, especially chapter 7.)

Lastly, to manage the use of these tools together I wrote mkRingsScript, which reads an input file of position and other data, and creates a shell script to invoke the above tools.

For more information about these tools, see the Tools section of this document.

Next, I raised the rings up off of the map amd marked the map points with colored spheres. Again the color of the sphere indicated which fast food restaurant. This gave a good indication of the location being represented. Once again the problem of interference between neighbors was apparent. >>>


sets of linked rings, each on a vector "pole" with a colored sphere as a "base"
I used the program latlon_to_sphere to create the spehere bases, and modified mkRings Script to output the file foo.vect>>>


15 Feb 2002rings animated./rings_anim.gif
16 Feb 2002color rings./c0.jpg
16 Feb 2002color rings animated./colors.gif
17 Feb 2002color rings offset to avoid colision./cc.jpg
17 Feb 2002full rings./ccc08.jpg
17 Feb 2002full rings animated./full.gif

>>>

Filename Date MachineID SiteName Latitude/Longitude (Deg Min Sec) Adult M / Adult F / Child M / Child F / Infant M / Infant F
HI10-B789BBE9.xml 2001.07.29 HI10
HI10-B789BBFB.xml 2001.07.29 HI10 Waipu / Papaa
HI2-B78ACD36.xml 2001.07.30 HI2 Peter _ _ _ _ _ _
HI2-B78B2249.xml 2001.07.30 HI2
HI2-B78B41B2.xml 2001.07.30 HI2 Peter _ _ _ _ _ _
HI2-B78B41CF.xml 2001.07.30 HI2
HI2-B7998B7B.xml 2001.08.10 HI2
HI2-B7B07426.xml 2001.08.27 HI2 Peter _ _ _ _ _ _
HI2-B81BDB11.xml 2001.11.17 HI2
HI4-B789BCB8.xml 2001.07.29 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 NULL NULL NULL NULL NULL NULL
HI4-B789BCC9.xml 2001.07.29 HI4
HI4-B7A67DA9.xml 2001.08.20 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 48 55 10 9 2 5
HI4-B7A67E05.xml 2001.08.20 HI4
HI4-B7B014EC.xml 2001.08.27 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 50 59 12 11 3 5
HI4-B7B0157E.xml 2001.08.27 HI4
HI4-B7C28BFD.xml 2001.09.10 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 4 .3 NULL NULL 2 NULL
HI4-B7C28D3B.xml 2001.09.10 HI4
HI4-B7DDD988.xml 2001.10.01 HI4
HI4-B7DDDA2D.xml 2001.10.01 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 3 .3 NULL NULL NULL NULL NULL NULL
HI4-B7EF85C1.xml 2001.10.14 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 NULL NULL NULL NULL NULL NULL
HI4-B7EF8604.xml 2001.10.14 HI4
HI4-B802FCC9.xml 2001.10.29 HI4
HI4-B802FD5A.xml 2001.10.29 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 2 2 5 NULL NULL NULL
HI4-B80BF93C.xml 2001.11.05 HI4
HI4-B80BF97B.xml 2001.11.05 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 NULL NULL NULL NULL NULL NULL
HI4-B875844D.xml 2002.01.24 HI4
HI4-B8758491.xml 2002.01.24 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 3 1 NULL NULL NULL NULL
HI5-B789BE4A.xml 2001.07.29 HI5 Paauilo LP 20 2.437 0 -155 21.965 0 NULL NULL NULL NULL NULL NULL
HI5-B789BE5A.xml 2001.07.29 HI5
HI5-B7A57DFE.xml 2001.08.19 HI5
HI5-B7A674A3.xml 2001.08.20 HI5 Paauilo LP 20 2.437 0 -155 21.965 0 36 23 10 5 3 NULL
HI5-B7DDDAA9.xml 2001.10.01 HI5
HI5-B7DDDB94.xml 2001.10.01 HI5 Paauilo LP 20 2.437 0 -155 21.965 0 4 5 NULL 3 1 NULL
HI5-B802FB39.xml 2001.10.29 HI5 Paauilo LP 20 2.437 0 -155 21.965 0 NULL NULL NULL NULL NULL NULL
HI5-B802FB83.xml 2001.10.29 HI5
HI5-B80BF6E6.xml 2001.11.05 HI5
HI5-B80BF785.xml 2001.11.05 HI5 Paauilo LP 20 2.437 0 -155 21.965 0 1 2 NULL NULL NULL NULL
HI5-B871BEBE.xml 2002.01.21 HI5
HI5-B871BF05.xml 2002.01.21 HI5 Paauilo LP 20 2.437 0 -155 21.965 0 NULL NULL NULL NULL NULL NULL
HI6-B789BD83.xml 2001.07.29 HI6 Paauhau AP 20 4.237 0 -115 26.635 0 NULL NULL NULL NULL NULL NULL
HI6-B789BD97.xml 2001.07.29 HI6
HI7-B789BDAB.xml 2001.07.29 HI7 Paauhau LP / H 20 4.914 0 -155 26.327 0 NULL NULL NULL NULL NULL NULL
HI7-B789BDBB.xml 2001.07.29 HI7
HI8-B79324C8.xml 2001.08.05 HI8 Ookala 20 0.571 0 -115 16.388 0 24 17 3 7 1 4
HI8-B79326E6.xml 2001.08.05 HI8
HI8-B7A98677.xml 2001.08.22 HI8 Ookala 20 0.571 0 -115 16.388 0 28 23 5 10 1 4
HI8-B7AA68B0.xml 2001.08.23 HI8
HI9-B789B9FA.xml 2001.07.29 HI9
HI9-B789BB77.xml 2001.07.29 HI9 Camp 8 _ _ _ _ _ _ _ _ _ _ _ _
HI9-B7A57D33.xml 2001.08.19 HI9
HI9-B7B014E7.xml 2001.08.27 HI9
HI9-B7EF8510.xml 2001.10.14 HI9

>>>

Filename Date MachineID SiteName Latitude/Longitude (Deg Min Sec) Adult M / Adult F / Child M / Child F / Infant M / Infant F
HI4-B7A67DA9.xml 2001.08.20 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 48 55 10 9 2 5
HI4-B7B014EC.xml 2001.08.27 HI4 Paauilo Mak 20 2.350 0 -155 22.086 0 50 59 12 11 3 5
HI8-B79324C8.xml 2001.08.05 HI8 Ookala 20 0.571 0 -115 16.388 0 24 17 3 7 1 4
HI8-B7A98677.xml 2001.08.22 HI8 Ookala 20 0.571 0 -115 16.388 0 28 23 5 10 1 4

>>>

15 Mar 2002Hawaii/hawaii00.jpgHawaii/hawaii00.jpg
15 Mar 2002Hawaii/h_anim.gifHawaii/h_anim.gif
15 Mar 2002Hawaii/hh.jpgHawaii/hh.jpg


Tools

Note: meta-syntax as follows: if A is required and B is optional, syntax is:

A <B>
>>>

mkTorus usage


abs@littleboy 3 % mkTorus -u
mkTorus: USAGE: mkTorus [<flags>]

    flag              meaning                 default
    ----------------  ----------------------  -------
    -D                debug                   FALSE
    -c                colors                  FALSE
    -C <r> <g> <b>    use supplied colors     FALSE
                      (floats 0.0 to 1.0)
    -d <int> <int>    divisions               24 36
    -r <real> <real>  radius                  1.0 8.0
    -t <type>         0 = polyh               0
                      1 = polyhc
                      2 = mesh
    -h                help on this program
    -u                usage (this message)
  

mkTorus sample input/output

Test
#
mkTorus -t 0 -d 4 4 -r 2.0 8.0 > torus.polyh

torus.polyh
smooth
16
0.000000 8.000000 2.000000
0.000000 10.000000 0.000000
0.000000 8.000000 -2.000000
0.000000 6.000000 -0.000000
8.000000 0.000000 2.000000
10.000000 0.000000 0.000000
8.000000 0.000000 -2.000000
6.000000 0.000000 -0.000000
0.000000 -8.000000 2.000000
0.000001 -10.000000 0.000000
0.000000 -8.000000 -2.000000
0.000000 -6.000000 -0.000000
-8.000000 -0.000001 2.000000
-10.000000 -0.000001 0.000000
-8.000000 -0.000001 -2.000000
-6.000000 -0.000000 -0.000000 
4
2 6 5 1
4
3 7 6 2
4
4 8 7 3
4
1 5 8 4
4
6 10 9 5
4
7 11 10 6
4
8 12 11 7
4
5 9 12 8
4
10 14 13 9
4
11 15 14 10
4
12 16 15 11
4
9 13 16 12
4
14 2 1 13
4
15 3 2 14
4
16 4 3 15
4
13 1 4 16 

mkTorus source code

mkMatrix usage


abs@littleboy 6 % mkMatrix -u
mkMatrix: USAGE: mkMatrix [<flags>]

    flag               meaning                 default
    -------------      ----------------------  -------
    -D                 debug                   FALSE
    -d                 angle is in degrees     radians
    -h                 help on this program
    -r <axis> <angle>  rotate about x,y or z   x 0.0
    -s <scale factor>  scale uniformly
    -t <x> <y> <z>     translate in xyz
    -u                 usage (this message)
  

mkMatrix sample input/output

Test
#
mkMatrix -r x 45 -d > xrot45.matrix

xrot45.matrix
1.000000 0.000000 0.000000 0.000000
0.000000 0.707107 0.707107 0.000000
0.000000 -0.707107 0.707107 0.000000
0.000000 0.000000 0.000000 1.000000
  

mkMatrix source code

xf usage


abs@littleboy 5 % xf -u
xf: USAGE: xf [<flags>]

    flag           meaning                 default
    -------------  ----------------------  -------
    -D             debug                   FALSE
    -t <int>       type: 0 = polyh         0
                         1 = polyhc
                         2 = mesh
    -f <filename>  name of matrix file     test.matrix
    -h             help on this program
    -o             output Java .obj file   FALSE
    -u             usage (this message)
  

xf sample input/output

Test
#
xf -D -f tranx5.matrix < old.polyh > tranx5.polyh

tranx5.matrix
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
5.000000 0.000000 0.000000 1.000000

old.polyh
facet
8
1.0 1.0 1.0
1.0 1.0 -1.0
1.0 -1.0 -1.0
1.0 -1.0 1.0
-1.0 1.0 1.0
-1.0 1.0 -1.0
-1.0 -1.0 -1.0
-1.0 -1.0 1.0
4
1 2 3 4
4 
5 6 7 8
4 
2 3 7 6 
4 
1 4 8 5
4 
2 1 5 6
4 
3 4 8 7

tranx5.polyh
facet
8
6.0 1.0 1.0
6.0 1.0 -1.0
6.0 -1.0 -1.0
6.0 -1.0 1.0
-4.0 1.0 1.0
-4.0 1.0 -1.0
-4.0 -1.0 -1.0
-4.0 -1.0 1.0
4
1 2 3 4
4 
5 6 7 8
4 
2 3 7 6 
4 
1 4 8 5
4 
2 1 5 6
4 
3 4 8 7
  

xf source code

combineGeometry help


abs@littleboy 5 % combineGeometry -h
combineGeometry: HELP:

    combineGeometry - combine two AVS polyh files into one

    For example, this program combines the following two files into one
    with the command:

        combineGeometry < test0.polyh -f test1.polyh > test2.polyh

    ::::::::::::::
    test0.polyh
    ::::::::::::::
    facet
    4
    -1.0 -1.0 0.0
    -1.0 1.0 0.0
    1.0 1.0 0.0
    1.0 -1.0 0.0
    4
    1 2 3 4
    ::::::::::::::
    test1.polyh
    ::::::::::::::
    facet
    5
    -2.0 -2.0 3.0
    -2.0 2.0 3.0
    2.0 2.0 3.0
    4.0 0.0 3.0
    2.0 -2.0 3.0
    5
    1 2 3 4 5
    ::::::::::::::
    test2.polyh
    ::::::::::::::
    facet
    9
    -1.000000 -1.000000 0.000000
    -1.000000 1.000000 0.000000
    1.000000 1.000000 0.000000
    1.000000 -1.000000 0.000000
    -2.000000 -2.000000 3.000000
    -2.000000 2.000000 3.000000
    2.000000 2.000000 3.000000
    4.000000 0.000000 3.000000
    2.000000 -2.000000 3.000000
    4
    1 2 3 4
    5
    5 6 7 8 9
  

combineGeometry usage


abs@littleboy 5 % combineGeometry -u

    flag           meaning                 default
    -------------  ----------------------  -------
    -D             debug                   FALSE
    -f <string>    filename for 2nd input  input2.polyh
    -h             help on this program
    -u             usage (this message)
  

combineGeometry source code

mkRingsScript help


abs@littleboy 13 % mkRingsScript -h
mkRingsScript: HELP:

    mkRingsScript - make a shell script to make rings from data

    This program reads an input file from standard input, of latitutde
    and longitude plus other data values, and writes out a script to use
    other programs to create rings of tori representing the data values
    above the latitude and longitude points.  The -n flag passes in the
    number of locations (one per line in the file) and the -v flag passes
    in the number of values at each location (one ring per value).  You
    can use -s to pass in a scale factor applied to all the rings.  The
    program can create AVS polyh, polyhc or mesh files controlled by
    the -t flag.

    The -m flag indicates that the first line in the data is
    (after dummy latitude and longitude values) the maximum
    for each value, and each ring's outer radius is proportional
    to a value divided by its maximum.

    If the number of iterations passed in with -i is greater than zero,
    the prgram tries to spread the rings out so that close locations'
    rings do not interlock.  Because moving some points farther
    apart imay bring others closer together, a number of iterations
    may be required to spread them aesthetically.  The -d flag
    allows you to pass in the minimum distance used in this process.

    For example, this command line:

        ./mkRingsScript -m -d 0.01 -i 0 -s 0.001 -t 1 -n 6 -v 6 < test.in > te
t_script
        chmod a+x test_script
        ./test_script

    with this input:

        32 45 0 -117 22 30 0.85 0.39 0.47 0.35 0.75 0.10
        32 45 0 -117 22 30 0.55 0.61 0.73 0.25 0.85 0.12
        32 45 0 -117 22 30 0.25 0.83 0.99 0.15 0.95 0.14
        32 45 0 -117 22 30 0.01 1.05 1.25 0.05 1.05 0.16
        32 45 0 -117 22 30 0.01 1.27 1.51 0.01 1.15 0.18
        32 45 0 -117 22 30 0.01 1.49 1.77 0.01 1.25 0.20

    produsces a script which creates the polyhc files of
    rings corresponding to the data, where the first six numbers
    on each line are latitude degrees, minutes and seconds followed
    by longitude degrees, minutes and seconds.  The next six
    numbers are the values used to create six rings linked to
    a central seventh at each location.

    When the type = 1 (polyhc), colors are created.
    The color depends on a utility function, from
    0 = red = bad to 1 = green = good.  Semi-arbitrarily
    the current utility function is a pointy-hat,
    zero outside the 0 < v < 2, a unit slope up from 0 to 1,
    and a unit slope down from 1 to 2:

        |    *
        |   * *
        |  *   *
        | *     *
        |*       *
    *****---------*****
        |

    The program also secretly creates the file: moved_lines.vect
    containing vectors which connect each point in the X-Y plane
    with its moved point where the ring is, above that plane in Z.

    If the -a flag is used, additional commands to create AVS .geom
    files are added.

    If the -c flag is used and the type is 0, additional commands
    are added to chain .polyh files with the combineGeometry
    program, and then use xf to create a .obj file which the Java
    applet ThreeD  can read.
  

mkRingsScript usage


abs@littleboy 13 % mkRingsScript -u
mkRingsScript: USAGE: mkRingsScript [flags] < infile > outfile

    flag           meaning                 default
    -------------  ----------------------  -------
    -D             debug                   FALSE
    -a             AVS geom files needed   FALSE
    -c             chain .polyh files      FALSE
    -d             distance minimum        0.01
    -h             help on this program
    -i <int>       number of iterations    0
    -m             max data line is 1st    FALSE
                       in data stream
    -n <int>       number of location      1
    -s <float>     scale of all tori       1.0
    -t <type>      0 = polyh               0
                   1 = polyhc
                   2 = mesh
    -u             usage (this message)
    -z <float>     shift tori along Z axis 0.01 
  

mkRingsScript sample input/output

Test
#
./mkRingsScript -D -a -m -d 0.01 -i 0 -s 0.001 -t 1 -n 3 -v 2 < test_few.in > test_script
chmod a+x test_script
echo "---------- running script ----------"
./test_script
echo "---------- done with script ----------"
  test_few.in
0.0 0.0   0.0 0.0 0.0     0.0 100 100
32 52.248 0.0 -117 12.590 0.0 20 40
32 54.400 0.0 -117 10.404 0.0 60 80
32 52.716 0.0 -117 9.971 0.0 100 110

  test_script
#
vect_to_geom < moved_lines.vect > moved_lines.geom
rm D?.geom D??.geom
#
rm base_torus*.geom data*.geom
mkTorus -d 8 16 -r 0.000200 0.000300 -t 1 -C 0.700000 0.300000 0.000000 > torus.
polyhc
mkMatrix -t -117.209831 32.870800 0.010000 > trans_latlon.matrix
xf -t 1 -f trans_latlon.matrix < torus.polyhc > base_torus0.polyhc
polyhc_to_geom < base_torus0.polyhc > base_torus0.geom
#
mkTorus -d 8 16 -r 0.000200 0.000200 -t 1 -C 0.800000 0.200000 0.000000 > torus.
polyhc
mkMatrix -r y 90 -d > rotY90.matrix
mkMatrix -t 0.0 0.000500 0.0 > transY.matrix
mkMatrix -r z -60.000000 -d > rotZPhi.matrix
xf -t 1 -f rotY90.matrix < torus.polyhc > temp00.polyhc
xf -t 1 -f transY.matrix < temp00.polyhc > temp01.polyhc
xf -t 1 -f rotZPhi.matrix < temp01.polyhc > temp02.polyhc
xf -t 1 -f trans_latlon.matrix < temp02.polyhc > data0_0.polyhc
rm temp*.polyhc
polyhc_to_geom < data0_0.polyhc > data0_0.geom
*
*
*
  

mkRingsScript source code

Last update 29-Mar-2001 by ABS.