#!/usr/local/bin/perl # # this is flip.pl # # written by Matthew Conroy (doctormatt "at" madandmoonly.com) # # December 1999 # # do whatever you want to with this program; if you find it # useful or make improvements I'd love to hear about it # print "This is flipbook.pl.\n\n"; ### get starting string print"starting string: "; $start_string=; chop($start_string); $length_start_string = length($start_string); ### get ending string print("ending string: "); $end_string = ; chop($end_string); # note: ending string might not have same length as starting string (due to spaces) print "\n"; print "The script will now list the initial position of each letter.\n"; print "If that letter only appears once in the ending string, then its\n"; print "ending position is determined; if the letter appears more than\n"; print "once, you will be asked to choose from among the possible ending\n"; print "positions for the letter. A letter in parenthesis following a \n"; print "position indicates that another of the same letter is in that \n"; print "position initially.\n\n"; ### determine/get permutation: the position in the final ### string corresonding to each letter of the starting string print "initial position / letter / ending position\n"; for($i=0; $i<$length_start_string; ++$i) { $letter = substr($start_string,$i,1); local @letter_positions; if ($letter !~ /\s/) { ### do this if the letter's not a space for($j=0; $j < length($end_string); ++$j) { push @letter_positions, $j if ((substr($end_string,$j,1) eq $letter) && (not $used_positions{$j})); } if (scalar(@letter_positions)==0) { print "The letter $letter doesn't appear in the ending string!"; exit; } elsif (scalar(@letter_positions)==1) { print $i," ",$letter," ",$letter_positions[0],"\n"; $end_pos[$i] = $letter_positions[0]; $used_positions{$end_pos[$i]} = 1; } else { ### more than one of $letter in $end_string print $i," ",$letter," ("; foreach(@letter_positions) { $lp = $_; unless ($used_positions{$lp}) { print " ",$lp; if (substr($start_string,$lp,1) eq $letter) { print "($letter)"; } } } print ") ? "; $position_choice = ; chop($position_choice); $end_pos[$i] = $position_choice; $used_positions{$end_pos[$i]}=1; } } } ### get number of frames print"number of frames: "; $num_frames=; chop($num_frames); ### ask if frame number wanted print "\nYou can choose to have the frame number \n"; print "printed in the lower left corner of each frame.\n"; print"This can be helpful if the frames get mixed up after\n"; print "cutting them from the pages.\n\n"; print "print frame number on each frame? "; $query = ; if ($query =~ /^y/i) { $print_frame_number =1; } else { $print_frame_number =0; } ### ask if separate page for each frame print "\nWhen you have the final version, and want to print\n"; print "the frames to paper, you should print on as few pages\n"; print "as possible. However, to preview the animation of the\n"; print "flipbook, you should give each frame its own page,\n"; print "so that you can step through the pages in your DVI\n"; print "viewer, and see the animation.\n\n"; print "Each frame on its own page? "; $query = ; if ($query =~ /^y/i) { $separate_pages = 1; } else { $separate_pages = 0; } ### ask for output file name print "\nOutput file name (default is flip.tex):"; $query = ; chop($query); if ($query !~ /\w/) { $out_filename = "flip.tex"; } else { $out_filename = $query; } ### ### Do it ### print "\nHere we go...\n"; ### some settings $latex_font = "\\ttfamily"; $letter_width = 3; $latex_letter_size = "\\tiny"; # for tiny, width=3 works well $box_width=200; #$box_width = ($length_start_string + 1)*$letter_width*1.1; $box_height=75; #$box_height = $box_width; $enclosing_box = 1; ### 1=yes, 0=no $x_shift = $box_width - $letter_width*(max($length_start_string,length($end_string))+3) ; $y_shift = $box_height/2 - $letter_width/2; ### create coordinates for spline - ### what we have here is the signed width and height ### of the 'frame' which defines the spline ### which is the path for each letter for ($i=0; $i < $length_start_string; ++$i) { $width[$i] = $letter_width * ($end_pos[$i]-$i); $height[$i] = $width[$i]; push @heights,abs($height[$i]); $initial_x[$i] = $letter_width * $i; $final_x[$i] = $letter_width * $end_pos[$i]; } if (max(@heights)>0.5*$box_height) { $scaling_factor = 0.5*$box_height/max(@heights); for ($i=0; $i < $length_start_string; ++$i) { $height[$i] *= $scaling_factor; } } ### create the LaTeX file open(OUT,">$out_filename") || die; # making LaTeX header print OUT "\\documentclass[11pt]{report}\n"; print OUT "\\pagestyle{empty}\n"; print OUT "\\addtolength{\\oddsidemargin}{-1.5in}\n"; print OUT "\\addtolength{\\evensidemargin}{-1.5in}\n"; print OUT "\\addtolength{\\textwidth}{2.5in}\n"; print OUT "\\addtolength{\\topmargin}{-1.0in}\n"; print OUT "\\addtolength{\\textheight}{2.0in}\n"; print OUT "\\begin{document}\n"; print OUT "$latex_font\n"; ## use fixed width font print OUT "$latex_letter_size\n"; ### use a little smaller text ### do the frames for ($frame=1; $frame<=$num_frames; ++$frame) { $t = ($frame-1)/($num_frames-1); print " Frame $frame \n"; print OUT "\\begin{picture}($box_width,$box_height)(0,0)\n"; if ($enclosing_box) { print OUT "\\put(0,0){\\line(0,1){$box_height}}\n"; print OUT "\\put(0,0){\\line(1,0){$box_width}}\n"; print OUT "\\put(0,$box_height){\\line(1,0){$box_width}}\n"; print OUT "\\put($box_width,0){\\line(0,1){$box_height}}\n"; $box_height_sub = $box_height-2; $box_width_sub = $box_width-2; print OUT "\\put(2,0){\\line(0,1){$box_height}}\n"; print OUT "\\put(0,2){\\line(1,0){$box_width}}\n"; print OUT "\\put(0,$box_height_sub){\\line(1,0){$box_width}}\n"; print OUT "\\put($box_width_sub,0){\\line(0,1){$box_height}}\n"; if ($print_frame_number) { print OUT "\\put(4,4){$frame}\n"; } } ### calculate coordinates for each letter, and print it for ($character=0; $character<$length_start_string; ++$character) { $letter = substr($start_string,$character,1); $x = $x_shift + &cubic($t,$initial_x[$character],$initial_x[$character], $final_x[$character], $final_x[$character]); $y = $y_shift + + &cubic($t,0,$height[$character],$height[$character],0); #print $letter," ",$x," ",$y,"\n"; $x = int $x; $y = int $y; ### put the letter in the TeX file print OUT "\\put($x,$y){$letter}\n"; } ### end for (character) ### end the picture environment print OUT "\\end{picture}\n\\hspace{0.25in}\n"; ### if it was an even frame, start a new "line" print OUT "\\bigskip\n\n" if (($frame % 2)==0); ### if $separate pages is true, start a new page print OUT "\\clearpage\n\n" if ($separate_pages); } ### end for (frame) # make final statement in LaTeX file print OUT "\\end{document}\n"; print "Done!\n"; ############################################################################### #################################### # # Subroutines # #################################### sub cubic { local $t = @_[0]; local $z1 = @_[1],$z2 = @_[2],$z3 = @_[3],$z4 = @_[4]; #print "... $z1 $z2 $z3 $z3 \n"; return((1-$t)**3*$z1 + 3*(1-$t)**2*$t*$z2 + 3*(1-$t)*($t**2)*$z3+($t**3)*$z4); } sub min { my $min = shift(@_); foreach $foo (@_) { $min = $foo if $foo<$min; } return $min; } sub max { my $max = shift(@_); foreach $foo (@_) { $max = $foo if $foo>$max; } return $max; } sub abs { if ($_>=0) { return($_); } else { return(-$_); } }