In a moment of madness I wondered if I could create a sine wave which was modulated at a higher frequency- but transverse to its current direction ( imagine bending a wire into a whole lot of small sin waves, then bending that wire bigger amounts but of much longer wavelength.) I thought turtle graphics would help.
Here's my first attempt- I got it wrong!!
More accurate turtle graphics WOULD have helped. But LB's native commands can't be used for accurate graphics since they round off distances and angles.
Luckily I wrote replacements long ago- so the errors don't accumulate as in the first attempt. Long time LB user. See my website! diga.me.uk
Basically, here's a warning to LB-ers not to use inbuilt turtle commands for accurate results. It stores nearest screen position and/or an integer angle, so each move/draw can be wrong by up to half a pixel. The next move then starts from the wrong position/angle, and in figures with finer detail than a large square it goes badly and unpredictably wrong. Example is my Koch curve example.. see rosettacode.org/wiki/Koch_curve
My replacements for draw and turning store x, y and orientation as floats, so errors should not exceed one pixel.
nomainwin
' Demonstrates turtle drawn directly, avoiding LB's turtle errors and giving
' direct access to turtle's position/heading, saved in globals.
global pi, TX, TY, Ttheta
pi =4 *atn( 1): TX =102: TY =252: Ttheta =0 ' screen left, centred vertically, pointing west
nomainwin
WindowWidth =1100: WindowHeight =700
open "Demo Koch Snowflake" for graphics_nsb as #wg
#wg "trapclose quit"
#wg "backcolor white"
#wg "goto 2 2 ; down ; box 1202 702 ; up"
call graticule
l =160
for d =0 to 5
TX = 180 *d +26 ' <<<< start position, direction of each Koch curve.
TY = 87 *d +51
Ttheta =0
for side =1 to 3
call fwd l, d
call turn 120
next side
#wg "flush"
next d
#wg "flush"
'#wg "print 1110"
wait
sub quit h$
call save$
close #h$
end
end sub
sub fwd length, depth
scan
if depth <= 0 then
call forward length
else
call fwd length /3, depth -1: call turn -60
call fwd length /3, depth -1: call turn 120
call fwd length /3, depth -1: call turn -60
call fwd length /3, depth -1
end if
end sub
function sinRad( a)
sinRad =sin( a *pi /180)
end function
function cosRad( a)
cosRad =cos( a *pi /180)
end function
'sub draw lifted, x, y
' if lifted =0 then #wg "up" else #wg "down"
' #wg "line "; TX; " "; TY; " "; x; " "; y
' Ttheta =atan2( x -TX, TY -y) *180 /pi ' NB DEGREES.
' TX =x
' TY =y
'end sub
sub turn angle ' increment/update global turtle direction ( in DEGREES)
Ttheta =( Ttheta +angle) 'mod 360
end sub
sub forward s
dx =s *cosRad( Ttheta)
dy =s *sinRad( Ttheta)
#wg "down ; line "; TX; " "; TY; " "; TX +dx; " "; TY +dy; " ; up"
TX =TX +dx
TY =TY +dy
end sub
function atan2( x, y)
Result$ = "Undetermined"
If ( x = 0) and ( y > 0) Then atan2 = pi / 2: Result$ = "Determined"
If ( x = 0) and ( y < 0) Then atan2 = 3 * pi / 2: Result$ = "Determined"
If ( x > 0) and ( y = 0) Then atan2 = 0: Result$ = "Determined"
If ( x < 0) and ( y = 0) Then atan2 = pi: Result$ = "Determined"
If Result$ = "Determined" Then [End.of.function]
BaseAngle = Atn( abs( y) /abs( x))
If (x > 0) and (y > 0) Then atan2 = BaseAngle
If (x < 0) and (y > 0) Then atan2 = pi -BaseAngle
If (x < 0) and (y < 0) Then atan2 = pi +BaseAngle
If (x > 0) and (y < 0) Then atan2 = 2*pi -BaseAngle
[End.of.function]
end function
sub graticule
#wg "down"
for x =0 to 1500 step 50 ' draw vertical graticule lines
'if x =( Tx -2) then #wg "size 4 ; color red" else #wg "size 2 ; color white"
#wg "line "; x +2; " "; 2; " "; x +2; " "; 702
next x
for y =0 to 800 step 50
#wg "line "; 2; " "; y +2; " "; 1202; " "; y +2
next y
#wg "up"
end sub
sub saveS
#wg "flush"
#wg "getbmp scr 0 0 1110 710"
filedialog "Save as ", "*.bmp", fn$
bmpsave "scr", fn$
end sub
Anatoly ( tsh3) commented- 'I remember having troubles drawing Pythagoras tree with turtle So I found it and then fixed with John's code.
Change..
#gr "turn -90"
#gr "go ";l
#gr "turn 45"
--
.. to ..
call turn -90
call forward l
call turn 45
So a recursive figure now renders correctly.
--
'some recursive drawing
global minLength
minLength = 5
nomainwin
WindowWidth = 640
WindowHeight = 480
UpperLeftX = (DisplayWidth - WindowWidth )/2
UpperLeftY = (DisplayHeight - WindowHeight )/2
open "gr" for graphics_nsb as #gr
#gr "trapclose [quit]"
#gr "home ; down ; posxy midX midY"
width = 2*midX : height = 2*midY
l = 100
#gr "place ";midX-l/2;" ";400
#gr "turn 90"
' print l
call box l
#gr "color red; go 10"
wait
sub box l
'recursion exit condition
scan
if l < minLength then
'it should left in same position as if drawn
#gr "go ";l
exit sub
end if
'draw a box
for i = 1 to 4
#gr "color ";word$("red green blue black",i)
#gr "go ";l
#gr "turn -90"
next
'set place for a next box
#gr "turn -90"
#gr "go ";l
#gr "turn 45"
'call recursively
call box l/sqr(2)
'goto next position
#gr "turn 90"
'call recursively
call box l/sqr(2)
'now set to back position...
#gr "turn 45"
#gr "go ";l
#gr "turn -90"
end sub
[quit]
close #gr
end
fixed code
Copy Code
'some recursive drawing
'+Turtle fix by Tenochtitlanuk
' Demonstrates turtle drawn directly, avoiding LB's turtle errors and giving
' direct access to turtle's position/heading, saved in globals.
global pi, TX, TY, Ttheta
pi =4 *atn( 1): TX =102: TY =252: Ttheta =0 ' screen left, centred vertically, pointing west
' // ---------------------------------
global minLength
minLength = 4
nomainwin
WindowWidth = 640
WindowHeight = 480
UpperLeftX = (DisplayWidth - WindowWidth )/2
UpperLeftY = (DisplayHeight - WindowHeight )/2
open "gr" for graphics_nsb as #gr
#gr "trapclose [quit]"
#gr "home ; down ; posxy midX midY"
width = 2*midX : height = 2*midY
l = 100
TX =midX-l/2: TY =400
' print l
call box l
#gr "color red; go 10"
wait
sub box l
'recursion exit condition
scan
if l < minLength then
'it should left in same position as if drawn
call forward l
exit sub
end if
'draw a box
for i = 1 to 4
#gr "color ";word$("red green blue black",i)
call forward l
call turn -90
next
'set place for a next box
call turn -90
call forward l
call turn 45
'call recursively
call box l/sqr(2)
'goto next position
call turn 90
'call recursively
call box l/sqr(2)
'now set to back position...
call turn 45
call forward l
call turn -90
end sub
[quit]
close #gr
end
'-------------------------------------------------
'Turtle fix by Tenochtitlanuk, with globals above
sub turn angle ' increment/update global turtle direction ( in DEGREES)
Ttheta =( Ttheta +angle) 'mod 360
end sub
sub forward s
dx =s *cosRad( Ttheta)
dy =s *sinRad( Ttheta)
#gr "down ; line "; TX; " "; TY; " "; TX +dx; " "; TY +dy; " ; up"
TX =TX +dx
TY =TY +dy
end sub
function sinRad( a)
sinRad =sin( a *pi /180)
end function
function cosRad( a)
cosRad =cos( a *pi /180)
end function