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; }