***** DRAGON CURVES WITH MUSIC ***** Many of the "fractal" or "self-similar" curves (I call them dragon curves) can be generated by recursive turtle graphics routines. The basic instructions in turtle graphics are: FORWARD :D go forward for a distance :D RIGHT :X turn right by :X degrees LEFT :Y turn left by :Y degrees For example, here is the program for the Koch curve: TO KOCH :SIZE :DEPTH IF :DEPTH=0 [FORWARD :SIZE STOP] KOCH :SIZE/3 :DEPTH-1 LEFT 60 KOCH :SIZE/3 :DEPTH-1 RIGHT 120 KOCH :SIZE/3 :DEPTH-1 LEFT 60 KOCH :SIZE/3 :DEPTH-1 END In this program, and the other recursive programs that construct dragon curves, there is a parameter :DEPTH. When :DEPTH is zero, the curve is just a line segment. When :DEPTH is increased by one, each segment is replaced by a copy of a basic figure consisting of a few line segments. The lengths of the individual segments are decreased when this happens, of course. The drawing commands are simply moving forward by a certain distance, and turning by a certain angle. This suggests a musical accompaniment for the drawing of such dragon curves. Moving forward for a distance :D will correspond to playing a note for length of time :D. Turning will correspond to changing the pitch of the note. (Right = higher, left = lower.) The natural correspondence between angles and changes in pitch lets an octave change correspond to 360 degrees turn. Thus, a turn by :D degrees means that the frequency is multiplied by the factor 2^(:D/360). For example, a 60-degree turn is a full step; a right-angle turn is a minor third; a 120-degree turn is a major third; and so on. Note that the dragon "McWorter's Pentigree" uses angles of 72 degrees; this interval, 2^(1/5), is not used in Western music. Do you like the sound? In the programs, the length of the note played is simply proportional to the length of the line segment. But a more mathematically correct system would be to make the time to traverse the whole curve remain constant when :DEPTH is changed. (So the duration of the note is proportional to a power of the length of the segment. The exponent used here is the "fractal dimension".) For example, in the Koch curve, above, the fractal dimension is s = (log 4)/(log 3). So when :DEPTH is increased by 1, the length of the line segments is decreased by factor 1/3, and the length of the notes should be decreased by factor (1/3)^s = 1/4. The number of line segments is increased by a factor of 4, so the total playing time is unchanged. The actual "fractal" is the self-similar curve that is the limit as :DEPTH increases without bound. In practice, when :DEPTH gets large enough, the pictures no longer change; so the picture gives us a good idea of the fractal curve itself. An interesting experiment would be to do this with the music. I have not been able to reach this goal on my Macintosh, since the Mac will not play notes shorter than a certain length. (There is some literature on "fractal music". It is NOT this.) -------------------------------------------------------------------- Gerald A. Edgar April, 1990 Dept. of Mathematics The Ohio State University Columbus, OH 43210 edgar@math.ohio-state.edu ----------------------------------------------------------------------- ----------------------------------------------------------------------- ;; Dragon curves with music. Logo source code. ;; The curves are: ;; 1 McWorter's Pentigree ;; 2 2 Dimensional Curve ;; 3 Triadic (SNOWFLAKE) Curve ;; 4 Quadric Curve ;; 5 Pinwheel Curve ;; 6 Hexomino Curve ;; 7 Gosper Curve (FLOWSNAKE) ;; 8 Arrow Curve ;; 9 Peano Curve ;; Sample usage: FRACTAL6 100 2 ;; This draws the Hexomino curve with :size 100 and :depth 2 ;; :size is the size of the curve, ;; :depth is the complexity of the curve (simplest is 0) ;; Or try my preset values to start with: for example ;; FRACTALS 6 for the Hexomino Curve. (Replace 6 by any ;; digit 1 to 9 for the other curves.) ;; --------------------------------------------------------------- ;; Tested on a Macintosh using Object Logo. ;; For other versions of Logo, you may need to make changes. ;; For example the following: ;; CS ;; clears the screen. It may be called CG; if so, define it: ;; TO CS ;; CG ;; END ;; TOOT :F :A :D ;; produces a note with frequency :F Hertz; ;; amplitude :A (0 to 255); duration :D seconds ;; Toot is called only by TOOTX with a duration :X/:DENOM, ;; so the speed can be adjusted by changing the value of ;; "DENOM. If your TOOT has duration measured in 60ths of ;; a second, then redefine TOOTX as follows: ;; TO TOOTX :X ;; TOOT :FREQ 100 :X/(:DENOM/60) ;; END ;; The starting frequency is :FREQ, so the pitch can be adjusted ;; by changing the value of "FREQ. ;; G. A. Edgar April, 1990 ;; Dept. of Mathematics ;; The Ohio State University ;; Columbus, OH 43210 ;; edgar@math.ohio-state.edu ;; --------------------------------------------------------------- MAKE "genlist [3 5 4 4 3 3 3 3 3] MAKE "denomlist [200 175 50 50 100 80 150 80 65] MAKE "denom 50 HT TO SETUP CS PU SETPOS [-100 -20] PD SETH 90 MAKE "freq 440 END setup to fractal1 :size :depth if :depth = 0 [forward :size tootx :size stop] leftmusic 36 fractal1 :size/2.62 :depth-1 leftmusic 72 fractal1 :size/2.62 :depth-1 rightmusic 144 fractal1 :size/2.62 :depth-1 rightmusic 72 fractal1 :size/2.62 :depth-1 leftmusic 72 fractal1 :size/2.62 :depth-1 leftmusic 72 fractal1 :size/2.62 :depth-1 rightmusic 36 end TO FRACTAL2 :SIZE :DEPTH IF :DEPTH = 0 [FD :SIZE TOOTX :SIZE STOP] FRACTAL2 :SIZE / 2 :DEPTH - 1 leftmusic 90 FRACTAL2 :SIZE / 2 :DEPTH - 1 rightmusic 180 FRACTAL2 :SIZE / 2 :DEPTH - 1 leftmusic 90 FRACTAL2 :SIZE / 2 :DEPTH - 1 END TO FRACTAL3 :SIZE :DEPTH IF :DEPTH = 0 [FD :SIZE TOOTX :SIZE STOP] FRACTAL3 :SIZE / 3 :DEPTH - 1 leftmusic 60 FRACTAL3 :SIZE / 3 :DEPTH - 1 rightmusic 120 FRACTAL3 :SIZE / 3 :DEPTH - 1 leftmusic 60 FRACTAL3 :SIZE / 3 :DEPTH - 1 END TO FRACTAL4 :SIZE :DEPTH IF :DEPTH = 0 [FD :SIZE TOOTX :SIZE STOP] FRACTAL4 :SIZE / 3 :DEPTH - 1 leftmusic 90 FRACTAL4 :SIZE / 3 :DEPTH - 1 rightmusic 90 FRACTAL4 :SIZE / 3 :DEPTH - 1 rightmusic 90 FRACTAL4 :SIZE / 3 :DEPTH - 1 leftmusic 90 FRACTAL4 :SIZE / 3 :DEPTH - 1 END TO FRACTAL5 :SIZE :LEVEL PINWHEEL :SIZE :LEVEL END TO FRACTAL6 :SIZE :LEVEL HEX :SIZE :LEVEL END TO FRACTAL7 :SIZE :DEPTH FLOW 0.9 * :SIZE "TRUE :DEPTH END TO FRACTAL8 :SIZE :LEVEL ARROW :SIZE :LEVEL END TO FRACTAL9 :SIZE :LEVEL PEANO 0.9 * :SIZE :LEVEL 1 END TO FRACTALS :TYPE SETUP make "denom item :type :denomlist RUN ( SE (WORD "FRACTAL :type) 200 (item :type :genlist) ) END TO TOOTX :X toot :freq 100 :X/:denom END TO PEANO :S :LEVEL :P LOCAL "A IF :LEVEL = 0 [FD :S TOOTX :S STOP] MAKE "A 0.25 * 2.236067977 * :S leftmusic 60 * :P PEANO :S / 3 :LEVEL - 1 -:P PEANO :S / 3 :LEVEL - 1 :P rightmusic 60 * :P PEANO :S / 3 :LEVEL - 1 :P rightmusic 60 * :P PEANO :S / 3 :LEVEL - 1 :P rightmusic 150 * :P PEANO :A / 3 :LEVEL - 1 :P PEANO :A / 3 :LEVEL - 1 -:P leftmusic 60 * :P PEANO :A / 3 :LEVEL - 1 -:P leftmusic 60 * :P PEANO :A / 3 :LEVEL - 1 -:P leftmusic 90 * :P PEANO :S / 3 :LEVEL - 1 :P rightmusic 150 * :P PEANO :A / 3 :LEVEL - 1 :P PEANO :A / 3 :LEVEL - 1 -:P leftmusic 150 * :P PEANO :S / 3 :LEVEL - 1 -:P PEANO :S / 3 :LEVEL - 1 :P END TO 7LB :N :DIR :L rightmusic 79.107 FLOW :N NOT :DIR :L leftmusic 60 FLOW :N :DIR :L FLOW :N :DIR :L leftmusic 120 FLOW :N :DIR :L leftmusic 60 FLOW :N NOT :DIR :L rightmusic 120 FLOW :N NOT :DIR :L rightmusic 60 FLOW :N :DIR :L leftmusic 19.107 END TO 7LF :N :DIR :L rightmusic 19.107 FLOW :N :DIR :L leftmusic 60 FLOW :N NOT :DIR :L leftmusic 120 FLOW :N NOT :DIR :L rightmusic 60 FLOW :N :DIR :L rightmusic 120 FLOW :N :DIR :L FLOW :N :DIR :L rightmusic 60 FLOW :N NOT :DIR :L leftmusic 79.107 END TO FLOW :N :DIR :L IF :L = 0 [FD :N TOOTX :N STOP] IFelse :DIR [7LF :N / SQrt 7 :DIR :L - 1] [7LB :N / SQrt 7 :DIR :L - 1] END TO FLOWSNAKE cs ht PU SETPOS [30 -20] PD REPEAT 3 [FLOW 90 "TRUE 3 rightmusic 120] leftmusic 120 FLOW 90 "TRUE 3 rightmusic 120 FLOW 90 "TRUE 3 FLOW 90 "TRUE 3 END TO HEX :SIZE :LEVEL IF :LEVEL = 0 [FD :SIZE TOOTX :SIZE STOP] HEX 0.25 * :SIZE :LEVEL - 1 leftmusic 60 HEX 0.25 * :SIZE :LEVEL - 1 rightmusic 60 HEX 0.25 * :SIZE :LEVEL - 1 rightmusic 60 HEX 0.25 * :SIZE :LEVEL - 1 rightmusic 120 HEX 0.25 * :SIZE :LEVEL - 1 HEX 0.25 * :SIZE :LEVEL - 1 leftmusic 120 HEX 0.25 * :SIZE :LEVEL - 1 leftmusic 60 HEX 0.25 * :SIZE :LEVEL - 1 leftmusic 60 HEX 0.25 * :SIZE :LEVEL - 1 rightmusic 60 HEX 0.25 * :SIZE :LEVEL - 1 END TO PINWHEEL :SIZE :LEVEL IF :LEVEL = 0 [FD :SIZE TOOTX :SIZE STOP] leftmusic 30 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 rightmusic 60 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 leftmusic 60 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 leftmusic 120 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 leftmusic 120 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 leftmusic 0 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 rightmusic 120 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 rightmusic 120 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 rightmusic 60 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 leftmusic 60 PINWHEEL 0.288675 * :SIZE :LEVEL - 1 rightmusic 30 END TO ARROW :SIZE :LEVEL IF :LEVEL = 0 [FD :SIZE TOOTX :SIZE STOP] ARROW 0.25 * :SIZE :LEVEL - 1 ARROW 0.25 * :SIZE :LEVEL - 1 leftmusic 120 ARROW 0.25 * :SIZE :LEVEL - 1 rightmusic 120 ARROW 0.25 * :SIZE :LEVEL - 1 rightmusic 60 ARROW 0.25 * :SIZE :LEVEL - 1 rightmusic 120 ARROW 0.25 * :SIZE :LEVEL - 1 leftmusic 60 ARROW 0.25 * :SIZE :LEVEL - 1 leftmusic 120 ARROW 0.25 * :SIZE :LEVEL - 1 leftmusic 60 ARROW 0.25 * :SIZE :LEVEL - 1 rightmusic 60 ARROW 0.25 * :SIZE :LEVEL - 1 END to leftmusic :x left :x make "freq :freq/power 2 (:x/360) end to rightmusic :x right :x make "freq :freq*power 2 (:x/360) end