Some experimenting with Yield, NearestNeighbors while maintaining walk(i);
Nearest Yield ⚠️ (variation)
Visual idea from a plotterfile by @msurguy at plotterfiles.com/@ms…2f-b64c-c0f665a70cff
(the plotterfiles.com link does not work as TurtleToy replaces the @ with @ which breaks the site)
Log in to post a comment.
// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);
// Global code will be evaluated once.
const turtle = new Turtle();
const randomSeed = 0; // min=0 max=1000 step=1
const radius = 50; // min=10 max=90 step=1
const tooFarThresholdRt = 50; //min=10 max=1000 step=1
const continuousDraw = 0; // min=0 max=1 step=1 (No,Yes)
const rings = 3; //min=0 max=10 step=1
// Seedable random number generator by David Bau: http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html
!function(a,b,c,d,e,f,g,h,i){function j(a){var b,c=a.length,e=this,f=0,g=e.i=e.j=0,h=e.S=[];for(c||(a=[c++]);d>f;)h[f]=f++;for(f=0;d>f;f++)h[f]=h[g=s&g+a[f%c]+(b=h[f])],h[g]=b;(e.g=function(a){for(var b,c=0,f=e.i,g=e.j,h=e.S;a--;)b=h[f=s&f+1],c=c*d+h[s&(h[f]=h[g=s&g+b])+(h[g]=b)];return e.i=f,e.j=g,c})(d)}function k(a,b){var c,d=[],e=typeof a;if(b&&"object"==e)for(c in a)try{d.push(k(a[c],b-1))}catch(f){}return d.length?d:"string"==e?a:a+"\0"}function l(a,b){for(var c,d=a+"",e=0;e<d.length;)b[s&e]=s&(c^=19*b[s&e])+d.charCodeAt(e++);return n(b)}function m(c){try{return o?n(o.randomBytes(d)):(a.crypto.getRandomValues(c=new Uint8Array(d)),n(c))}catch(e){return[+new Date,a,(c=a.navigator)&&c.plugins,a.screen,n(b)]}}function n(a){return String.fromCharCode.apply(0,a)}var o,p=c.pow(d,e),q=c.pow(2,f),r=2*q,s=d-1,t=c["seed"+i]=function(a,f,g){var h=[];f=1==f?{entropy:!0}:f||{};var o=l(k(f.entropy?[a,n(b)]:null==a?m():a,3),h),s=new j(h);return l(n(s.S),b),(f.pass||g||function(a,b,d){return d?(c[i]=a,b):a})(function(){for(var a=s.g(e),b=p,c=0;q>a;)a=(a+c)*d,b*=d,c=s.g(1);for(;a>=r;)a/=2,b/=2,c>>>=1;return(a+c)/b},o,"global"in f?f.global:this==c)};if(l(c[i](),b),g&&g.exports){g.exports=t;try{o=require("crypto")}catch(u){}}else h&&h.amd&&h(function(){return t})}(this,[],Math,256,6,52,"object"==typeof module&&module,"function"==typeof define&&define,"random");
Math.seedrandom('' + randomSeed);
function distanceSquared(p1, p2) {
return Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2);
}
class NearestNeighbor {
points = [];
pointCount = 0;
constructor(pointCount) {
this.pointCount = pointCount;
}
init() {
for(let pt of this.generatePoint()) {
this.points.push(pt);
}
let index = this.nearestUnvisited([0, 0]);
while(index !== null) {
let found = this.nearestUnvisited(this.points[index]);
this.points[index][2] = found;
index = found;
}
return this;
}
nearestUnvisited(coord) {
let nearest = [null, 10000];
for(let i = 0; i < this.points.length; i++) {
if(this.points[i][2] !== false) {
continue;
}
let d = distanceSquared(this.points[i], coord);
if(d < nearest[1]) {
nearest = [i, d];
}
}
return nearest[0];
}
*iteratePoints() {
for(let i = 0; i < this.points.length; i++) {
yield this.points[i];
}
}
getPoint(index) {
return this.points[index];
}
}
class NearestNeighborSphere extends NearestNeighbor {
constructor(pointCount, radius) {
super(pointCount);
this.R = radius;
}
*generatePoint () {
for(let i = 0; i < this.pointCount; i++) {
let r = this.R * Math.sin(Math.sqrt(Math.random()) * Math.PI / 2);
let theta = Math.random() * 2 * Math.PI;
yield [r * Math.cos(theta), r * Math.sin(theta), false];
}
}
}
class NearestNeighborRing extends NearestNeighborSphere {
*generatePoint () {
for(let i = 0; i < this.pointCount; i++) {
let theta = Math.random() * 2 * Math.PI;
yield [this.R * Math.cos(theta), this.R * Math.sin(theta), false];
}
}
}
class NearestNeighborIterator {
nns = [];
currentNN = null;
add(nn) {
this.nns.push(nn);
}
getNN() {
return this.currentNN;
}
*points() {
for(let nn of this.nns) {
this.currentNN = nn;
for(let pt of nn.iteratePoints()) {
yield pt;
}
}
this.currentNN = null;
}
}
let nni = new NearestNeighborIterator();
nni.add(new NearestNeighborSphere(Math.pow(radius, 2.1), radius).init());
for(let i = 0; i < rings; i++) {
nni.add(new NearestNeighborRing(Math.pow(radius + (radius * ((i + 1)/(rings + 2))), 2) / 16, radius + (radius * ((i + 1)/(rings + 2)))).init());
}
let drawToggler = false;
let iterator = nni.points();
// The walk function will be called until it returns false.
function walk(i) {
let pt = iterator.next().value;
if(pt !== undefined) {
if(nni.getNN().points[pt[2]] !== undefined) {
turtle.jump(pt);
if((continuousDraw === 1 || !drawToggler) && distanceSquared(pt, nni.getNN().points[pt[2]]) < tooFarThresholdRt) {
turtle.goto(nni.getNN().points[pt[2]])
drawToggler = true;
} else {
turtle.jump(nni.getNN().points[pt[2]])
drawToggler = false;
}
}
return true;
}
return false;
}