I thought it would be cool if you had a vertical line segment, shrunk it, rotated it, and added it to previous versions of itself over and over again.
Here are some pictures generated with this algorithm:
Basically, each pattern is described by two values: Theta and scale. Any two adjacent lines from a "theta" degree angle, and each line after any other line is "scale" times smaller.
So long as "scale" is less than one, there is a final point (a point after you iterate this an infinite number of times, and isn't at infinity).
This program makes pictures like that! The red circle you can see - if it isn't covered up by lines - is the final point. Which you CAN calculate. I used an infinite series of matrices, because that's just cool.
controls:
W and S keys control "zoom"
UP and DOWN arrow keys control "scale" (limited to in between 0 and 1)
LEFT and RIGHT arrow keys control "theta".
global a as float
global b as float
global c as float
global d as float
//matrix:
//[a b]
//[c d]
global PPU as float
PPU=50
global theta as float
global scale as float
global ret_x as float
global ret_y as float
theta=10
scale=.9
sync on
sync rate 60
scaleinterp as float
scaleinterp=0.0
do
cls
text 0,0,"(up/down) Scale: "+str$(scale)
text 0,16,"(left/right) Theta: "+str$(scale)
text 0,32,"(w/s) Pixels Per Unit: "+str$(PPU)
text 0,48,"Screen FPS: "+str$(screen fps())
maxnum#=-log(PPU)/log(scale)
numtodraw=ceil(maxnum#)
if numtodraw>2500 then numtodraw=2500
if numtodraw<200 then numtodraw=200
drawSwirl(numtodraw)
mult#=1.0/screen fps()
if shiftkey() then mult#=mult#*.05
if rightkey() then inc theta,180.0*mult#
if leftkey() then dec theta,180.0*mult#
if upkey() then inc scaleinterp,2.0*mult#
if downkey() then dec scaleinterp,2.0*mult#
if scaleinterp> 3.5 then scaleinterp= 3.5
if scaleinterp<-3.5 then scaleinterp=-3.5
if keystate(17) then inc PPU,30.0*mult#
if keystate(31) then dec PPU,30.0*mult#
scale=cNorm(scaleinterp)
sync
loop
end
//cumulative normal distribution
//seful for calculating a value inbetween 0 and 1
//pulled from http://finance.bi.no/~bernt/gcc_prog/recipes/recipes/node23.html
function cNorm(x as float)
if x>5.0 then exitfunction 1.0
if x<-5.0 then exitfunction 0.0
b1#=.31938153
b2#=-.356563782
b3#=1.781477927
b4#=-1.821255978
b5#=1.330274429
p#=.2316419
c2#=.3989423
a2#=absolut(x)
t#=1.0/(1.0+a2#*p#)
ba#=c2#*exp((-x)*(x/2.0))
n#=((((b5#*t#+b4#)*t#+b3#)*t#+b2#)*t#+b1#)*t#
n#=1.0-ba#*n#
if x<0.0 then n#=1.0-n#
endfunction n#
function absolut(num as float)
if num>0 then exitfunction num
num=-num
endfunction num
function drawSwirl(numIterations as integer)
tempx as float
tempy as float
lastx as float
lasty as float
getInterpEnd()
ink rgb(255,0,0)
tempx=ret_x
tempy=ret_y
coordinatesToScreen(tempx,tempy)
circle ret_x,ret_y,10
tempx=0
tempy=1
lastx=0
lasty=0
screenLine(tempx,tempy,lastx,lasty)
lastx=tempx
lasty=tempy
ink rgb(255,255,255)
for n=1 to numIterations
getInterpPoint(n)
tempx=lastx+ret_x
tempy=lasty+ret_y
screenLine(lastx,lasty,tempx,tempy)
lastx=tempx
lasty=tempy
next n
endfunction
function screenLine(x1 as float, y1 as float, x2 as float, y2 as float)
coordinatesToScreen(x1,y1)
tempx=ret_x
tempy=ret_y
coordinatesToScreen(x2,y2)
d3d_line tempx,tempy,ret_x,ret_y
endfunction
function coordinatesToScreen(x as float, y as float)
ret_x=x*PPU+screen width()/2
ret_y=y*PPU+100
endfunction
function getInterpEnd()
detnum#=scale*scale-2*scale*cos(theta)+1
ret_x=(sin(theta)*scale)/detnum#
ret_y=1-(scale*scale-scale*cos(theta))/detnum#
endfunction
function getInterpPoint(n as integer)
findTN(n)
ret_x=b
ret_y=d
endfunction
function findTN(n as integer)
temps#=intPow(scale,n)
a= temps#*cos(n*theta)
b= temps#*sin(n*theta)
c=-temps#*sin(n*theta)
d= temps#*cos(n*theta)
endfunction
function intPow(myval as float, pow as integer)
retval#=1
for n=1 to pow
retval#=retval#*myval
next n
endfunction retval#