#!/usr/local/bin/perl # # Program Name: phase2 Larry Gales 11-1999 # # Purpose: # This program reads in 3D data for a VRML program. The data is of the # form: # type=x-axis, max=100, span=85-88, thick=3, grid=5, color=white,name=age # type=y-axis, max= 80, span=.2-0.23, thick=3, grid=5, color=white,name=sex # type=z-axis, max= 70, span=52-96, thick=3, grid=5, color=white,name=ht # # type=cone, x=2, y=3, z=2, width=0.5, height=1, color=green # type=cylinder, x=5, y=19, z=22, width=0.5, height=1, color=green # type=sphere, x=22, y=23, z=33, radius=0.8, color=blue # type=box, x=30, y=12, z=13, size=2, color=red # type=text, x=13, y=22, z=14, size=3, string=Hi there!, color=yellow # # which describe the coordinate system and data points to be plotted, # in terms of the types of symbols, their size, location, and color. # The data is free-form, and case insensitive. It is assumed that all # data values are converted (maped) to the range 0 to N where N is <= 100. # The true maximum value (which appears on the output) is given by # the value "truemax". # # Note that all data values are divided by 25 in order to create a display # in VRML that is of the right size. # # Errors are flagged and sent to STDERR output. Note that data lines that # contain "//" are comment lines and are ignored # # The program creates VRML structures which display data # # Invocation: # You invoke this program as follows: # # mead% phase2 < xxx.data > xxx.wrl # # where "phase2" is this program, "xxx.data" is the input data for it, # which is created by a previous program named "phase1", # and "xxx.wrl" is the final VRML code which can be displayed in 3D # if it is dragged over any browser window that has the Cosmo Player 2.1.1 # installed. # # # ^^^^^^^^^^^^^^^^^^^^ Main Program ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ &initialize; while () { # Main input loop chop; $line = $_; # Current input line $Nlines++; @pairs = split( /,/, $line); # Splits line based on "'" $len = @pairs; # Number of comma delimited pairs &initial_input; # Initilize input values to 0 &parse_input; if ($gtype eq " " ) { # If blank line, ignore next; }; if ($Err == 1 ) { print STDERR "# ERROR in data for line $Nlines \n"; print STDERR "# Line= $line \n"; next; } &convert_color; if ( $gtype =~ /-axis/i ) { # Shift the axes so they run from &process_axes; } &process_data; # Print VRML controls for a sphere } # End of main loop &check_for_errors; &make_gridlines; # vvvvvvvvvvvvvvvvvvvv End Main Program vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Initialize all non-input variables to 0 and print out VRML header file sub initialize { $Nlines = 0; # Number of lines of input data $Xmin = 0; $Xmax = 0; # Min/Max of X-axis $Ymin = 0; $Ymax = 0; # Min/Max of Y-axis $Zmin = 0; $Zmax = 0; # Min/Max of Z-axis $Xgrid =0; $Xthickness = 0; # No. grid lines, axis width, X $Ygrid =0; $Ythickness = 0; # No. grid lines, axis width, Y $Zgrid =0; $Zthickness = 0; # No. grid lines, axis width, Z $min =0; # Minimum is always 0 print "#VRML V2.0 utf8 \n"; print "\n"; print "#Created with V-Realm Builder v2.1\n"; print "#Ligos Corporation\n"; print "#www.ligos.com\n"; print "\n"; } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Initialize all input variables to 0 sub initial_input { $Err = 0; # Error indicator $gtype = " "; # Graphic type (eg, axis, cone,...) $x = 0; $y = 0; $z = 0; # (x,y,z) coords of data point $max = 0; # All data converted to 0 - $max $span = " "; # Range of data along axis $grid = 0; # Number of grid lines $color = 0; # Color of data points/axes $width = 0; $height = 0; # Width/height of data point objects $thickness = 0; # Thickness of axis lines $str = 0; # Text to be displayed at (x,y,z) $radius = 0; # Radius of cylinder, sphere, or cone $size = 0; # Size of sides of box, or text string $a_name = ""; # name for axis } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Parse the input line, break it into t=v pairs, and extract the values sub parse_input { for ( $i = 0; $i < $len; $i++ ) { # Begin loop for each input line $t = 0; $v = 0; ($t,$v) = split(/=/,$pairs[$i]); # Splits pair on "=" (a = b) if ( $str[$i] =~ /\/\// ) { # Ignore comment line w/ 2 slashes $t = $t; } elsif ( $t =~ /type\b/i ) { # Tests for "type = ..." $gtype = $v; } elsif ( $t =~ /\bx\b/i ) { # Tests for "x = ..." $x = $v*0.04; } elsif ( $t =~ /\by\b/i ) { $y = $v*0.04; } elsif ( $t =~ /\bz\b/i ) { $z = $v*0.04; } elsif ( $t =~ /\bmax\b/i ) { $max = $v*0.04; } elsif ( $t =~ /\bspan\b/i ) { $span = $v; } elsif ( $t =~ /thick/i ) { $thickness = $v*0.04; } elsif ( $t =~ /color\b/i ) { $clr = $v; } elsif ( $t =~ /width\b/i ) { $width = $v*0.04; } elsif ( $t =~ /height\b/i ) { $height = $v*0.04; } elsif ( $t =~ /radius\b/i ) { $radius = $v*0.04; } elsif ( $t =~ /size\b/i ) { $size = $v*0.04; } elsif ( $t =~ /string\b/i) { $str = $v; } elsif ( $t =~ /grid\b/i) { $grid = $v; } elsif ( $t =~ /name\b/i) { $a_name = $v; $a_name =~ s/(^\s*)(\w)/$2/; # Suppress leading blanks $a_name =~ s/(\s+)/ /g; # Convert internal blanks } else { # Bad input: invalid syntax or name $Err = 1; } } # End of loop for one line } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Convert color names (e.g., Red, Green, ...) to RGB values sub convert_color { if ( $clr =~ /red/i ) { # Convert color names to R-G-B $rgb = "1 0 0 "; } elsif ( $clr =~ /green/i ) { $rgb = "0 1 0"; } elsif ( $clr =~ /blue/i ) { $rgb = "0 0 1"; } elsif ( $clr =~ /cyan/i ) { $rgb = "0 1 1"; } elsif ( $clr =~ /magenta/i ) { $rgb = "1 0 1"; } elsif ( $clr =~ /yellow/i ) { $rgb = "1 1 0"; } elsif ( $clr =~ /white/i ) { $rgb = "1 1 1"; } elsif ( $clr =~ /black/i ) { $rgb = "0 0 0"; }; } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Carry out all operations (except grid lines) for the axes sub process_axes { $range = $max - $min; $range = $range < 0 ? -$range : $range; $midpoint = $range/2.0; $shft = $min + $midpoint; if ( $gtype =~ /x-axis/i ) { # Print VRML controls for X-axis $Xgrid = $grid; $Xrange = $range; # Save values for grid lines $Xmin = $min; $Xmax = $max; $Xrgb = $rgb; $Xthickness = $thickness; $Xshft = $shft; print "Transform { \n"; print " translation $shft 0 0 \n"; print " rotation 0 0 1 1.5708 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Cylinder { height $range radius $thickness } \n"; print " } \n"; print "} \n"; $txtsize = 7.0*$thickness; # Add axis annotation $span =~ s/(^\s*)(\w)/$2/; # Suppress leading blanks $legend = 1.1 * $max; if ( $a_name ne "" ) { $axisStr = $a_name . ":" . $span; } else { $axisStr = "X:" . $span; # (so no leading spaces) } $axisStr = '"' . $axisStr . '"'; # Enclose in quotes print "Transform { \n"; print " translation $legend 0 0 \n"; print " scale $txtsize $txtsize $txtsize \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Text { string $axisStr } \n"; print " } \n"; print "} \n"; } if ( $gtype =~ /y-axis/i ) { # Print VRML controls for Y-axis # Save values for grid lines $Ygrid = $grid; $Yrange = $range; $Ymin = $min; $Ymax = $max; $Yrgb = $rgb; $Ythickness = $thickness; $Yshft = $shft; print "Transform { \n"; print " translation 0 $shft 0 \n"; print " rotation 0 0 1 0 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Cylinder { height $range radius $thickness } \n"; print " } \n"; print "} \n"; $txtsize = 7.0*$thickness; # Add axis annotation $span =~ s/(^\s*)(\w)/$2/; # Suppress leading blanksr $legend = 1.1 * $max; if ( $a_name ne "" ) { $axisStr = $a_name . ":" . $span; } else { $axisStr = "Y:" . $span; # (so no leading spaces) } $axisStr = '"' . $axisStr . '"'; # Enclose in quotes print "Transform { \n"; print " translation 0 $legend 0 \n"; print " scale $txtsize $txtsize $txtsize \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Text { string $axisStr } \n"; print " } \n"; print "} \n"; } if ( $gtype =~ /z-axis/i ) { # Print VRML controls for Z-axis # Save values for grid lines $Zgrid = $grid; $Zrange = $range; $Zmin = $min; $Zmax = $max; $Zrgb = $rgb; $Zthickness = $thickness; $Zshft = $shft; print "Transform { \n"; print " translation 0 0 $shft \n"; print " rotation 1 0 0 1.5708 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Cylinder { height $range radius $thickness } \n"; print " } \n"; print "} \n"; $txtsize = 7.0*$thickness; # Add axis annotation $span =~ s/(^\s*)(\w)/$2/; # Suppress leading blanks $legend = 1.1 * $max; if ( $a_name ne "" ) { $axisStr = $a_name . ":" . $span; } else { $axisStr = "Z:" . $span; # (so no leading spaces) } $axisStr = '"' . $axisStr . '"'; # Enclose in quotes print "Transform { \n"; print " translation 0 0 $legend \n"; print " scale $txtsize $txtsize $txtsize \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Text { string $axisStr } \n"; print " } \n"; print "} \n"; } } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Write out VRMK controls for the data values sub process_data { if ( $gtype =~ /sphere/i ) { print "Transform { \n"; print " translation $x $y $z \n"; print " rotation 0 0 1 0 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Sphere { radius $radius } \n"; print " } \n"; print "} \n"; } if ( $gtype =~ /cone/i ) { print "Transform { \n"; print " translation $x $y $z \n"; print " rotation 0 0 1 0 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Cone { bottomRadius $width height $height \n"; print " side TRUE} \n"; print " } \n"; print "} \n"; } if ( $gtype =~ /box/i ) { print "Transform { \n"; print " translation $x $y $z \n"; print " rotation 0 0 1 0 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Box { size $size $size $size } \n"; print " } \n"; print "} \n"; } # Print VRML controls for text string if ( $gtype =~ /text/i ) { $str =~ s/(^\s*)(\w)/$2/; # Suppress leading blanks $str =~ s/(\s+)/ /g; # Convert internal blanks to _ $str = '"' . $str . '"'; # Enclose in quotes print "Transform { \n"; print " translation $x $y $z \n"; print " scale $size $size $size \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Text { string $str } \n"; print " } \n"; print "} \n"; } if ( $gtype =~ /cylinder/i ) { print "Transform { \n"; print " translation $x $y $z \n"; print " rotation 0 0 1 0 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $rgb } } \n"; print " geometry Cylinder { height $height radius $width } \n"; print " } \n"; print "} \n"; } } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Create grid lines for each of the axes. Note that we must have the values # for all of the axes, because the grid lines for the X-axis depend on # the Z-axis, the values for the Y-axis depend on the values for the # X-axis, and so on. sub make_gridlines { # Grid lines for X-axis if ( $Xgrid > 0 ) { # Distance between Grid lines $delt = $Xrange/$Xgrid; } $Gthick = $Xthickness/3.0; # Thickness of grid lines for ( $j = 0; $j < $Xgrid + 1; $j++ ) { # Loop for grid lines if ( $Xgrid == 0 ) { last; } $dshft = $Xmin + $j * $delt; print "Transform { \n"; print " translation $dshft 0 $Zshft \n"; print " rotation 1 0 0 1.5708 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $Xrgb } } \n"; print " geometry Cylinder { height $Zrange radius $Gthick} \n"; print " } \n"; print "} \n"; } # Grid lines for Y-axis if ( $Ygrid > 0 ) { # Distance between Grid lines $delt = $Yrange/$Ygrid; } $Gthick = $Ythickness/3.0; # Thickness of grid lines for ( $j = 0; $j < $Ygrid + 1; $j++ ) { # Loop for grid lines if ( $Ygrid == 0 ) { last; } $dshft = $Ymin + $j * $delt; print "Transform { \n"; print " translation $Xshft $dshft 0 \n"; print " rotation 0 0 1 1.5708 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $Yrgb } } \n"; print " geometry Cylinder { height $Xrange radius $Gthick} \n"; print " } \n"; print "} \n"; } # Grid lines for Z-axis if ( $Zgrid > 0 ) { # Distance between Grid lines $delt = $Zrange/$Zgrid; } $Gthick = $Zthickness/3.0; # Thickness of grid lines for ( $j = 0; $j < $Zgrid + 1; $j++ ) { # Loop for grid lines if ( $Zgrid == 0 ) { last; } $dshft = $Zmin + $j * $delt; print "Transform { \n"; print " translation 0 $Yshft $dshft \n"; print " rotation 0 0 1 0 \n"; print " children Shape { \n"; print " appearance Appearance { material Material { \n"; print " diffuseColor $Zrgb } } \n"; print " geometry Cylinder { height $Yrange radius $Gthick} \n"; print " } \n"; print "} \n"; } } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # Make sure all axis values are available sub check_for_errors { if ( ($Xmax <= $Xmin) || ($Ymax <= $Ymin) || ($Zmax <= $Zmin) ) { print STDERR " ERROR: some axis values are invalid \n"; } } # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv