Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl -w
- use Math::Trig;
- use POSIX qw/ceil/;
- ##
- # PEEVE 2(To) Turtle
- # Converts a PEEVE script to a Turtle Script.
- ##
- #FILENAME Variables
- $FILE=$ARGV[0];
- $FILEEXT=$FILEEXT= ($ARGV[0] =~ /([^.]+)$/)[0];
- $FILEOUT=0; #If 0, print to stdOut, if 1, print to file specified by ARGV[1]
- #Initalisation checks
- #Check to see if there is at least 1 argument
- if($FILEEXT ne "peeve")
- {
- #Print error message and close if there is no arguments
- print("Invalid filetype in file argument.");
- exit;
- }
- if($#ARGV == 1)
- {
- $FILEOUT=1;
- }
- #Turtle Variables
- $xPos=200; #The current x position of the turtle
- $yPos=200; #The current y position of the turtle
- $dir=0; #The direction in degrees, that the turtle is facing.
- #File Variables
- $lineCount=0; #Keeps track of what line in the file we're at. Used for error checking.
- #---Main---#
- #Open the file, or close if not found.
- if($#ARGV < 0)
- {
- $FILE=*STDIN;
- }
- else
- {
- open(FILE) or die("File not found.");
- }
- #@output is the array which holds the text to be written to the svg file.
- #Add the header information onto the output
- #Iterate through the file line by line
- foreach $line (<FILE>)
- {
- $lineCount=$lineCount + 1;
- preProc($line);
- @line = split(' ', $line);
- if($line ne "\n")
- {
- #Check syntax
- checkSyntax(@line);
- }
- if(@line[0] eq "LINE")
- {
- drawLine(@line[1], @line[2], @line[3], @line[4]);
- }
- elsif(@line[0] eq "POLYGON")
- {
- drawPolygon(@line[1], @line[2], @line[3], @line[4],@line[5]);
- }
- elsif(@line[0] eq "CIRCLE")
- {
- drawCircle(@line[1], @line[2], @line[3]);
- }
- #Else we have style commands.
- else
- {
- push(@output, $line);
- }
- }
- #Output to file
- if($FILEOUT == 1)
- {
- open(MYFILE, ">${ARGV[1]}.turtle");
- print MYFILE @output;
- close(MYFILE);
- }
- else
- {
- print @output;
- }
- #Draws line
- #Accepts 4 arguments:
- #Starting Coordinates x1,y1
- #Ending Coordinates x2, y2
- sub drawLine
- {
- #Move to start coordinates
- moveTurtle($xPos, $yPos, @_[0], @_[1]);
- #PENDOWN
- push(@output, "PENDOWN\n");
- moveTurtle(@_[0], @_[1], @_[2], @_[3]);
- #PENUP
- push(@output, "PENUP\n");
- }
- #Draws polygon
- sub drawPolygon
- {
- $init_angle=@_[2];
- $n_sides=@_[3];
- $side_length=@_[4];
- #Calculate turning angle
- $turningAngle=180-((180*($n_sides-2))/($n_sides));
- #Move to start coordinates
- moveTurtle($xPos, $yPos, $_[0], $_[1]);
- #Rotate to init_angle
- rotate($init_angle);
- #PENDOWN
- push(@output, "PENDOWN\n");
- #Give our turtle a little workout
- for($count = 0; $count < $n_sides; $count++)
- {
- push(@output, "FORWARD ${side_length}\n");
- rotate($dir+$turningAngle);
- }
- #PENUP
- push(@output, "PENUP\n");
- }
- #Draws circle
- sub drawCircle
- {
- $radius=@_[2];
- $circumference=2*$radius*pi;
- #Polygon variables
- $init_angle=0;
- #Calculate number of sides. If the radius is less than 4, the side length must also be calculated.
- if($radius < 4)
- {
- $side_length=2*$radius*sin(deg2rad(22.5));
- $n_sides = 8; #Minimum of 8 sides.
- }
- else
- {
- $side_length=3; #This is the maximum side length allowed.
- $n_sides = ((360) / (2 * rad2deg(asin(1.5/$radius))));
- #$n_sides = ceil($circumference / 3)
- }
- #Move turtle to the start + the radius to the left and half side length down
- moveTurtle($xPos, $yPos, ($_[0]-$radius), ($_[1]+($side_length/2)));
- #Start position is our current position, since we moved here above.
- #Call drawPolygon to draw the circle.
- drawPolygon($xPos, $yPos, 0, $n_sides, $side_length);
- }
- #Moves the turtle from point A to point B
- sub moveTurtle
- {
- $x1=@_[0];
- $y1=@_[1];
- $x2=@_[2];
- $y2=@_[3];
- $angle=0;
- $forwardLength=0;
- #If we're moving to the right
- if($x2 > $x1)
- {
- print "In first/second quad";
- #If we're moving up (First Quadrant)
- if($y2 > $y1)
- {
- print "First Quad\n";
- $angle=rad2deg(atan(($y2-$y1)/($x2-$y1)));
- #Rotate the turtle
- rotate(($angle + 90));
- #Pythagoras to get length of forward
- $forwardLength=sqrt((($x2-$x1)** 2) + (($y2-$y1)**2));
- push(@output, "FORWARD ${forwardLength}\n");
- }
- #If we're moving up (Second Quadrant)
- elsif($y1 > $y2)
- {
- print "Second Quad\n";
- $angle=rad2deg(atan(($x2-$x1)/($y1-$y2)));
- rotate($angle);
- #Pythagoras to get length of forward
- $forwardLength=sqrt((($x2-$x1)** 2) + (($y1-$y2)**2));
- push(@output, "FORWARD ${forwardLength}\n");
- }
- #We're moving to the right directly on the x axis.
- elsif($y1 == $y2)
- {
- print "Direct Right\n";
- #Rotate to 90 degrees (EAST)
- rotate(90);
- push(@output, "FORWARD @{[$x2-$x1]}\n");
- }
- }
- #If we're moving to the left
- elsif($x1 > $x2)
- {
- #If we're moving up (Third)
- if($y2 > $y1)
- {
- print "Fourth Quad\n";
- $angle=rad2deg(atan(($x1-$x2)/($y2-$y1)));
- rotate(($angle + 180)); #Add 180 as offset to Fourth Quadrant
- #Pythagoras to get length of forward
- $forwardLength=sqrt((($x1-$x2)** 2) + (($y2-$y1)** 2));
- push(@output, "FORWARD ${forwardLength}\n");
- }
- #If we're moving up (Third Quadrant)
- elsif($y1 > $y2)
- {
- print "Third Quad\n";
- $angle=rad2deg(atan(($y1-$y2)/($x1-$x2)));
- rotate(($angle + 270)); #Add 270 as offset to Third Quadrant
- #Pythagoras to get length of forward
- $forwardLength=sqrt((($x1-$x2)** 2) + (($y1-$y2)** 2));
- push(@output, "FORWARD ${forwardLength}\n");
- }
- #We're moving to the left directly on the x axis.
- else
- {
- print "Direct Left\n";
- #Rotate to 270 degrees (WEST)
- rotate(270);
- push(@output, "FORWARD @{[$x1-$x2]}\n");
- }
- }
- #We're moving directly up or down the y axis.
- else
- {
- #Move down
- if($y2 > $y1)
- {
- print "Direct Up\n";
- rotate(180); #Rotate to 0 degrees
- push(@output, "FORWARD @{[$y2-$y1]}\n");
- }
- #Move up
- elsif($y1 > $y2)
- {
- rotate(0); #Rotate to 180 degrees
- push(@output, "FORWARD @{[$y1-$y2]}\n");
- }
- #May as well account for all possibilities.
- else
- {
- #No change in position, really?
- }
- }
- $xPos = $x2;
- $yPos = $y2;
- }
- #Preprocesses the lines read from the peeve script.
- #Chops new lines and comments.
- sub preProc
- {
- #Remove comments
- $_[0] =~ s/#.*$//;
- }
- #Used for smart rotations of the turtle.
- #Accepts the new direction the turtle will face as parameter.
- sub rotate
- {
- $newDir=@_[0];
- if($dir != $newDir)
- {
- #Make smart turns :D
- if($dir > $newDir)
- {
- if(($dir - $newDir) > 180)
- {
- push(@output, "RIGHT @{[360 - $dir + $newDir]}\n");
- }
- else
- {
- push(@output, "LEFT @{[$dir - $newDir]}\n");
- }
- }
- else
- {
- if(($newDir - $dir) > 180)
- {
- push(@output, "LEFT @{[$dir + 360-$newDir]}\n");
- }
- else
- {
- push(@output, "RIGHT @{[$newDir - $dir]}\n");
- }
- }
- $dir = $newDir;
- }
- }
- sub checkSyntax
- {
- #TODO: Check each invidual argument...
- @lineRead=@_;
- $lineLength = @lineRead;
- #Check command
- if(@lineRead[0] ne "LINE" and @lineRead[0] ne "POLYGON" and @lineRead[0] ne "CIRCLE" and @lineRead[0] ne "SETSTYLE" and @lineRead[0] ne "DEFINESTYLE")
- {
- print "Syntax error (Invalid Command: ${lineRead[0]}) at line ${lineCount} of ${FILE}. Terminating execution.\n";
- exit;
- }
- if(@lineRead[0] eq "LINE" and $lineLength != 5)
- {
- print "Syntax error at line (Invalid Arguments) ${lineCount} of ${FILE}.\n Terminating execution.\n";
- exit;
- }
- elsif(@lineRead[0] eq "POLYGON" and $lineLength != 6)
- {
- print "Syntax error at line (Invalid Arguments) ${lineCount} of ${FILE}.\n Terminating execution.\n";
- exit;
- }
- elsif(@lineRead[0] eq "CIRCLE" and $lineLength != 4)
- {
- print "Syntax error at line (Invalid Arguments) ${lineCount} of ${FILE}.\n Terminating execution.\n";
- exit;
- }
- }
Add Comment
Please, Sign In to add comment