From 7eeb791fad8f9735169ea39c043ee1d50fe86c62 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 12 Apr 2008 04:09:41 +0000 Subject: [PATCH] finish legacy graphics docs; add turtles docs svn: r9274 --- collects/graphics/info.ss | 1 - collects/graphics/scribblings/common.ss | 14 + collects/graphics/scribblings/graphics.scrbl | 670 +++++------------- collects/graphics/scribblings/info.ss | 5 +- .../scribblings/traditional-turtles.scrbl | 218 ++++++ collects/graphics/scribblings/turtles.scrbl | 13 + .../graphics/scribblings/value-turtles.scrbl | 86 +++ 7 files changed, 523 insertions(+), 484 deletions(-) create mode 100644 collects/graphics/scribblings/common.ss create mode 100644 collects/graphics/scribblings/traditional-turtles.scrbl create mode 100644 collects/graphics/scribblings/turtles.scrbl create mode 100644 collects/graphics/scribblings/value-turtles.scrbl diff --git a/collects/graphics/info.ss b/collects/graphics/info.ss index 63f4ab2a84..13a63c4835 100644 --- a/collects/graphics/info.ss +++ b/collects/graphics/info.ss @@ -1,3 +1,2 @@ #lang setup/infotab -(define compile-omit-paths '("value-turex.ss" "value-turtle-lib.ss")) diff --git a/collects/graphics/scribblings/common.ss b/collects/graphics/scribblings/common.ss new file mode 100644 index 0000000000..a4c95f31f2 --- /dev/null +++ b/collects/graphics/scribblings/common.ss @@ -0,0 +1,14 @@ +#lang scheme/base + +(require scribble/manual + (for-label scheme/base + scheme/contract + scheme/class + scheme/unit + scheme/gui/base)) +(provide (all-from-out scribble/manual) + (for-label (all-from-out scheme/base + scheme/contract + scheme/class + scheme/unit + scheme/gui/base))) diff --git a/collects/graphics/scribblings/graphics.scrbl b/collects/graphics/scribblings/graphics.scrbl index 659ea8b4fe..4b7a87503b 100644 --- a/collects/graphics/scribblings/graphics.scrbl +++ b/collects/graphics/scribblings/graphics.scrbl @@ -1,14 +1,13 @@ #lang scribble/doc -@(require scribble/manual - (for-label scheme/base - scheme/contract - "../graphics.ss")) +@(require "common.ss" + (for-label "../graphics.ss" + "../graphics-sig.ss" + "../graphics-unit.ss" + "../graphics-posn-less-unit.ss")) @title{@bold{Graphics}: Legacy Library} -@table-of-contents[] - -@section[#:style 'toc]{Viewport Graphics} +@defmodule[graphics/graphics] The viewport graphics library is a relatively simple toolbox of graphics commands. The library is not very powerful; it is intended as @@ -20,13 +19,11 @@ commands available within Chez Scheme at Rice University. The functionality of that library has been reproduced (with backward compatibility) in this version. -@defmodule[graphics/graphics] - -@local-table-of-contents[] +@table-of-contents[] @; ---------------------------------------------------------------------- -@subsection{Basic Commands} +@section{Basic Commands} @defproc[(open-graphics) void?]{ @@ -85,7 +82,7 @@ for drawing), @scheme[#f] otherwise.} @; ---------------------------------------------------------------------- -@subsection{Position Operations} +@section[#:tag "posn"]{Position Operations} A position is a pixel location within a viewport. The upper-left corner is pixel @math{(0, 0)}, and positions increase to the left and @@ -120,7 +117,7 @@ to draw.} @; ---------------------------------------------------------------------- -@subsection{Color Operations} +@section{Color Operations} A color can be represented in three ways: as a color index (an integer in 0 to 299, inclusive), as a color name string, or as a @scheme[rgb] @@ -151,7 +148,7 @@ color or @scheme[#f] otherwise.} @; ---------------------------------------------------------------------- -@subsection{Draw, Clear, and Flip Operations} +@section{Draw, Clear, and Flip Operations} The following are the basic graphics operations for drawing to a viewport. Each function takes a viewport as its argument and returns @@ -166,7 +163,7 @@ colored, @schemeidfont{clear-} functions make them white, and @schemeidfont{flip-} commands @deftech{invert} pixels (which makes black white, white black, and is otherwise ill-defined). -@subsubsection{Viewports} +@subsection{Viewports} @defproc[((draw-viewport [viewport viewport?]) [color (or/c (integer-in 0 299) @@ -195,7 +192,7 @@ Copies the content of @scheme[source] into @scheme[dest].} @; ---------------------------------------- -@subsubsection{Pixels} +@subsection{Pixels} @defproc[((draw-pixel [viewport viewport?]) [p posn?] @@ -221,7 +218,7 @@ Whitens the pixel in @scheme[viewport] at @scheme[p].} @; ---------------------------------------- -@subsubsection{Lines} +@subsection{Lines} @defproc[((draw-line [viewport viewport?]) [p1 posn?] @@ -255,7 +252,7 @@ and @scheme[p2].} @; ---------------------------------------- -@subsubsection{Rectangles} +@subsection{Rectangles} @defproc[((draw-rectangle [viewport viewport?]) [p posn?] @@ -328,7 +325,7 @@ to @scheme[draw-solid-rectangle].} @; ---------------------------------------- -@subsubsection{Ellipses} +@subsection{Ellipses} @defproc[((draw-ellipse [viewport viewport?]) [p posn?] @@ -401,7 +398,7 @@ to @scheme[draw-solid-ellipse].} @; ---------------------------------------- -@subsubsection{Polygons} +@subsection{Polygons} @defproc[((draw-polygon [viewport viewport?]) [points (listof posn?)] @@ -468,7 +465,7 @@ Whitens a polygon border in @scheme[viewport], analogous to @; ---------------------------------------- -@subsubsection{Strings} +@subsection{Strings} @defproc[((draw-string [viewport viewport?]) [p posn?] @@ -502,7 +499,7 @@ The lower left of the string begins at @scheme[p].} @; ---------------------------------------- -@subsubsection{Pixmaps} +@subsection{Pixmaps} @defproc[(((draw-pixmap-posn [file path-string?] [type (one-of/c 'unknown 'unknown/mask @@ -552,95 +549,90 @@ The @scheme[type] argument determines the kind of file that is written.} @; ---------------------------------------- -@;{ +@section{World Operations} -@subsection{World Operations} +Every canvas comes with an associated world. A client program can set +the world, start the world's clock, stop the world's clock, and deal +with tick events (the clock ticks) and keyboard inputs (keyevents). -Every canvas comes with an associated world. A client program can set the world, -start the world's clock, stop the world's clock, and deal with tick events (the -clock ticks) and keyboard inputs (keyevents). +@defproc[((init-world [viewport viewport?]) [v any/c]) void?]{ -@itemize{ -@item{\Function{init-world} - @scheme[((init-world @scheme[viewport]) X)] -Takes a viewport descriptor. It returns a function whose input becomes the -initial value of the world associated with this canvas.} +Sets the initial value of @scheme[viewport]'s world to @scheme[v].} -@item{\Function{set-on-tick-event} - @scheme[((set-on-tick-event @scheme[viewport]) number @scheme[unary procedure])] -Takes a viewport descriptor. It returns a function whose first input is a - number and the second one is a function from worlds to worlds. The number - determines how frequently the clock ticks. The given function is called for - every clock tick on the current world; the result becomes the next world.} +@defproc[((set-on-tick-event [viewport viewport?]) + [secs real?] [update-callback (any/c . -> . any/c)]) void?]{ -@item{\Function{stop-tick} - @scheme[((stop-tick @scheme[viewport]))] -Takes a viewport descriptor. It returns a function of no arguments that can - stop the clock for this canvas's world.} +For @scheme[viewport], sets @scheme[update-callback] to be invoked to +transform the world value every @scheme[secs] seconds. Only one +callback is installed at a time.} -@item{\Function{set-on-key-event} - @scheme[((set-on-key-event @scheme[viewport]) unary-procedure)] -Takes a viewport descriptor. It returns a function whose input becomes the - keyevent callback function. This callback consumes the latest keyevent and the - current world and a keyevent; it produces the next world.} -} +@defproc[((stop-tick [viewport viewport?])) void?]{ -@subsection{Miscellaneous Operations} +Stops updating @scheme[viewport]'s world via a callback installed with +@scheme[set-on-tick-event].} -@itemize{ -@item{\Function{get-string-size} - @scheme[((get-string-size @scheme[viewport]) string)] - Takes a viewport descriptor. It returns a -function that returns the size of a string as a list of two numbers: -the width and height.} +@defproc[((set-on-key-event [viewport viewport?]) + [key-callback (any/c any/c . -> . any/c)]) + void?]{ -@item{\Function{viewport->snip} - @scheme[(viewport->snip @scheme[viewport])] - Takes a viewport descriptor. It returns an -object that can be inserted into an editor buffer to display the -current image in the viewport. (Subsequent drawing to the viewport -does not affect the snip's image.) +Sets @scheme[key-callback] as the function to call whenever a key +event is received for @scheme[viewport]. The @scheme[key-callback] is +given a key event and the current world, and it produces an updated +world.} -When snips are the results of computations in the interactions window, DrScheme will print show the contents of the viewport, right in the interactions window.} +@; ---------------------------------------- -@item{\Function{viewport-dc} - @scheme[(viewport-dc @scheme[viewport])] - Takes a viewport descriptor. It returns an -object that can be used with the primitive MrEd toolbox -functions to draw into the viewport's on-screen representation -(if any). Mirror all such drawing to the result of -@scheme[(viewport-offscreen-dc @scheme[viewport])], too.} +@section{Miscellaneous Operations} -@item{\Function{viewport-offscreen-dc} - @scheme[(viewport-offscreen-dc @scheme[viewport])] - Takes a viewport descriptor. It returns an - object that can be used with the primitive MrEd toolbox - functions to draw into the viewport's off-screen representation. - Mirror all such drawing to the result of - @scheme[(viewport-dc @scheme[viewport])], too.} -} +@defproc[((get-string-size [viewport viewport?]) [str string?]) (list/c real? real?)]{ -@subsection{An Example} +Returns the size of @scheme[str] as drawn into @scheme[viewport] as a +list of two numbers: width and height.} + +@defproc[(viewport->snip [viewport viewport?]) (is-a?/c snip%)] + +Returns an object that can be inserted into an editor buffer to +display the current image in the viewport. (Subsequent drawing to the +viewport does not affect the snip's image.) + +When snips are the results of computations in the interactions window, +DrScheme shows the snip in the interactions window.} + +@defproc[(viewport-dc [viewport viewport?]) (is-a?/c dc<%>)]{ + +Returns an object for direct drawing into @scheme[viewport]'s +on-screen representation (if any). Mirror all such drawing to the +result of @scheme[(viewport-buffer-dc viewport)], too.} + +@defproc[(viewport-buffer-dc [viewport viewport?]) (is-a?/c dc<%>)]{ + +Returns an object for direct drawing into @scheme[viewport]'s +off-screen representation. Mirror all such drawing to the +result of @scheme[(viewport-dc viewport)], too.} + +@; ---------------------------------------- + +@section{An Example} @schemeblock[ (open-graphics) -;; nothing appears to happen, but the library is initialized... +(code:comment #, @t{nothing appears to happen, but the library is initialized...}) (define w (open-viewport "practice" 300 300)) -;; viewport appears +(code:comment #, @t{viewport window appears}) ((draw-line w) (make-posn 30 30) (make-posn 100 100)) -;; line appears +(code:comment #, @t{line appears}) (close-viewport w) -;; viewport disappears +(code:comment #, @t{viewport disappears}) (close-graphics) -;; again, nothing appears to happen, but -;; unclosed viewports (if any) would disappear +(code:comment #, @t{again, nothing appears to happen, but}) +(code:comment #, @t{unclosed viewports (if any) would disappear}) ] -@subsection{A More Complicated Example} +@section{A More Complicated Example} The use of multiple viewports, viewport descriptors, drawing operations for multiple viewports is as easy as the use of a single @@ -648,24 +640,24 @@ viewport: @schemeblock[ (open-graphics) -(let* (;; @scheme[w1] and @scheme[w2] are viewport descriptors for different windows +(let* ((code:comment #, @t{@scheme[w1] and @scheme[w2] are viewports for different windows}) [w1 (open-viewport "viewport 1" 300 300)] [w2 (open-viewport "viewport 2" 200 500)] - ;; d1 and d2 are functions that draw lines in different viewports + (code:comment #, @t{@scheme[d1] and @scheme[d2] draw lines in different viewports}) [d1 (draw-line w1)] [d2 (draw-line w2)]) - ;; draws a line in viewport labeled "viewport 1" + (code:comment #, @t{draws a line in viewport labeled ``viewport 1''}) (d1 (make-posn 100 5) (make-posn 5 100)) - ;; draws a line in viewport labeled "viewport 2" + (code:comment #, @t{draws a line in viewport labeled ``viewport 2''}) (d2 (make-posn 100 100) (make-posn 101 400))) -;; we no longer have access to viewports 1 and 2, -;; since their descriptors did not escape the @scheme[let] +(code:comment #, @t{we no longer have access to viewports 1 and 2,}) +(code:comment #, @t{since their descriptors did not escape the @scheme[let]}) (close-graphics) -;; removes the viewports +(code:comment #, @t{removes the viewports}) ] -@subsection{Protecting Graphics Operations} +@section{Protecting Graphics Operations} To guarantee the proper closing of viewports in cases of errors, especially when a program manages several viewports simultaneously, a @@ -674,436 +666,152 @@ programmer should use @scheme[dynamic-wind:] @schemeblock[ (let ([w (open-viewport "hello" 100 100)]) (dynamic-wind - ;; what we want to happen first: nothing + (code:comment #, @t{what we want to happen first: nothing}) void - ;; the main program (errors constrained to this piece) - (lambda () (draw-pixel 13)) ; an error - ;; what we would like to happen, whether the main program finishes - ;; normally or not + (code:comment #, @t{the main program (errors constrained to this piece)}) + (lambda () (draw-pixel 13)) (code:comment #, @t{an error}) + (code:comment #, @t{what we would like to happen, whether the main program}) + (code:comment #, @t{finishes normally or not}) (lambda () (close-viewport w)))) ] -@subsection{Mouse Operations} +@; ---------------------------------------- -The graphics library contains functions that determine where the -mouse is, if there are any clicks, etc. -The functions @scheme[get-mouse-click] and @scheme[ready-mouse-click] first -return a ``mouse-click descriptor,'' and then other functions take -the descriptor and return the mouse's position, which button was -pushed, etc. -Mouse clicks are buffered and returned in the same order in which -they occurred. -Thus, the descriptors returned by @scheme[get-mouse-click] and -@scheme[ready-mouse-click] may be from clicks that occurred long -before these functions were called. +@section{Mouse Operations} -@itemize{ -@item{\Function{get-mouse-click} - @scheme[(get-mouse-click @scheme[viewport])] - Takes a viewport descriptor and returns -a mouse click descriptor. -It returns the next mouse click in the @scheme[viewport], waiting for a click +The graphics library contains functions that determine where the mouse +is, if there are any clicks, etc. The functions +@scheme[get-mouse-click] and @scheme[ready-mouse-click] first return a +``mouse-click descriptor,'' and then other functions take the +descriptor and return the mouse's position, which button was pushed, +etc. Mouse clicks are buffered and returned in the same order in +which they occurred. Thus, the descriptors returned by +@scheme[get-mouse-click] and @scheme[ready-mouse-click] may be from +clicks that occurred long before these functions were called. + +@defproc[(get-mouse-click [viewport viewport?]) mouse-click?]{ + +Returns the next mouse click in @scheme[viewport], waiting for a click if necessary.} -@item{\Function{ready-mouse-click} - @scheme[(ready-mouse-click @scheme[viewport])] - Takes a viewport descriptor and returns -either a mouse click descriptor, or else @scheme[#f] if none is available. -Unlike the previous function, @scheme[ready-mouse-click] returns immediately.} -@item{\Function{ready-mouse-release} - @scheme[(ready-mouse-release @scheme[viewport])] - Takes a viewport descriptor and returns -either a click descriptor from a mouse-release (button-up) event, -or else @scheme[#f] if none is available.} +@defproc[(ready-mouse-click [viewport viewport?]) + (or/c mouse-click? false/c)]{ -@item{\Function{query-mouse-posn} - @scheme[(query-mouse-posn @scheme[viewport])] - Takes a viewport descriptor and returns -either the position of the mouse cursor within the @scheme[viewport], -or else @scheme[#f] if the cursor is currently outside the @scheme[viewport].} +Returns either a mouse click descriptor or @scheme[#f] if none is +available. Unlike @scheme[get-mouse-click], +@scheme[ready-mouse-click] always returns immediately.} -@item{\Function{mouse-click-posn} - @scheme[(mouse-click-posn @scheme[mouse-click])] - Takes a mouse click descriptor and -returns the position of the pixel where the click occurred.} -@item{\Function{left-mouse-click?} - @scheme[(left-mouse-click?\ @scheme[mouse-click])] - Takes a mouse click descriptor and returns -@scheme[#t] if the click occurred with the left mouse button, -or else @scheme[#f].} +@defproc[(ready-mouse-release [viewport viewport?]) + (or/c mouse-click? false/c)]{ -@item{\Function{middle-mouse-click?} - @scheme[(middle-mouse-click?\ @scheme[mouse-click])] -Similar to @scheme[left-mouse-click?].} +Returns either a click descriptor from a mouse-release (button-up) +event or @scheme[#f] if none is available.} -@item{\Function{right-mouse-click?} - @scheme[(right-mouse-click?\ @scheme[mouse-click])] -Similar to @scheme[left-mouse-click?].} -} -@subsection{Keyboard Operations} +@defproc[(query-mouse-posn [viewport viewport?]) (or/c posn? false/c)]{ + +Returns either the position of the mouse cursor within +@scheme[viewport] or else @scheme[#f] if the cursor is currently +outside @scheme[viewport].} + + +@defproc[(mouse-click-posn [mouse-click mouse-click?]) posn?]{ + +Returns the position of the pixel within a viewport where a given +mouse click occurred.} + + +@defproc[(left-mouse-click? [mouse-click mouse-click?]) boolean?]{ + +Returns @scheme[#t] if the mouse click occurred with the left mouse +button, @scheme[#f] otherwise.} + +@defproc[(middle-mouse-click? [mouse-click mouse-click?]) boolean?]{ + +Returns @scheme[#t] if the mouse click occurred with the middle mouse +button, @scheme[#f] otherwise.} + +@defproc[(right-mouse-click? [mouse-click mouse-click?]) boolean?]{ + +Returns @scheme[#t] if the mouse click occurred with the right mouse +button, @scheme[#f] otherwise.} + +@; ---------------------------------------- + +@section{Keyboard Operations} The graphics library contains functions that report key presses from - the keyboard. The functions @scheme[get-key-press] and - @scheme[ready-key-press] return a ``key-press descriptor,'' and then - @scheme[key-value] takes the descriptor and returns a character or - symbol (usually a character) representing the key that was pressed. - Key presses are buffered and returned in the same order in which they - occurred. Thus, the descriptors returned by @scheme[get-key-press] and - @scheme[ready-key-press] may be from presses that occurred long before - these functions were called. +the keyboard. The functions @scheme[get-key-press] and +@scheme[ready-key-press] return a ``key-press descriptor,'' and then +@scheme[key-value] takes the descriptor and returns a character or +symbol (usually a character) representing the key that was pressed. +Key presses are buffered and returned in the same order in which they +occurred. Thus, the descriptors returned by @scheme[get-key-press] +and @scheme[ready-key-press] may be from presses that occurred long +before these functions were called. -@itemize{ -@item{\Function{get-key-press} - @scheme[(get-key-press @scheme[viewport])] - Takes a viewport descriptor and returns -a key press descriptor. -It returns the next key press in the @scheme[viewport], waiting for a click -if necessary.} +@defproc[(get-key-press [viewport viewport?]) key-press?]{ -@item{\Function{ready-key-press} - @scheme[(ready-key-press @scheme[viewport])] - Takes a viewport descriptor and returns -either a key press descriptor, or else @scheme[#f] if none is available. -Unlike the previous function, @scheme[ready-key-press] returns immediately.} +Returns the next key press in the @scheme[viewport], waiting for a +key press if necessary.} -@item{\Function{key-value} - @scheme[(key-value @scheme[key-press])] +@defproc[(ready-key-press [viewport viewport?]) key-press?]{ - Takes a key press descriptor and returns a character or special - symbol for the key that was pressed. For example, the Enter key - generates \scmch{return}, and the up-arrow key generates @scheme['up]. - For a complete list of possible return values, see {\MrEdManual}.} -} +Returns the next key press in the @scheme[viewport] or returns +@scheme[#f] if none is available. Unlike @scheme[get-key-press], +@scheme[ready-key-press] always returns immediately.} -@subsection{Flushing} +@defproc[(key-value [key-press key-press?]) (or/c character? symbol?)]{ -@itemize{ -@item{\Function{viewport-flush-input} - @scheme[(viewport-flush-input @scheme[viewport])] -As noted above, key presses and mouse clicks are buffered. -@scheme[viewport-flush-input] takes a viewport descriptor -and empties the input buffer of mouse and keyboard events.} -} +Returns a character or special symbol for the key that was +pressed. For example, the Enter key generates @scheme[#\return], and the +up-arrow key generates @scheme['up]. For a complete list of possible +return values, see @method[key-event% get-key-code].} -@subsection{Unitized Graphics} +@; ---------------------------------------- -To use a unitized version of the graphics library (see {\MzLibManual} - for more information on units), get the signatures - \scmsigfirst{graphics}, \scmsigfirst{graphics:posn-less}, and - \scmsigfirst{graphics:posn} with: +@section{Flushing} -@schemeblock[ -(require (libKW "graphics-sig.ss" "graphics")) -] +@defproc[(viewport-flush-input [viewport viewport?]) void?]{ -The \scmsig{graphics} signature includes all of the names defined in - this chapter. The \scmsig{graphics:posn-less} signature contains - everything except the \scm{posn} structure information, and - \scmsig{graphics:posn} contains only the \scm{posn} structure. +Empties all mouse and keyboard events in the input buffer of +@scheme[viewport].} -To obtain \scmunitfirst{graphics}, which imports \scmsig{mred} (all of - the MrEd classes, functions, and constants) and exports - \scmsig{graphics}: +@; ---------------------------------------- -@schemeblock[ -(require (libKW "graphics-unit.ss" "graphics")) -] +@section{Graphics Library as a Unit} -The @filepath{graphics-posn-less-unit.ss} library provides - \scmunit{graphics-posn-less}, which imports \scmsig{graphics:posn} in - addition to MrEd. +@subsection{Signatures} -@; ====================================================================== +@defmodule[graphics/graphics-sig] -@section[#:tag "misc:turtles"]{Turtles} +@defsignature[graphics^ ()] -@subsection{Traditional Turtles} +Includes all of the bindings defined earlier in this chapter, except +the @scheme[posn] bindings of @secref["posn"]. -There are two ways to use the turtles in DrScheme. You can -use it as a TeachPack (see the DrScheme manual for details -of TeachPacks) or as a library. Use the -@filepath{turtles.ss} TeachPack. -In the MrEd language or in a module, load turtles with +@defsignature[graphics:posn^ ()] -@schemeblock[ -(require (libKW "turtles.ss" "graphics")) -] +Includes the @scheme[posn] bindings of @secref["posn"]. -The following are the turtle functions: -@itemize{ -@item{{@scheme[(turtles b)]}\Function{turtles} - shows and hides the turtles window based on the boolean @scheme[b]. - The parameter @scheme[b] is optional; if it is left out, it toggles the - state of the turtles.} +@subsection{Unit with @scheme[posn]} -@item{{{@scheme[(move n)]}}\Function{move} - moves the turtle n pixels.} +@defmodule[graphics/graphics-unit] -@item{{{@scheme[(draw n)]}}\Function{draw} - moves the turtle n pixels and draws a line on that path.} +@defthing[graphics@ unit?]{ -@item{{{@scheme[(erase n)]}}\Function{erase} - moves the turtle n pixels and erases along that path. +Imports @scheme[mred^] and exports both @scheme[graphics^] and +@scheme[graphics:posn^].} -\Function{move-offset} -\Function{draw-offset} -\Function{erase-offset}} -@item{{{ @scheme[(move-offset h v)], @scheme[(draw-offset h v)], @scheme[(erase-offset h v)]}} - are just like move, draw and erase, except they take a horizontal and - vertical offset from the turtle's current position.} +@subsection{Unit without @scheme[posn]} -@item{{ @scheme[(turn theta)]}\Function{turn} - turns the turtle theta degrees counter-clockwise.} +@defmodule[graphics/graphics-posn-less-unit] -@item{{ @scheme[(turn/radians theta)]}\Function{turn/radians} - turns the turtle theta radians counter-clockwise.} +@defthing[graphics-posn-less@ unit?]{ -@item{{{@scheme[(clear)]}}\Function{clear} - erases the turtles window.} -} - -Turtles also defines these syntactic forms: - -@itemize{ -@item{{{@scheme[(split E)]}}\Function{split} - spawns a new turtle where - the turtle is currently located. In order to distinguish the two turtles, - only the new one evaluates the expression E. For example, if you start - with a fresh turtle-window and type: - -\begin{center} -\begin{schemebox} -(split (turn/radians (/ pi 2))) -\end{schemebox} -\end{center} - - you will have two turtles, pointing at right angles to each other. - To see that, try this: - -\begin{center} -\begin{schemebox} -(draw 100) -\end{schemebox} -\end{center} - - You will see two lines. Now, if you evaluate those two expression - again, you will have four turtles, etc} - -@item{{{@scheme[(split* E ...)]}}\Function{split*} - is similar to @scheme[(split E ...)], except it creates as many turtles as - there are expressions and each turtles does one of the expression. For - example, to create two turtles, one pointing at $\pi/2$ and one at - $\pi/3$, evaluate this: - -\begin{center} -\begin{schemebox} -(split* (turn/radians (/ pi 3)) (turn/radians (/ pi 2))) -\end{schemebox} -\end{center}} - -@item{{{@scheme[(tprompt E...)]}}\Function{tprompt} - provides a way to limit the splitting of the turtles. Before - the expression E is run, the state of the turtles (how many, their - positions and headings) is "checkpointed," then E is evaluated and - the state of the turtles is restored, but all drawing that may have - occurred during execution of E remains. - - For example, if you do this: - -\begin{center} -\begin{schemebox} -(tprompt (draw 100)) -\end{schemebox} -\end{center} - - the turtle will move forward 100 pixels, draw a line there and then - be immediately put back in it's original position. Also, if you do this: - -\begin{center} -\begin{schemebox} -(tprompt (split (turn/radians (/ pi 2)))) -\end{schemebox} -\end{center} - - the turtle will split into two turtles, one will turn 90 degrees and then - the turtles will be put back into their original state -- as if the split - never took place. - - The fern functions below demonstrate more advanced use of @scheme[tprompt].} -} - -In the file @filepath{turtle-examples.ss} in the @filepath{graphics} library of your PLT - distribution, you will find these functions and values defined, as - example turtle programs. (The file is located in the @filepath{graphics} - subdirectory of the @filepath{collects} subdirectory of the PLT - distribution). - -@itemize{ -@item{{{@scheme[(regular-poly sides radius)]}} - draws a regular poly centered at the turtle with - sides @scheme[sides] and with radius @scheme[radius].} - -@item{{{@scheme[(regular-polys sides s)]}} - draws s regular polys spaced evenly outwards with sides @scheme[sides].} - -@item{{{@scheme[(radial-turtles n)]}} - places $2^n$ turtles spaced evenly pointing radially outward} - -@item{{{@scheme[(spaced-turtles n)]}} - places $2^n$ turtles pointing in the same direction as the original turtle - evenly spaced in a line.} - -@item{{{@scheme[(spokes)]}} - draws some spokes, using radial-turtles and spaced-turtles} - -@item{{{@scheme[(spyro-gyra)]}} - draws a spyro-grya reminiscent shape} - -@item{{{@scheme[(neato)]}} - as the name says\ldots} - -@item{{{@scheme[(graphics-bexam)]}} - draws a fractal that came up on an exam I took.} - -@item{{{@scheme[serp-size]}} - a constant which is a good size for the serp procedures - -\index{Serpinski Triangle}} -@item{{@scheme[(serp serp-size)], @scheme[(serp-nosplit serp-size)]} - draws the Serpinski triangle in two different ways, the first using split - heavily. After running the first one, try executing - @scheme[(draw 10)].} - -@item{{{@scheme[koch-size]}} - a constant which is a good size for the koch procedures - -\index{Koch Snowflake}} -@item{{{@scheme[(koch-split koch-size)],@scheme[(koch-draw koch-size)]}} - draws the same koch snowflake in two different ways. - -\index{Lorenz Attractor} -\index{Butterfly Attractor}} -@item{{{@scheme[(lorenz a b c)]}} - watch the lorenz "butterfly" attractor with initial values a b and c.} - -@item{{{@scheme[(lorenz1)]}} - a good setting for the lorenz attractor - -\index{Peano space-filling curve}} -@item{{@scheme[(peano1 peano-size)]} - -This will draw the Peano space-filling curve, using split.} - -@item{{@scheme[(peano2 peano-size)]} - -This will draw the Peano space-filling curve, without using split. - -\index{Fern Fractal}} -@item{{{@scheme[fern-size]}} - a good size for the fern functions} - -@item{{{@scheme[(fern1 fern-size)]}} - You will probably want to point the turtle up before running - this one, with something like: - -\begin{center} -@scheme[(turn/radians (- (/ pi 2)))] -\end{center}} - -@item{{{@scheme[(fern2 fern-size)]}} - a fern -- you may need to backup a little for this one.} - -} - -@subsection{Value Turtles} - -There are two ways to use the turtles in DrScheme. You can -use it as a TeachPack (see the DrScheme manual for details -of TeachPacks) or as a library. Use the -@filepathFirst{value-turtles.ss} TeachPack. - -In the MrEd language or in a module, load turtles with - -@schemeblock[ -(require (libKW "value-turtles.ss" "graphics")) -] - - -The value turtles are a variation on the turtles library. -Rather than having just a single window where each operation -changes the state of that window, in this library, the -entire turtles window is treated as a value. This means -that each of the primitive operations accepts, in addition -to the usual arguments, a turtles window value and instead -of returning nothing, returns a turtles window value. - -The following are the value turtle functions: - -@itemize{ -@item{{@scheme[(turtles number number [number number number])]}\FunctionK{turtles}{turtlesVal} - creates a new turtles window. The first two arguments are - the width and height of the turtles window. The remaining - arguments specify the x,y position of the initial turtle - and the angle. The default to a turtle in the middle of - the window, pointing to the right.} - -@item{{{@scheme[(move n turtles)]}}\FunctionK{move}{moveVal} - moves the turtle n pixels, returning a new turtles window.} - -@item{{{@scheme[(draw n turtles)]}}\FunctionK{draw}{drawVal} - moves the turtle n pixels and draws a line on that path, - returning a new turtles window.} - -@item{{{@scheme[(erase n turtles)]}}\FunctionK{erase}{eraseVal} - moves the turtle n pixels and erases along that path, - returning a new turtles window. - -\FunctionK{move-offset}{move-offsetVal} -\FunctionK{draw-offset}{draw-offsetVal} -\FunctionK{erase-offset}{erase-offsetVal}} -@item{{{@scheme[(move-offset h v turtles)], - @scheme[(draw-offset h v turtles)], - @scheme[(erase-offset h v turtles)]}} - are just like move, draw and erase, except they take a horizontal and - vertical offset from the turtle's current position.} - -@item{{ @scheme[(turn theta turtles)]}\FunctionK{turn}{turnVal} - turns the turtle theta degrees counter-clockwise, - returning a new turtles window.} - -@item{{ @scheme[(turn/radians theta)]}\FunctionK{turn/radians}{turn/radiansVal} - turns the turtle theta radians counter-clockwise, - returning a new turtles window.} - -@item{{@scheme[(merge turtles turtles)]}\Function{merge} - - The @scheme[split] and @scheme[tprompt] functionality - provided by the imperative turtles implementation aren't - needed for this, since the turtles window is itself a - value. - - Instead, the @scheme[merge] accepts two turtles windows - and combines the state of the two turtles windows into a - single window. The new window contains all of the - turtles of the previous two windows, but only the line - drawings of the first turtles argument.} - -} - -In the file @filepath{value-turtles-examples.ss} in the -@filepath{graphics} library of your PLT distribution, you will -find these functions and values defined, as example turtle -programs. (The file is located in the @filepath{graphics} -subdirectory of the @filepath{collects} subdirectory of the PLT -distribution). - -It contains a sampling of the examples from the normal -turtles implementation, but translated to use @scheme[merge] -and the values turtles. - -} +Imports @scheme[mred^] and @scheme[graphics:posn^] and exports +@scheme[graphics^].} diff --git a/collects/graphics/scribblings/info.ss b/collects/graphics/scribblings/info.ss index e60f295df2..8b4db7e848 100644 --- a/collects/graphics/scribblings/info.ss +++ b/collects/graphics/scribblings/info.ss @@ -1,4 +1,5 @@ #lang setup/infotab -(define scribblings '(("graphics.scrbl" (multi-page)))) -(define doc-categories '(legacy)) +(define scribblings '(("graphics.scrbl" (multi-page)) + ("turtles.scrbl" (multi-page)))) +(define doc-categories '(legacy library)) diff --git a/collects/graphics/scribblings/traditional-turtles.scrbl b/collects/graphics/scribblings/traditional-turtles.scrbl new file mode 100644 index 0000000000..54442717c2 --- /dev/null +++ b/collects/graphics/scribblings/traditional-turtles.scrbl @@ -0,0 +1,218 @@ +#lang scribble/doc +@(require "common.ss" + (for-label "../turtles.ss" + "../turtle-examples.ss")) + +@title{Traditional Turtles} + +@defmodule[graphics/turtles] + +@defproc*[([(turtles [on? any/c]) void?] + [(turtles) void?])]{ + +Shows and hides the turtles window based on @scheme[on?]. If +@scheme[on?] is not supplied, the state is toggled.} + +@defproc[(move [n real?]) void?]{ + +Moves the turtle @scheme[n] pixels without drawing.} + +@defproc[(draw [n real?]) void?]{ + +Moves the turtle @scheme[n] pixels and draws a line on the path.} + +@defproc[(erase [n real?]) void?]{ + +Moves the turtle @scheme[n] pixels and erase along the path.} + +@deftogether[( +@defproc[(move-offset [h real?][v real?]) void?] +@defproc[(draw-offset [h real?][v real?]) void?] +@defproc[(erase-offset [h real?][v real?]) void?] +)]{ + +Like @scheme[move], @scheme[draw], and @scheme[erase], but using a +horizontal and vertical offset from the turtle's current position.} + + +@defproc[(turn [theta real?]) void?]{ + +Turns the turtle @scheme[theta] degrees counter-clockwise.} + +@defproc[(turn/radians [theta real?]) void?]{ + +Turns the turtle @scheme[theta] radians counter-clockwise.} + +@defproc[(clear) void?]{ + +Erases the turtles window.} + +@defform[(split expr ...)]{ + +Spawns a new turtle where the turtle is currently located. In order to +distinguish the two turtles, only the new one evaluates +@scheme[expr]. For example, if you start with a fresh turtle-window +and type: + +@schemeblock[ +(split (turn/radians (/ pi 2))) +] + +you will have two turtles, pointing at right angles to each +other. Continue with + +@schemeblock[ +(draw 100) +] + +You will see two lines. Now, if you evaluate those two expression +again, you will have four turtles, etc.} + +@defform[(split* expr ...)]{ + +Like @scheme[(split expr ...)], except that one turtle is created for +each @scheme[expr]. + +For example, to create two turtles, one pointing at @math["\u3C0/2"] +and one at @math["\u3C0/3"], evaluate + +@schemeblock[ + (split* (turn/radians (/ pi 3)) (turn/radians (/ pi 2))) +]} + +@defform[(tprompt expr ...)]{ + +Limits the splitting of the turtles. Before@scheme[expr] is evaluated, +the state of the turtles (how many, their positions and headings) is +``checkpointed.'' Then @scheme[expr] is evaluated, and then the state +of the turtles is restored, but all drawing that may have occurred +during execution of @scheme[expr] remains. + +For example + +@schemeblock[ +(tprompt (draw 100)) +] + +moves a turtle forward 100 pixel while drawing a line, and then moves +the turtle be immediately back to it's original position. Similarly, + +@schemeblock[ +(tprompt (split (turn/radians (/ pi 2)))) +] + +splits the turtle into two, rotates one 90 degrees, and then +collapses back to a single turtle. + +The fern functions below demonstrate more advanced use of +@scheme[tprompt].} + +@; ---------------------------------------- + +@section{Examples} + +@defmodule[graphics/turtle-examples] + +The @schememodname[graphics/turtle-examples] library's source is meant +to be read, but it also exports the following examples. + +@defproc[(regular-poly [sides exact-nonnegative-integer?] [radius real?]) + void?]{ + +Draws a regular poly centered at the turtle with @scheme[sides] sides +and with radius @scheme[radius].} + +@defproc[(regular-polys [n exact-nonnegative-integer?] [s any/c]) + void?]{ + +Draws @scheme[n] regular polys each with @scheme[n] sides centered at +the turtle.} + +@defproc[(radial-turtles [n exact-nonnegative-integer?]) void?]{ + +Places @math{2^n} turtles spaced evenly pointing radially outward.} + +@defproc[(spaced-turtles [n exact-nonnegative-integer?]) void?]{ + +Places @math{2^n} turtles evenly spaced in a line and pointing in the +same direction as the original turtle.} + +@defproc[(spokes) void?]{ + +Draws some spokes, using @scheme[radial-turtles] and +@scheme[spaced-turtles].} + +@defproc[(spyro-gyra) void?]{ + +Draws a spyro-grya reminiscent shape.} + +@defproc[(neato) void?]{ + +As the name says...} + +@defproc[(graphics-bexam) void?]{ + +Draws a fractal that came up on an exam that the author took.} + +@defthing[serp-size real?]{ + +A constant that is a good size for the @scheme[serp] procedures.} + +@deftogether[( +@defproc[(serp [serp-size real?]) void?] +@defproc[(serp-nosplit [serp-size real?]) void?] +)]{ + +Draws the @as-index{Serpinski triangle} in two different ways, the +first using @scheme[split] heavily. After running the first one, try +executing @scheme[(draw 10)].} + + +@defthing[koch-size real?]{ + +A constant that is a good size for the @scheme[koch] procedures.} + +@deftogether[( +@defproc[(koch [koch-size real?]) void?] +@defproc[(koch-nosplit [koch-size real?]) void?] +)]{ + +Draws the same @as-index{Koch snowflake} in two different ways.} + +@defproc[(lorenz [a real?] [b real?] [c real?]) void?]{ + +Watch the @as-index{Lorenz attractor} (a.k.a. @as-index{butterfly attractor}) +initial values @scheme[a], @scheme[b], and @scheme[c].} + +@defproc[(lorenz1) void?]{ + +Calls @scheme[lorenze] with good initial values.} + +@deftogether[( +@defproc[(peano1 [peano-size real?]) void?] +@defproc[(peano2 [peano-size real?]) void?] +)]{ + +Draws the @as-index{Peano space-filling curve}, where @scheme[peano1] uses +@scheme[split].} + +@defthing[fern-size exact-nonnegative-integer?]{ + +A good size for the @scheme[fern1] and @scheme[fern2] functions.} + +@deftogether[( +@defproc[(fern1 [fern-size exact-nonnegative-integer?]) void?] +@defproc[(fern2 [fern-size exact-nonnegative-integer?]) void?] +)]{ + +Draws a @as-index{fern fractal}. + +For @scheme[fern1], you will probably want to point the turtle up +before running this one, with something like: + +@schemeblock[ +@scheme[(turn/radians (- (/ pi 2)))] +] + +For @scheme[fern2], you may need to backup a little.} + diff --git a/collects/graphics/scribblings/turtles.scrbl b/collects/graphics/scribblings/turtles.scrbl new file mode 100644 index 0000000000..c74aa6890f --- /dev/null +++ b/collects/graphics/scribblings/turtles.scrbl @@ -0,0 +1,13 @@ +#lang scribble/doc +@(require scribble/manual) + +@title{Turtle Graphics} + +Turtle graphics are available in two forms: traditional imperative +turtle operations that draw into a fixed window, and functional turtle +operations that consume and produce a turtle picture. + +@table-of-contents[] + +@include-section["traditional-turtles.scrbl"] +@include-section["value-turtles.scrbl"] diff --git a/collects/graphics/scribblings/value-turtles.scrbl b/collects/graphics/scribblings/value-turtles.scrbl new file mode 100644 index 0000000000..db8edad09d --- /dev/null +++ b/collects/graphics/scribblings/value-turtles.scrbl @@ -0,0 +1,86 @@ +#lang scribble/doc +@(require "common.ss" + (for-label "../value-turtles.ss")) + + +@title{Value Turtles} + +@defmodule[graphics/value-turtles] + +The value turtles are a variation on traditional turtles. Rather than +having just a single window where each operation changes the state of +that window, in the @scheme[graphics/value-turtles] library, the +entire turtles window is treated as a value. This means that each of +the primitive operations accepts, in addition to the usual arguments, +a turtles-window value; instead of returning nothing, each returns a +turtles-window value. + +@defproc[(turtles [width real?] + [height real?] + [init-x real? (/ width 2)] + [init-y real? (/ height 2)] + [init-angle real? 0]) + turtles-window?]{ + +Creates a new turtles window with the given @scheme[width] and +@scheme[height]. The remaining arguments specify position of the +initial turtle and the direction in radians (where @scheme[0] is to +the right).} + +@defproc[(move [n real?] [turtles turtles-window?]) turtles-window?]{ + +Moves the turtle @scheme[n] pixels, returning a new turtles window.} + +@defproc[(draw [n real?] [turtles turtles-window?]) turtles-window?]{ + +Moves the turtle @scheme[n] pixels and draws a line along the path, +returning a new turtles window.} + +@defproc[(erase [n real?] [turtles turtles-window?]) turtles-window?]{ + +Moves the turtle @scheme[n] pixels and erases a line along the path, +returning a new turtles window.} + + +@deftogether[( +@defproc[(move-offset [h real?] [v real?] [turtles turtles-window?]) turtles-window?] +@defproc[(draw-offset [h real?] [v real?] [turtles turtles-window?]) turtles-window?] +@defproc[(erase-offset [h real?] [v real?] [turtles turtles-window?]) turtles-window?] +)]{ + +Like @scheme[move], @scheme[draw], and @scheme[erase], but using a +horizontal and vertical offset from the turtle's current position.} + + +@defproc[(turn [theta real?] [turtles turtles-window?]) turtles-window?]{ + +Turns the turtle @scheme[theta] degrees counter-clockwise, returning a +new turtles window.} + +@defproc[(turn/radians [theta real?] [turtles turtles-window?]) turtles-window?]{ + +Turns the turtle @scheme[theta] radians counter-clockwise, returning a +new turtles window.} + +@defproc[(merge [turtles1 turtles-window?] [turtles2 turtles-window?]) turtles-window?]{ + +The @scheme[split] and @scheme[tprompt] forms provided by +@schememodname[graphics/turtles] isn't needed for +@schememodname[graphics/value-turtles], since the turtles window is a +value. + +Instead, the @scheme[merge] accepts two turtles windows and combines +the state of the two turtles windows into a single window. The new +window contains all of the turtles of the previous two windows, but +only the line drawings of the first turtles argument.} + +@; ---------------------------------------- + +@section[#:tag "value-examples"]{Examples} + +@defmodule[graphics/value-turtle-examples] + +The @schememodname[graphics/value-turtle-examples] library is similar +to @schememodname[graphics/turtle-examples], but using +@schememodname[graphics/value-turtles] instead of +@schememodname[graphics/turtles].