1: =pod
   2: Well, I was bored the other day and started playing around with one of the silly pastimes that I
   3: amuse myself with (ASCII art).  Then I thought, "Hey, I can incorporate another one of the things
   4: I amuse myself with!"  That was Perl, and so I started fiddling aroud with Perl scripts to make
   5: ASCII Art.  Then I though, "Hey, I can incorporate another one of the things I amuse myself with!"
   6: That was n-dimensional geometry, and that was also 4 days ago.  This is the net-result.
   7: 
   8: Just run this little puppy, and it will happily print out objects up to 6 dimensions.  It can
   9: only draw cubes, and at the moment it can't go higher than 6 dimensions (since there aren't many
  10: characters after that that look good unless you want to duplicate things)
  11: 
  12: I'm sure this could be written more prettily, compactly, extensibly, and so on.  It's fairly dumb
  13: at the moment.  But gosh-darn it, it does do this one thing pretty well.
  14: 
  15: And I just *know* that you've been dying to see an ASCII hyper cube, so take a look at it.  :)
  16: 
  17: The thing that I'm most pleased with, is that they're actually drawn by their mathematical definitions.
  18: So a point is zero dimensional, a line is a moving point, a plane a moving line, and so on.  It 
  19: places the objects and then connects them to form the next higher dimension.  No lame-o caching
  20: of previously created ASCII for me!  No sir.
  21: 
  22: If, for some arcane reason, someone wants a more robust version of this thing, I may look into it.  But,
  23: realistically, such endeavors are best left as an exercise for the reader.  ;)
  24: 
  25: More intelligent methods to add are the ability to have more complex objects, the difference between
  26: 'front' and 'back' and a couple of other things.  I'll email ideas I have about it, if you'd like, but
  27: otherwise the weekend is over and I'm done with this little diversion.
  28: 
  29: =cut
  30: 
  31: use strict;
  32: 
  33: #define the ascii characters for each direction
  34: my @hor = qw(- =);
  35: my @ver = qw(| !);
  36: my @ud  = qw(/);
  37: my @dd  = qw(\\);
  38: 
  39: #create our universe
  40: make_space();
  41: 
  42: #well, a zero dimensional object is a point
  43: my $point = "+";        
  44: 
  45: #take a point,
  46: place_in_space($point, 0, 0);  
  47: #move it somewhere else,
  48: place_in_space($point, 7,0);  
  49: #and draw a line between them, and you have:
  50: make_path();          
  51: 
  52: #a one dimensional object (a line)
  53: my $line = space_rip();      
  54: 
  55: #take a line,
  56: place_in_space($line, 4, 5);  
  57: #move it somewhere else,
  58: place_in_space($line, 4, 10);  
  59: #and draw a line between them, and you have:
  60: make_path();          
  61: 
  62: #a two dimensional object (a square)
  63: my $square = space_rip();    
  64: 
  65: #take a square,
  66: place_in_space($square, 4, 5);  
  67: #move it somwhere else,
  68: place_in_space($square, 7, 8);  
  69: #and draw a line between them, and you have:
  70: make_path();          
  71: 
  72: #a three dimensional object (a cube)
  73: my $cube = space_rip();      
  74: 
  75: #take a cube,
  76: place_in_space ($cube,5,12);  
  77: #move it somewhere else,
  78: place_in_space ($cube,15,2);   
  79: #and draw a line between them, and you have:
  80: make_path();          
  81: 
  82: #a four dimensional object (a hyper cube)
  83: my $hypercube = space_rip();  
  84: 
  85: #take a hypercube,
  86: place_in_space($hypercube, 5, 12);  
  87: #move it somewhere else,
  88: place_in_space($hypercube, 30, 12);  
  89: #and draw a line between them, and you have:
  90: make_path();            
  91: 
  92: #a five dimensional object (hyper hyper cube)
  93: my $cube5d = space_rip();      
  94: 
  95: #take a 5d cube,
  96: place_in_space($cube5d, 5, 12);    
  97: #move it somewhere else,
  98: place_in_space($cube5d, 5, 34);    
  99: #and draw a line between them, and you have:
 100: make_path();            
 101: 
 102: #a six dimensional object (hyper hyper hyper cube)
 103: my $cube6d = space_rip();      
 104: 
 105: #and we'll just stop at 6 dimensions, what with 
 106: #the lack of good ascii characters and all...
 107: 
 108: #let's see what we made!
 109: 
 110: print "=====\nPoint:\n=====\n\n$point\n\n=====\n\n\n";
 111: print "=====\nLine:\n=====\n$line\n\n=====\n\n\n";
 112: print "=====\nSquare:\n=====\n$square\n\n=====\n\n\n";
 113: print "=====\nCube:\n=====\n$cube\n\n=====\n\n\n";
 114: print "=====\nHyper Cube:\n=====\n$hypercube\n\n=====\n\n\n";
 115: print "=====\n5d Cube:\n=====\n$cube5d\n\n=====\n\n\n";
 116: print "=====\n6d Cube:\n=====\n$cube6d\n\n=====";              
 117: 
 118: BEGIN {
 119: 
 120:   my @space = ();
 121: 
 122:   sub make_space () {
 123:     foreach my $x (0..100){
 124:       foreach my $y (0..100){
 125:         $space[$x]->[$y] = " ";
 126:       };
 127:     };
 128:   };
 129:   
 130:   my %space  = ();
 131:   my $which  = 0;
 132:   my $node   = 0;
 133:   my $min_x = 10000;
 134:   
 135:   sub place_in_space {
 136:     my ($cube, $x, $y) = @_;
 137:     
 138:     $min_x = $x if $x < $min_x;
 139:     
 140:     my @cube = map {[split // ]} split(/\n/,$cube);
 141:     
 142:     my $node = 0;
 143:     
 144:     foreach (@cube){
 145:       foreach my $z (0..$#$_){
 146:         next if $_->[$z] =~ /^\s*$/;
 147:         my $i = $x + $z;
 148:         $space[$y]->[$i] = $_->[$z];
 149:         $space{"space" . $which . "p" . $node++} 
 150:           = [$y, $i] if $_->[$z] eq "+";
 151:       };
 152:       $y++;
 153:     };
 154:     
 155:     $which++;
 156:     
 157:   };
 158:   
 159:   sub space_rip() {
 160:     my $rip = undef;
 161:     foreach (@space){
 162:       my $dim = join ("", @$_);
 163:       next if $dim =~ /^\s*$/;
 164:       $dim =~ s/(^\s{$min_x}|\s+$)//g;
 165:       $rip .= "\n$dim";
 166:     };
 167:     make_space();
 168:     $min_x = 100000;
 169:     return $rip;
 170:   };
 171:   
 172:   sub make_path() {
 173:     my $htoken = shift @hor;
 174:     my $vtoken = shift @ver;
 175:     my $utoken = shift @ud;
 176:     my $dtoken = shift @dd;
 177:     my ($use_h, $use_v, $use_ud, $use_dd) = (0,0,0,0);
 178:     foreach my $cube (0..$which){
 179:       my $node = 0;
 180:       
 181:       while (defined (my $alpha_node = 
 182:           $space{"space" . $cube . "p" . $node})){
 183:         my $cube2 = $cube + 1;
 184:         my $beta_node = 
 185:           $space{"space" . $cube2 . "p" . $node} or last;
 186:         
 187:         my ($ax, $ay) = @$alpha_node;
 188:         my ($bx, $by) = @$beta_node;
 189:         
 190:         
 191:         my $max_y = max($ay, $by);
 192:         my $min_y = min($ay, $by);
 193:         
 194:         my $max_x = max($ax, $bx);
 195:         my $min_x = min($ax, $bx);
 196:       
 197:         if ($ax == $bx){  #horizontal
 198:           $use_h++;
 199:           foreach (1..($max_y - $min_y - 1)){
 200:             $space[$ax]->[$min_y + $_] = $htoken
 201:               unless $space[$ax]->[$min_y + $_] 
 202:                 =~ /[$htoken@hor+]/o;
 203:           };
 204:         }
 205:         elsif ($ay == $by){  #vertical
 206:           $use_v++;
 207:           foreach (1..($max_x - $min_x - 1)){
 208:             $space[$min_x + $_]->[$ay] = $vtoken
 209:               unless $space[$min_x + $_]->[$ay] 
 210:                 =~ /[$vtoken@ver+]/o;
 211:           };
 212:         }
 213:         elsif ($by > $ay && $bx > $ax) {  #down diagonal
 214:           return undef unless delta($ax, $bx) == 
 215:             delta($ay, $by);
 216:           $use_dd++;
 217:           foreach (1..($max_x - $min_x - 1)){
 218:               $space[$min_x + $_]->[$min_y + $_] = $dtoken
 219:                 unless $space[$min_x + $_]->[$min_y + $_] 
 220:                   =~ /[$dtoken@dd+]/o;
 221:           };
 222:         }
 223:         else {        #up diagonal
 224:           return undef unless delta($ax, $bx) == 
 225:             delta($ay, $by);
 226:           $use_ud++;
 227:           foreach (1..($max_x - $min_x - 1)){
 228:               $space[$min_x + $_]->[$max_y - $_] = $utoken
 229:                 unless $space[$min_x + $_]->[$max_y - $_] 
 230:                   =~ /[$utoken@ud+]/o;
 231:           };
 232:         };
 233:         delete $space{"space" . $cube2 . "p" . $node};
 234:         delete $space{"space" . $cube . "p" . $node};
 235:         $node++;
 236:       };
 237:     };
 238:     
 239:     unshift @hor, $htoken unless $use_h;
 240:     unshift @ver, $vtoken unless $use_v;
 241:     unshift @dd, $dtoken unless $use_dd;
 242:     unshift @ud, $utoken unless $use_ud;
 243:   };
 244:   
 245:   sub max {
 246:     my ($a, $b) = @_;
 247:     return $a > $b ? $a : $b;
 248:   };
 249:   
 250:   
 251:   sub min {
 252:     my ($a, $b) = @_;
 253:     return $a > $b ? $b : $a;
 254:   };
 255:   
 256:   
 257:   sub delta {
 258:     my ($a, $b) = @_;
 259:     return abs($a - $b);
 260:   };
 261: };
 262: 

Replies are listed 'Best First'.
(Ovid) RE: perl in multiple dimensions
by Ovid (Cardinal) on Sep 11, 2000 at 19:47 UTC
    I love it! This reminds me of one of my first big programming projects. I was in high school back in '84 and fascinated by non-non-Euclidean geometry, topology, and the like. I found a program written in BASIC for the Apple II e that would display 3-D graphs with hidden-line removal. I rewrote the primary algorithms to display a hypercube and rotate it. Needless to say, that kind of mathematical number crunching on an Apple II e was basically useless and I had to give up. Thanks for bringing back memories!

    Incidentally, how would you do hidden-line removal on an n-dimensional object with n>3? Would you have to adopt the perspective of an n-dimensional entity? If anyone cares to tackle that question, be gentle with me. My math skills are a little rusty :)

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just go the the link and check out our stats.

    Update: jimt's response below is one of the funniest posts that I have read in quite a while :)

      I see Ovid corrected it, but I think his *original* post was much much funnier:

      I found a program written in BASIC for the Apple II e that would display 3-D graphs with hidden-line removal. I rewrote the primary algorithms to display a hypercube and rotate it. Needless to sayServer Error(Error Id 4592402)!

      The Server Error was due to the brackets, I'm assuming, but the error occurred in the absolute best possible place in his post. :) It reads absolutely perfectly. (I did change the brackets to I's, to get it to post correctly)