I use the following solution:
Code: Select all
'Find nearest via Archimedean spiral
'by Dutchman, january 2017
/*
In polar coordinates (r,phi) the spiral can be described
by the equation r=a+b*phi with real numbers a and b.
Parameter a determines the starting point,
while b controls the distance between successive turnings.
*/
/*
Problem to be solved:
For the program "Brownian tree"
Particles are sprites
A circular particle with corediameter 'size' and larger halo.
Its halo has touched a random positioned "tree" with diameter 'size'
Connect the core to the touched point of "tree"
*/
wait=0.1 ' pause time
OPTION SPRITE POS CENTRAL
OPTION BASE 1
' --- constants
pi=ARG(-1)
pipi=2*pi
GET SCREEN SIZE sw,sh
mid=sw/2+1i*sh/2
DIM pos(1) ' position of sprite 1
pos(1)=sw/2+1i*sh/2 'startpostion of particle
size=sw/15
halo=5*size
showconnect=1
show=1 ' visibility of "core"
GOSUB Initialise
SPRITE 1 ALPHA 0.7
DO UNTIL BUTTON_PRESSED("step")
test=1
connect(1,size,sw)
DO UNTIL BUTTON_PRESSED("step")
test=0
DO
GRAPHICS CLEAR 0.5,0.5,0.5
SPRITE 1 AT REAL(pos(1)),IMAG(pos(1))
change:
SPRITE "tree" AT RND(sw/2)+sw/4,RND(sh/2)+sh/4
DO UNTIL BUTTON_PRESSED("step")
IF NOT connect(1,size,sw) THEN change
DO UNTIL BUTTON_PRESSED("step")
UNTIL 0
END
' === subroutines and function
'r'
DEF connect(n,size,maxrange)
' find nearest point, by Dutchman
pos=.pos(n)
SPRITE "core" AT REAL(pos),IMAG(pos)
' --- search with "core"
SPRITE "core" SHOW
IF SPRITES_COLLIDE("core","tree") THEN
SPRITE "core" HIDE
RETURN 1
ENDIF
' --- move via Archimedean spiral
gain=1.5 '0.75 for full coverage
a=gain*size/2
b=gain*size/6.28319 'size/2π
sign=(-1)^(RND(2)+1) ' turn left or right
phi=0
sprite "core" alpha 0.5
DO
SPRITE "core" STAMP
phi+=dphi
r=a+b*phi
z=r*EXP(1i*phi*sign)
SPRITE "core" AT REAL(pos+z),IMAG(pos+z)
phi+=gain*size/r
pause .wait
UNTIL SPRITES_COLLIDE("core","tree") OR r>maxrange
SPRITE "core" STAMP
' --- finish
IF r>maxrange THEN
SPRITE "core" HIDE ! RETURN 0
ENDIF
' --- move to position
phi=ARG(z)'+sign*size/2/r
SPRITE "core" AT REAL(pos),IMAG(pos)
SPRITE "core" STAMP
DO
pause .wait
pos+=size/4*EXP(1i*phi)
SPRITE "core" AT REAL(pos),IMAG(pos)
SPRITE "core" STAMP
UNTIL SPRITES_COLLIDE("core","tree") OR ABS(pos-.mid)>maxrange
SPRITE "core" HIDE
IF ABS(pos-.mid)>maxrange THEN RETURN 0
SPRITE n AT REAL(pos),IMAG(pos)
.pos(n)=pos
RETURN 1
END DEF
''
Initialise:
GRAPHICS
GRAPHICS CLEAR 0.5,0.5,0.5
SPRITE 1 BEGIN halo,halo
FILL COLOR 1,0,0
FILL ALPHA 0.7
FILL CIRCLE halo/2,halo/2 SIZE halo/2
FILL ALPHA 1
FILL COLOR 1,1,0
FILL CIRCLE halo/2,halo/2 SIZE size/2
SPRITE END
SPRITE 1 AT REAL(pos(1)),IMAG(pos(1))
SPRITE 1 SHOW
SPRITE "core" BEGIN size,size
FILL COLOR .show,.show,0
FILL CIRCLE size/2,size/2 SIZE .size/2
SPRITE END
SPRITE "tree" BEGIN size,size
FILL COLOR 0,1,0
FILL CIRCLE size/2,size/2 SIZE size/2
SPRITE END
SPRITE "tree" AT sw/2,(sh-halo-size)/2
SPRITE "tree" SHOW
setstepbutton(30,sw/2-40,sh-40)
RETURN
'
DEF SetStepButton(fsize,x,y)
SET BUTTONS CUSTOM
SET BUTTONS FONT SIZE fsize
FILL COLOR 1,0,0
DRAW COLOR 1,1,0
BUTTON "step" TEXT "Step" AT x,y SIZE 2.5*fsize,fsize+8
END DEF