The red ball is pushed away from black nodes, add new nodes by dragging from an existent node, to delete a node shift-click it and add a fixed node with ctrl-click.
_="B=F=5 S= N=[Q={f:$],A=[]G={x:30 yHXHY:J,TOxx-f.x;yy-f.y;M>.sqrt(x*x+y*y;i<60RiFVL=i,y:40 X:i,Y:40JAa:LG:L-$_C_L-CsetInterval(VU=u=Rc.width=c.height=60RB in aVAd=(F/T(a],b]`1d*b?.3:d<0?.1:Rx%d;y%d;WZyWjZjyNzW%.7@Z%.7fT(e,Q)<8(u=f)S^f(U=fAmoveTo(ylineTo( ystroke(red';Dy,4 7(Nfy(2Dy,f^(S?U:u)?8:1 72#000',(2d=M>.pow(T(eG)*.03,52W=x/d,Z=y/d,XjW,YjZzW*F@Z*Fz((tx`X)*X=t@((ty`Y)*+1Y=t)zX%;yY=Y*+$,30downOctrlKey?,f:$):shiftKey?u(_g=u]={f:A=Ag^ag^b}):(S=u)=J;upOSS||}`$2S=J;moveO!xEX,!yEY}e,fVe.!y:!y,X:!Y:!y.filter(.push({_fill); 0,a].b].onmousebeginP>(+=&&f||(NWHZHx:Aa:SG:U)}b.function(x,Style='=,a..98return A.pop(!Q.$1}%*=2),>ath@yBfor(iC1].f=Darc(EpageG,bH: J0}O=R0;V){_N[`)-j-=zx";for(Y=0;$="zj`_VROJHGEDCB@>2%$! "[Y++];)Z=_.split($),_=Z.join(Z.pop());eval(_)
Xz0iQj1GPTUJUz0JTj1bUT17ZjokXSxBPVtdRz17eDozMAl5SFhIWTpKLFRPeBp4LWYueDt5GnktZi55Ox5NPi5zcXJ0KHgqeCt5KnkVO2k8NjBSaRBGVkw9E2kseTo0MAlYOmksWTo0MEoIQQVhOkxHOkwtJBUfX0NfTC1Dc2V0SW50ZXJ2YWwoF1ZVPXU9UmMud2lkdGg9Yy5oZWlnaHQ9NjBSQiBpbiBhVkEEZD0oRi9UKAZhXSwGYl1gMQhkKhpiPy4zOmQ8MD8uMTpSeCVkO3klZDsLEgtXEBgLWhB5CAwSDFdqGAxaankVCE4EAhICegJXJS43QAJaJS43CGYRVChlLFEpPDgRKHU9ZikRU15mEShVPWYVFUEEHG1vdmVUbygLGAt5CBxsaW5lVG8oDBggDHkVCBxzdHJva2UoCA8IGXJlZCc7RBYYFnksNAkJNwgHKAhOBGYRAnkRKA8yRAIYAnksZl4oUz9VOnUpPzg6MQkJNzIZIzAwMCcsBygyZD1NPi5wb3coVChlRykqLjAzLDUyVz14L2QsWj15L2QsFlhqVywWWWpaGxICelcqRkBaKkYbeigodBp4YAJYKSodG1g9dEAoKHQaeWACWSkqHSsxG1k9dCkVCBZ6FlglHTsWeRAWWT0WWSodKyQsMzAIDmRvd25PAmN0cmxLZXk/AyxmOiQpOgJzaGlmdEtleT91EShfZz11XT17ZjpBPUEEHmdeAmERZ14CYn0VKTooUz11KRQ9ShU7DnVwT1MRH1MUfHwDfWAkMlM9SjsObW92ZU8heEVYLCF5RVl9ARdlLGZWAmUuAxMhGHk6IXksWDohGFk6IXkELmZpbHRlcigBBS5wdXNoKHsGXwIHHGZpbGwIKTsJMCwLBmFdLgwGYl0uDm9ubW91c2UPHGJlZ2luUD4oECs9ESYmEmZ8fCgTTgVXSFpIeDoUEUEFYTpTRzpVFSl9FmIuF2Z1bmN0aW9uKBh4LBkHU3R5bGU9Jxo9AhssAhxhLh0uOTgecmV0dXJuIB9BLnBvcCgIIVEuJDF9JSo9MiksPmF0aEAbeRBCZm9yKGlDMV0uZj1EHGFyYyhFGnBhZ2VHLGJIOglKMH1PPQFSMDtWKXtfTltgKS1qLT16eBAiO2ZvcihZPTA7JD0iempgX1ZST0pIR0VEQ0JAPjIlJCEfHh0cGxoZGBcWFRQTEhEQDw4MCwkIBwYFBAMCASJbWSsrXTspWj1fLnNwbGl0KCQpLF89Wi5qb2luKFoucG9wKCkpO2V2YWwoXyk=
Original source not submitted