Lissajous figures appear when analyzing the motion of perpendicular vibrations with different frequencies. Basically, if you do a parametric plot with Y=A*Sin(w*t+y0), and X=B*Sin(v*t+x0), you get a lissajous figure. A and B are the magnitudes of the vibrations, and v and w are the angular velocities (2 Pi times the frequency). These can be visualized as rotations of a circle.
This is what the code draws:
sliders change the radii (A and B), and the angular velocities (v and w)
[edit]
updated so you can also change the initial phase, y0 and x0.
[edit2]
and the really interesting ones to see are the ones where v/w is rational. For example, if v was pi and w was 1, the pattern would never repeat! Sorry I didn't give any easy way to control v/w, you'll have to hunt around for cool ones.
`%Project Title%
`lissajous.dba
`====================
type sliderbar
txt as string //displayed as "my text |---o---| (slider value)"
x as integer //x position of the text
y as integer //y position of the text
xpos as integer //x position of the slider
ypos as integer //y position of the slider (constant)
barwidth as integer //width of the bar you grab onto (1=a vertical line)
height as integer //height of the bar
minpos as integer//leftmost position that xpos can be
maxpos as integer //rightmost position that xpos can be
mouseoffset as integer //used for click/drag calculations
state as integer //clicked, not clicked
color as dword //box color, not text color
rval as float //the value that the slider should return at maximum dragging
lval as float
endtype
global w as integer
global h as integer
w=screen width()
h=screen height()
dim sliderbars(-1) as sliderbar
global mousestate as integer
mousestate=0 // not pressed
//1= newly pressed
//2= held
//3= newly released
global mousexpos as integer
global mouseypos as integer
mousexpos=0
mouseypos=0
type oscillatortype
angvel as float
xpos as float
ypos as float
radius as float
initialphase as float
endtype
dim oscillator(1) as oscillatortype
oscillator(0).xpos=100
oscillator(0).ypos=200
oscillator(0).radius=100
oscillator(0).initialPhase=120
oscillator(0).angvel=1
oscillator(1).xpos=500
oscillator(1).ypos=450
oscillator(1).radius=50
oscillator(1).initialPhase=240
oscillator(1).angvel=2
gosub initSliderControls
global time as float
do
cls
time=time+.5
if time>5000 then time=0
updateMouseCode()
updatesliderBars()
drawLissajousbox()
drawSliderBars()
drawOscillator(0)
drawOscillator(1)
drawlissajousfigure()
oscillator(0).angvel=getsliderval(0)
oscillator(0).radius=getsliderval(1)
oscillator(0).initialphase=getsliderval(2)
oscillator(1).angvel=getsliderval(3)
oscillator(1).radius=getsliderval(4)
oscillator(1).initialphase=getsliderval(5)
sync
loop
sync
wait key
end
function drawLissajousFigure()
lock pixels
ink rgb(0,255,0),0
for t#=0 to 5000 step .5
dot getlissajouspointx(t#),getlissajouspointy(t#)
next t#
unlock pixels
endfunction
function drawLissajousBox()
xstart0=oscillator(0).xpos+oscillator(0).radius*cos(oscillator(0).angvel*time+oscillator(0).initialPhase)
ystart0=oscillator(0).ypos-oscillator(0).radius*sin(oscillator(0).angvel*time+oscillator(0).initialPhase)
xstart1=oscillator(1).xpos+oscillator(1).radius*cos(oscillator(1).angvel*time+oscillator(1).initialPhase)
ystart1=oscillator(1).ypos-oscillator(1).radius*sin(oscillator(1).angvel*time+oscillator(1).initialPhase)
ymin0=oscillator(0).ypos-oscillator(0).radius
ymax0=oscillator(0).ypos+oscillator(0).radius
xmin1=oscillator(1).xpos-oscillator(1).radius
xmax1=oscillator(1).xpos+oscillator(1).radius
ink rgb(255,255,255),0
drawlinebox(xmin1,ymin0,xmax1-xmin1,ymax0-ymin0)
line xstart0,ystart0,xstart1,ystart0
line xstart1,ystart0,xstart1,ystart1
endfunction
function getLissajousPointX(t as float)
xstart1=oscillator(1).xpos+oscillator(1).radius*cos(oscillator(1).angvel*t+oscillator(1).initialPhase)
endfunction xstart1
function getLissajousPointY(t as float)
ystart0=oscillator(0).ypos-oscillator(0).radius*sin(oscillator(0).angvel*t+oscillator(0).initialPhase)
endfunction ystart0
function drawOscillator(n)
drawHarmonicOscillator(oscillator(n).xpos,oscillator(n).ypos,oscillator(n).radius,oscillator(n).angvel*time+oscillator(n).initialphase)
endfunction
function drawHarmonicOscillator(x,y,radius,phase as float)
ink rgb(255,255,255),0
circle x,y,radius
ink rgb(255,0,0),0
circle x+radius*cos(phase),y-radius*sin(phase),5
endfunction
initSliderControls:
addsliderbar(0,0,40,400, rgb(255,0,255),0,6.29,"angvel 0:")
addsliderbar(0,16,40,400,rgb(0,0,255) ,10,300,"radius 0:")
addsliderbar(0,32,40,400,rgb(0,0,255) ,10,300,"phase0 0:")
addsliderbar(0,48,40,400,rgb(0,255,0) ,0,6.29,"angvel 1:")
addsliderbar(0,64,40,400,rgb(255,0,0) ,10,300,"radius 1:")
addsliderbar(0,80,40,400,rgb(0,0,255) ,10,300,"phase0 1:")
return
//slider bars for dragging & number changing
function addSliderBar(x,y,barwidth,width, color as dword, lnum as float, rnum as float, txt as string)
strw=text width(txt)
strh=text height(txt)
array insert at bottom sliderbars()
n=array count(sliderbars())
sliderbars(n).x=x
sliderbars(n).y=y
sliderbars(n).xpos=x+strw+10
sliderbars(n).ypos=y+3
sliderbars(n).height=strh-6
sliderbars(n).barwidth=barwidth
sliderbars(n).color=color
sliderbars(n).maxpos=x+strw+10+width
sliderbars(n).state=0 //unselected
sliderbars(n).mouseoffset=0
sliderbars(n).lval=lnum
sliderbars(n).rval=rnum
sliderbars(n).minpos=x+strw+10
sliderbars(n).txt=txt
endfunction
function updateMouseCode()
mousexpos=mousex()
mouseypos=mousey()
local newmousestate as integer
if mouseclick()
if mousestate=0 or mousestate=3 //not pressed or newly released
newmousestate=1 //newly pressed
endif
if mousestate=1 or mousestate=2 //newly pressed or held
newmousestate=2 //held
endif
else
if mousestate=0 or mousestate=3 //not pressed or newly released
newmousestate=0 //not pressed
endif
if mousestate=1 or mousestate=2 //newly pressed or held
newmousestate=3 //newly released
endif
endif
mousestate=newmousestate
endfunction
function drawLineBox(x,y,width,height)
line x,y,x+width,y
line x,y+height,x+width,y+height
line x,y,x,y+height
line x+width,y,x+width,y+height
endfunction
function drawSliderBars()
for n=0 to array count(sliderbars())
text sliderbars(n).x,sliderbars(n).y,sliderbars(n).txt
box sliderbars(n).xpos,sliderbars(n).ypos,sliderbars(n).xpos+sliderbars(n).barwidth,sliderbars(n).ypos+sliderbars(n).height,sliderbars(n).color,sliderbars(n).color,sliderbars(n).color,sliderbars(n).color
text sliderbars(n).maxpos+10,sliderbars(n).y,str$(getsliderval(n))
drawLineBox(sliderbars(n).minpos,sliderbars(n).ypos,sliderbars(n).maxpos-sliderbars(n).minpos,sliderbars(n).height)
next n
endfunction
function getsliderval(n as integer)
v#=(sliderbars(n).xpos-sliderbars(n).minpos)*1.0/(sliderbars(n).maxpos-sliderbars(n).minpos)*(sliderbars(n).rval-sliderbars(n).lval)+sliderbars(n).lval
endfunction v#
function updateSliderBars()
for n=0 to array count(sliderbars())
//mousestate 1 is newly pressed
if mousestate=1 and mousexpos>sliderbars(n).xpos
if mousexpos<sliderbars(n).xpos+sliderbars(n).barwidth and mouseypos>sliderbars(n).ypos and mouseypos<sliderbars(n).ypos+sliderbars(n).height
sliderbars(n).state=1 //selected
sliderbars(n).mouseoffset=mousexpos
endif
endif
if mousestate=0 or mousestate=3
sliderbars(n).state=0 //unselected
sliderbars(n).mouseoffset=0
endif
if mousestate=2 and sliderbars(n).state=1
sliderbars(n).xpos=sliderbars(n).xpos+mousexpos-sliderbars(n).mouseoffset
sliderbars(n).mouseoffset=mousexpos
endif
if sliderbars(n).xpos>sliderbars(n).maxpos then sliderbars(n).xpos=sliderbars(n).maxpos
if sliderbars(n).xpos<sliderbars(n).minpos then sliderbars(n).xpos=sliderbars(n).minpos
next n
endfunction
[edit3]
And this is an awesome animation (not mine) showing other types of lissajous figures with different waveforms (so instead of the dots traversing on a circle with constant angular velocity, they move on some other weird shape with constant angular velocity)