#!/usr/bin/perl # # Usage: perl splitspeck.pl speckfile # # Splits the data points in speckfile based on texturevar into several # different .speck files # Creates files speckfilename_x.speck, for all possible texturevar values x. # # Usage2: perl splitspeck.pl speckfile cffile # # As before, but also creates a new .cf file (called new_$cffile) # based on cffile that deals with the splits. # # You dont have to specify the number of files to be split into # It works that out from the number of texture you define in speckfile # (so you probably dont want to have extra textures that you never use) # # Usage3: perl splitspeck.pl speckfile cffile newcffile # # As with usage2, but you specify the name of the new .cf file. # # # Dinoj Surendran, dinoj@cs.uchicago.edu, 29 February 2004 # # No small furry creatures were harmed during the writing of this code. # They would have been if I had better aim. # # # This code has not been polished! I've got too many other things to do tonight, # and I don't wanna see this code any other night. or any other day, for that matter. use FileHandle; my $speckfile = new FileHandle; $speckfile->open ("<".$ARGV[0]); # first deal with the .speck file my $txcol = 0; my %FILES; my %datavar; my $speckfilenoext = $ARGV[0]; $speckfilenoext =~s/\.speck//g; my $headerall = ""; my @splitinto = (); # indices (texture values) this speck file is split into... while ($line = <$speckfile>) { chomp $line; @parts = split (/[\t\n ]+/, $line); $start; $txvar = -1; if ($line =~ m/datavar/) { $start = 0; while ($parts[$start] ne "datavar") { $start++; } $datavar{ $parts[$start+1] } = $parts[$start+2] ; $headerall = $headerall.$line."\n"; } # datavar 0 eclass # datavar 1 distmpc # datavar 2 redshift # datavar 3 pictype # datavar 4 ori # -> # $datavar{ "0" } = "eclass" # $datavar{ "1" } = "distmpc" # $datavar{ "2" } = "redshift" # $datavar{ "3" } = "pictype" # $datavar{ "4" } = "ori" elsif ($line =~ m/texturevar/) { while ($parts[$start] ne "texturevar") {$start++;} $txvar = $parts[$start+1]; $txcol = 0; @k = keys (%datavar); while (($txcol <= $#k) && ($datavar{$txcol} ne $txvar)) { $txcol++; } if ($datavar{$txcol} ne $txvar) { print "\nERROR: texturevar is $txvar but there is no datavar like that\n\n"; return; } $txcol = $txcol + 3; $headerall = $headerall.$line."\n"; } elsif ($line =~m/var/) { $headerall = $headerall.$line."\n"; } # # if there's a line " texturevar pictype" # then $txvar is set to "pictype" # and $parts[$txcol] goes through the values "eclass", "distmpc", "redshift" and # finally "pictype" (while $txcol goes through 0, 1, 2, 3 respectively) # $txcol doesnt go to 4 since $txvar="pictype" equals $datavar[3]. elsif ($line =~ m/texture/) { $start = 0; while ($parts[$start] ne "texture") {$start++;} $blend = $parts[$start+1]; $txnum = $parts[$start+2]; $image = $parts[$start+3]; # Example: if $line is # "texture -a 3 shape10.sgi" # then # $blend = "-a" # $txnum = 3 # $image = "shape10.sgi" $fil = sprintf(">%s_%d.speck",$speckfilenoext,$txnum); $splitinto[$#splitinto+1] = $txnum; $FILES[$txnum] = new FileHandle; $FILES[$txnum]->open("$fil") or die ("aagh"); $FILES[$txnum]->printf ("%s",$headerall); $FILES[$txnum]->printf ("texture %s 1 %s\n\n", $blend, $image); # if $speckfile is "blah.speck", this creates blah_3.speck # and writes its headers. # These headers are the same as those in blah.speck before the "texture .." lines # and then the line "texture -a 1 shape10.sgi" # This is the only "texture..." line in blah_3.speck # # $FILES[3] = ptr to write in file blah_3.speck } elsif ( (!($line =~ m/var/)) && ($#parts > 0)) # this must be a data line - we assume it has the right number of numeric entries... { $start = 0; while (isnumeric($parts[$start]) == 0) {$start++;} if (0 == $txcol) # occurs only if no previous line with texturevar. { print "\nERROR! Texture column not determined before data lines start! (Or the texture column specified is wrong...\n\n"; return; } $x = $parts[$start+0]; $y = $parts[$start+1]; $z = $parts[$start+2]; $tx = $parts[$start+$txcol]; # rem $txcol already had 3 added to it # now place this line in $FILES[$tx]. for ($i=$start; $i<$start+$txcol; $i++) { $FILES[$tx]->printf ( " %0.10f", $parts[$i]); } $FILES[$tx]->printf ( " 1"); for ($i=$start+$txcol+1; $i <= $#parts ; $i++) { $FILES[$tx]->printf ( " %0.10f", $parts[$i]); } $FILES[$tx]->printf ("\n"); } else { $headerall = $headerall.$line."\n"; } } $speckfile->close(); # then deal with the .cf file if ($#ARGV < 1) { print "No CF file supplied, so no CF file created.\n"; exit(0); } my $cffile = new FileHandle; $cffile->open ("<".$ARGV[1]); my $newcffile = new FileHandle; if ($#ARGV >= 2) { $newcffile->open (">".$ARGV[2]); } else { $newcffile->open (">new_".$ARGV[1]); } $b4object = ""; # contains all objects b4 the object to be split $b4 = 1; # set to 0 once you've reached the object to be split $inG = 0; # set to 1 once you're in the object # code below also deals with pre-object headers such as filepath statements while ($line = <$cffile>) { chomp $line; if ($line =~m/object/) # start of a new object { $lastobject = $currentobject; $currentobject = $line; if (1 == $in) # just finished object to be split, moving to next { $in = 0; # split up $lastobject for ($j=0; $j <= $#splitinto; $j++) { $_ = $lastobject; ($gnum,$gname) = /object\s+[gG](\d+)\s*=(\w+).*/ ; $newgnum = $gnum + $j; $newgname = $gname."_".$splitinto[$j]; $newspeckfilenoext = $speckfilenoext."_".$splitinto[$j]; $object2Bsplit = $lastobject; $object2Bsplit =~ s/g$gnum\s*=\s*$gname/g$newgnum=$newgname/; $object2Bsplit =~ s/$speckfilenoext\.speck/$newspeckfilenoext\.speck/; $newcffile->printf ("\n$object2Bsplit\n"); } } elsif (1 == $b4) # starting on next object (which might be the object # to be split, or before it) { $newcffile->printf ("\n$lastobject\n"); } else # this is after the object to be split { $_ = $lastobject; ($objnum,$objname) = /object\s+[gG](\d+)\s*=(\w+).*/ ; $newobjnum = $objnum + $#splitinto; $lastobject =~ s/g$objnum\s*=/g$newobjnum=/; $newcffile->printf ("\n$lastobject\n"); } } else # already in an object { $currentobject = $currentobject."\n".$line; } if ($line =~m/$speckfilenoext\.speck/) { $b4 = 0; $in = 1; } } $_ = $currentobject; ($objnum,$objname) = /object\s+[gG](\d+)\s*=(\w+).*/ ; $newobjnum = $objnum + $#splitinto; $currentobject =~ s/g$objnum\s*=/g$newobjnum=/; $newcffile->printf ("\n$currentobject\n"); $newcffile->close(); ###################### sub isnumeric() { my ($x) = @_; if ((0+$x == 0) && (sprintf("%s",sprintf("%d",$x)) ne $x)) {return 0;} else {return 1;} }