Use of 3D arrays

Like most computer languages, LB handles one and two dimensional arrays. i.e. lists of numeric ( or string) terms addressable by one or two parameters. Code like dim height( 12) or dim width( 20, 20).

The 3D extension of this, which would cover situations representing values in three ( usually spatial) dimensions has to be simulated.

LB Help File shows one way. I use a slightly different way in the code below. I've on other occasions used indexing into a long string, and into a file too.

The context of my interest is the many situations where we wish to visually display and examine 3D data. Think of a CT tomogram of your head. Doctors expect to be able to select the plane of interest and fly through and around the areas/ volumes of concern. Or astrophysicists want to model all the stars of a galaxy and their motion. Or reactor physicists want to model the behavious of neutrons in a reactor core.

Another modern area is 3D 'point clouds' such as the representations of surfaces that have been laser-scanned. This time we have a 'sparse' data set since most voxels are empty, but still needs lots of computing power.

I visited this topic before, for instance at my website.

Nearly 30 years ago a condemned man volunteered to be frozen and sliced into sub-millimetre sections, which were photographed and made available on the 'web as a fly-through animation called the 'Visible Human Project'- see Wikipedia. Magic! You can guess which sections pupils in school particularly found fascinating!

Most medical data now is gathered by non-invasive scanning, rather than gung-ho freezing an executed man and grinding the cadaver down millimeter by millimeter!

Sadly, the amounts of computing needed require very high speed computers, and programs have to be written to compile to machine code and handle many parallel graphic processers. My first coding was on Titan -a predecessor of the early Fortran computers. I've moved with the times, and do what I can with LB on modern machines. But the problem is that that 'image of your head' may contain 10,000,000,000 voxels, each spelling out a local value, and you want to calculate and display in real-time a 2D plane through those 3D data. I have to be content with much lower resolutions and still have such long computational delays that I generally speed up the display by collecting images then making an animated GIF.

An example situation

Imagine a 3D cylinder. Cross sections parallel to the 3 axes will be circles or rectangles. If you choose a random plane you may miss entirely, or get all sorts of ellipses or skinny rectangles... But straightforward to code.

Here are three animations as you sweep through the figure and surrounding space. ( Not synchronised, and played asn animated GIFs faster than the code can do in real time.)

- - -


Code

Note that without the bmp the right hand of the display will not show the diagram, and you need manually to create the folder the images are to go in.



nomainwin

global N: N =40

dim threeD$( N^3)

WindowWidth  =1750
WindowHeight = 680

open "3D arrays" for graphics_nsb as #wg

#wg "trapclose quit"
#wg "down ; size 1 ; fill black ; color cyan ; font 18 bold"
#wg "up ; goto  17 503 ; down ; box  437 97"
#wg "up ; goto 437 503 ; down ; box  857 97"
#wg "up ; goto 857 503 ; down ; box 1277 97"

'loadbmp "scr", "CartesianAxes2.bmp"
'#wg "down ; drawbmp scr 1290 100"

#wg "flush ; size 4"

now =time$( "seconds")

for x =0 to N -1
    for y =0 to N -1
        for z =0 to N -1
            R =int( ( ( x -20)^2 +( y -20)^2)^0.5)
            if R <=16 and ( ( z >10) and ( z <36)) then call arrayPut x, y, z,   "255 255 0" else call arrayPut x, y, z,   "0 0 0"
            scan
        next z
    next y
next x

print time$( "seconds") -now ; " seconds to generate 3D array"
now =time$( "seconds")

    '   __________________________________________________________

for z =N -1 to 0 step -1
    for x =N -1 to 0 step -1
        for y =0 to N -1
            v$ =arrayGet$( x, y, z)
            'if v$ ="0 0 0" then #wg "size 2" else #wg "size 4"
            #wg "color "; v$
            #wg "backcolor "; v$
            #wg "set "; 20 +10 *x; " "; 500 -10 *y
            scan
        next y
    next x
    #wg "up ; goto 180 60 ; down ; color cyan"
    #wg "\" +"z =" +right$( "000" +str$( z), 3)
    #wg "flush ; getbmp scr 17 30 420 465"
    bmpsave "scr", "screens3/layerZ" +right$( "000" +str$( z), 3) +".bmp"
next z


print time$( "seconds") - now ;" seconds to display all Z-layers of 3D array"

for x =N -1 to 0 step -1
    for y =N -1 to 0 step -1
        for z =0 to N -1
            v$ =arrayGet$( x, y, z)
            'if v$ ="0 0 0" then #wg "size 2" else #wg "size 4"
            #wg "color "; v$
            #wg "backcolor "; v$
            #wg "set "; 440 +10 *y; " "; 500 -10 *z
            scan
        next z
    next y
    #wg "up ; goto 600 60 ; down ; color cyan"
    #wg "\" +"x =" +right$( "000" +str$( x), 3)
    #wg "flush ; getbmp scr 437 30 420 465"
    bmpsave "scr", "screens3/layerX" +right$( "000" +str$( x), 3) +".bmp"
next x

print time$( "seconds") - now ;" seconds to display all X layers of 3D array"


for y =N -1 to 0 step -1
    for x =N -1 to 0 step -1
        for z =0 to N -1
            v$ =arrayGet$( x, y, z)
            'if v$ ="0 0 0" then #wg "size 2" else #wg "size 4"
            #wg "color "; v$
            #wg "backcolor "; v$
            #wg "set "; 860 +10 *x; " "; 500 -10 *z
            scan
        next z
    next x
    #wg "up ; goto 1020 60 ; down ; color cyan"
    #wg "\" +"y =" +right$( "000" +str$( y), 3)
    #wg "flush ; getbmp scr 857 30 420 465"
    bmpsave "scr", "screens3/layerY" +right$( "000" +str$( y), 3) +".bmp"
next y

print time$( "seconds") - now ;" seconds to display all Y-layers of 3D array"

wait
    '   ______________________________________________________________________

sub arrayPut i, j, k, value$    '   limited to 100 by 100 by 100 terms
    threeD$( i +N *j +N^2 *k) =value$
end sub

function arrayGet$( i, j, k)    '   limited to 100 by 100 by 100 terms
    arrayGet$ =threeD$( i +N *j +N^2 *k)
end function

sub quit h$
    close #wg
    end
end sub