Artifact 3b2c0ed7ae105098447e687b3cadae1f85c1c76c644d93d9a9837efee67831e4:
- Executable file
r37/packages/plot/turtle.red
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 9515) [annotate] [blame] [check-ins using] [more...]
- Executable file
r38/packages/plot/turtle.red
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 9515) [annotate] [blame] [check-ins using]
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;