-
Code- one of many versions.
You specify the axiom and rule and angle, and it iteratively creates the long string of moves to be drawn,
'QO fractal generator version f
nomainwin
UpperLeftX = 10
UpperLeftY = 2
WindowWidth =1020
WindowHeight = 730
textbox #w.text, 2, 2,1000, 30
graphicbox #w.graphic, 2, 40,1000, 550
texteditor #w.tedit, 2, 600,1000, 200
button #w.b, "Draw", [doit], UL, 930, 50, 50, 30
open "QO Fractal Generator" for window_nf as #w
#w "trapclose quit"
#w.graphic "size 2 ; color black ; cls ; fill darkblue"
#w "font courier_new 8"
'axiom$ = "F"
axiom$ = "F"
rule$ = "F-F++F-F"
'rule$ = "F-F+F+F-F"
n = 0
pi = 4 *atn( 1)
angle = 60 *pi /180
'angle = 90 *pi /180
[doit]
n =n +1
if n >7 then call quit h$
totalx = 0
totaly = 0
newrule$ = ""
direction = 0 ' NB in RADIANS
state =1
#w.tedit "Iteration # ";
#w.tedit n;
#w.tedit " & rule = "
l =len( axiom$)
for k =1 to l /128
#w.tedit mid$( axiom$, k, 128)
next k
for i =1 to len( axiom$)
ch$ =mid$( axiom$, i, 1)
select case ch$
case "+"
direction =direction +angle
newrule$ =newrule$ +"+"
case "-"
direction =direction -angle
newrule$ =newrule$ +"-"
case "F"
newrule$ =newrule$ +rule$
totalx = totalx +cos( direction)
totaly = totaly +sin( direction)
end select
next i
op$ ="Total x = " +str$( int( totalx)) +" & total y = " +str$( int( totaly))
#w.text op$
ste =440 /totalx
xx =10: yy =250: direction =0
#w.graphic "cls ; fill darkblue"
#w.graphic "up ; goto 20 500 ; down ; north; turn 90"
'#w.graphic "color "; str$( 40 +30 *n); " "; str$( 40 +30 *n); " 50"
'if state =1 then state =0 else state =1
#w.graphic "color "; word$( "black white", state +1)
#w.graphic "size "; 1 +2 *( 7 -n)
for i =1 to len( axiom$)
in$ =mid$( axiom$, i, 1)
select case in$
case "F"
xx =xx +ste *cos( direction)
yy =yy +ste *sin( direction)
case "+"
direction =direction +angle
case "-"
direction =direction -angle
end select
#w.graphic "goto "; str$( int( 2 *xx)); " "; str$( 2 *int( yy))
scan
#w.graphic "flush ; getbmp scr 0 0 1000 550"
bmpsave "scr", "IFSrule" +rule$ +str$( n) +".bmp"
next i
axiom$ =newrule$
timer 1000, [o]
wait
[o]
timer 0
wait
sub quit h$
close #w
end
end sub
We've had several visits to this, including for Rosetta Code. There are three variations that produce the same figure but in very different ways.
Draw scaled and moved triangles
Do by IFS ( iterated file function system)
Draw as a single non-imtersecting line curve.
While I've coded all ways, this is the latter one. Was writing in LB5 on Linux and found one or two glitches.
I was particularly pleased by the graphic created by overlaying each iteration in a different colour and with thinner lines to match the greater resolution. Worth watching it ruin!
' ***********************************************************************
' ** **
' ** sierpinskiArrow2alteredHoriz.bas tenochtitlanuk 24/06/30 **
' ** **
' ***********************************************************************
nomainwin
global pi, TX, TY, Ttheta
TX =400: TY =350: Ttheta =0 ' screen centre, pointing North/up. ' <<<<<<<<<<<<<<<<<<<<<<<<<
pi =4 *atn( 1)
WindowWidth = 760
WindowHeight = 900
open "Sierpinski arrowhead" for graphics_nsb as #wg
#wg "trapclose quit"
#wg "color cyan ; font Arial bold 18"
#wg "cls ; down ; fill blue ; backcolor blue ; flush"
'width =11
for i =0 to 11
'#wg "cls ; down ; fill blue ; backcolor blue ; flush" ' rem this line to see each iteration on its own...
#wg "color "; word$( "red,white,yellow,180 180 80,brown,cyan,darkcyan,130 255 120,131 130 255,darkgray,darkgreen,darkpink,darkred,green,lightgray,palegray,pink,blue", i +1, ",")
#wg "up ; goto 20 "; 30 +20 * i; " ; down"
#wg "\order "; i
#wg "size "; max( 1, 41 -5 *i)
TX =710: TY =850: Ttheta =-90
call SierpinskiArrowhead i, 800 ' order, length
#wg "flush"
#wg "getbmp scr 0 0 1400 900"
'bmpsave "scr", "scr3/SierpinskiArrow" +str$( i) +".bmp"
call Sleep 2000
next i
wait
sub quit h$
close #wg
end
end sub
sub Sleep ms
timer ms, [k]
wait
[k]
timer 0
end sub
sub SierpinskiArrowhead order, length
if ( order and 1) =0 then ' order is even..
call curve order, length, 60
else
call turn -60
call curve order, length, 60
end if
end sub
sub curve order, length, angle
scan
if order =0 then
'#wg "go "; length
call forward length
else
'#wg "turn " +str$( angle)
call curve order -1, length /2, 0 -angle
call turn angle
call curve order -1, length /2, 0 +angle
'#wg "turn " +str$( angle)
call turn angle
call curve order -1, length /2, 0 -angle
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)
if Theta <0 then Ttheta =Ttheta +360
Ttheta =Ttheta 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
' <<<<<<<<<<<<<<<<<<<<<<<<