123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- module turtle;
- % REDUCE implementation of Turtle Graphics
- % Caroline Cotter, ZIB,Berlin, 1998.
- % The main user commands for drawing pictures follow.
- load_package gnuplot;
- %USER SETTING FUNCTIONS
- % The following allow the user to reset the position of the turtle whilst
- % drawing a %picture - that is, these commands are to be used when the pen is
- % to be lifted and set down at a new point, or to change the direction
- % (heading) of the turtle. Since these do not actually draw anything,
- % nothing is returned. However, in order %to allow a continuous drawing,
- % the latest position of the turtle must be returned
- %(otherwise an error is incurred when trying to plot the points).
- algebraic<<
- procedure setheading(mu); %Redirects the turtle
- begin scalar w;
- w:=if mu=() then heading
- else ck(mu); %remember ck sets between 0 and 360
- heading:=w;
- return {x_coord,y_coord}
- end;
- procedure setx(i); %Relocates the turtle in the x-direction
- begin;
- x_coord:=i;
- return {x_coord,y_coord}
- end;
- procedure sety(j); %Relocates the turtle in the y-direction
- begin;
- y_coord:=j;
- return {x_coord,y_coord}
- end;
- procedure setposition(q); %Repositions the turtle (takes cartesian
- begin; %coordinate as its argument)
- x_coord:=first q;
- y_coord:=second q;
- return {x_coord,y_coord}
- end;
- % Both turnleft and turnright redirect the turtle,
- % dependent on its current direction
- procedure turnleft(gamma);
- begin;
- heading:=ck(heading + gamma);
- return {x_coord,y_coord}
- end;
- procedure turnright(delta);
- begin;
- heading:=ck(heading - delta);
- return {x_coord,y_coord}
- end;
- procedure setheadingtowards(q); %This takes a cartesian coordinate point as
- %its argument and redirects the turtle towards
- begin scalar x,y,f; %the point specified.
- x:=first q - x_coord;
- y:=second q - y_coord;
- f:=polar({x,y});
- heading:= ck(second f);
- return {x_coord,y_coord}
- end;
- %We also need to use forward/back without drawing a line
- %(in addition to the other set commands). These have the effect
- % of penup/pendown commands used in conjunction with forward/back.
- procedure setforward(m);
- begin scalar theta,s,u;
- theta:=heading;
- s:={m,theta};
- u:=cartesian(s);
- return setposition(u)
- end;
- procedure setback(n);
- begin scalar theta,v,w;
- theta:=ck(heading+180);
- v:={n,theta};
- w:=cartesian(v);
- heading:=ck(theta-180);
- return setposition(w)
- end;
- %LINE-DRAWING FUNCTIONS
- % The following functions are used when an actual line is to be drawn
- % between two points on the graph. They each return a list of two points which,
- % when used within the draw function, are joined together by a line.
- % In addition, they reset the position of the turtle,
- % but do not alter the direction stored.
- procedure move(p); %This takes a cartesian coordinate point as
- %its argument and draws a line towards the
- begin scalar x,y,line; %specified point
- x:=first p;
- y:=second p;
- line:={{x_coord,y_coord},{x,y}};
- x_coord:=x;
- y_coord:=y;
- return line
- end;
- procedure forward(c); %The turtle is moved c units in the direction
- begin scalar theta,s,u,fl; %of the current heading setting
- theta:=heading;
- s:={c,theta};
- u:=cartesian(s);
- fl:= {{x_coord,y_coord},{x_coord+first(u),y_coord+second(u)}};
- x_coord:=x_coord+first(u);
- y_coord:=y_coord+second(u);
- return fl
- end;
- procedure back(d); %The turtle is moved d units in the opposite
- begin scalar theta,v,w,bl; %direction to heading
- theta:=ck(heading+180);
- v:={d,theta};
- w:=cartesian(v);
- bl:= {{x_coord,y_coord},{x_coord+first(w),y_coord+second(w)}};
- x_coord:=x_coord+first(w);
- y_coord:=y_coord+second(w);
- heading:=ck(theta-180);
- return bl
- end;
- %PLOTTING PICTURES
- % The next functions gather the commands input by the user and turn
- % them into a graph output in a gnuplot window;
- procedure draw(p); %This is the function the user calls to draw
- %the list of commands as a picture. It takes
- begin scalar g; %a list as its argument. The items in the list
- %are expected to be any of the setting or plot-
- %ting functions already outlined.
- g:=for each a in p collect a;
- plot g
- end;
- %SUMMARY
- % The main variables:
- % x_coord
- % y_coord
- % heading
- %are global, so it is advised that these are not altered directly.
- % The following functions have been used in order to create the user commands, but they
- %cannot be used directly in the draw function:
- % degree, rad,
- % polar, cartesian,
- % ck, try.
- %(also the info command is designed to be used outside of a call to draw)
- % The following functions are all user commands which can be placed in the list to be
- %executed by the draw command:
- % clearscreen
- % home
- % setheading
- % setx
- % sety
- % setposition
- % turnleft
- % turnright
- % setheadingtowards
- % setforward
- % setback
- % move
- % forward
- % back
- % The most important function is the draw function. It takes the list
- % of commands and plots the points given.
- %NOTE
- % When using conditional statements under a call to draw, the final else
- % statement must return a point or at least {x_coord,y_coord} if the picture
- % is to be continued. Also for statements must include 'collect ' with a
- % list of drawing commands. (The variable needs to begin counting from 0
- % if it is to be joined onto the previous list %of drawing commands,
- % e.g. for i:=0:10 collect{.......}).
- % This program is designed to take the "Turtle Graphics" commands and implement
- % them in REDUCE.
- % Where possible, commands have remained the same, but pen-up & pen-down
- % commands are not used. Instead the commands either set the variables
- %(which are the x and y coordinates and heading variable), or draw a line.
- %STARTING UP
- % Many commands have either ordinary cartesian arguments or polar coordinate
- % arguments, so we need to be able to transform them all into cartesian to
- % plot on an x-y plane. This invovles the use of the pi function, so we
- % need floating point accuracy:
- %% on rounded;
- % The following are the main variables of the program, but the user should not
- %attempt to alter them directly. The functions
- % 'setx,sety,setposition,setheading' are for that purpose.
- x_coord:=0;
- y_coord:=0;
- heading:=0;
- procedure clearscreen(); % This function resets the variables to the
- begin; %original position.
- plotreset; %If the user has plotkeep on then this will
- %clear the current gnuplot window.
- x_coord:=0;
- y_coord:=0;
- heading:=0;
- return {x_coord,y_coord}
- end;
- procedure home(); % This also resets the variables and in general
- begin; %is sufficient since gnuplot automatically rep-
- x_coord:=0; %laces its windows each time it plots a new
- y_coord:=0; %graph.
- heading:=0;
- return {x_coord,y_coord}
- end;
- %DEGREE-RADIAN TRANSFORMS
- % These functions are called in the commands for drawing graphs.
- % The user need not call on either degree or rad for drawing purposes.
- procedure degree(theta);
- begin scalar a;
- a:=theta*180/pi;
- return a
- end;
- procedure rad(mu);
- begin scalar b;
- b:=mu*pi/180;
- return b
- end;
- %POLAR-CARTESIAN TRANSFORMS
- % Again, there is no use for these functions in drawing, but they are needed to
- % turn user inputs into x-y coordinate points.
- procedure polar(p);
- begin scalar x,y,r,theta;
- x:=first p;
- y:=second p;
- r:=(x^2+y^2)^(1/2);
- if x>0 then theta:=atan(y/x)
- else if x=0 then theta:=sign(y)*pi/2
- else theta:=pi+atan(y/x);
- return(list(r,degree(theta)))
- end;
- procedure cartesian(p);
- begin scalar r,theta,x,y;
- r:=first p;
- theta:=rad(second p);
- x:=r*cos(theta);
- y:=r*sin(theta);
- return(list(x,y))
- end;
- procedure ck(m); %This is a useful function to keep the heading
- %variable within the 0-360 range. It is used
- begin; %within other functions for controlling the
- %heading size - it is not necessary for the
- %user to call ck.
- if numberp m then <<
- if (m>=0 and m<360) then heading:=m;
- if (m<0) then ck(360+m);
- if (m>=360) then ck(m-360) >>
- else rederr "error:ck needs numeric argument";
- return heading
- end;
- >>;
- endmodule;
- end;
|