memoscan
← all memos

Memo 0x6d37d44f…837c57 on Ethereum

class StreamlineGenerator{majorGrid;minorGrid;paramsSq;candidateSeedsMajor=[];candidateSeedsMinor=[];resolve;allStreamlines=[];streamlinesMajor=[];streamlinesMinor=[];allStreamlinesSimple=[];worldDimensions;origin;constructor(t,e,i){this.worldDimensions=e,this.origin=t,(this.params=i).dtest=Math.min(i.dtest,i.dsep),this.majorGrid=new GridStorage(this.worldDimensions,this.origin,this.params.dsep),this.minorGrid=new GridStorage(this.worldDimensions,this.origin,this.params.dsep),this.setParamsSq()}joinDanglingStreamlines(){for(const e of[!0,!1])for(const i of this.streamlines(e))if(!i[0].equals(i[i.length-1])){var t=this.getBestNextPoint(i[0],i[4]);if(null!==t)for(const s of this.pointsBetween(i[0],t,this.params.dstep))i.unshift(s),this.grid(e).addSample(s);t=this.getBestNextPoint(i[i.length-1],i[i.length-4]);if(null!==t)for(const r of this.pointsBetween(i[i.length-1],t,this.params.dstep))i.push(r),this.grid(e).addSample(r)}this.allStreamlinesSimple=[];for(const a of this.allStreamlines)this.allStreamlinesSimple.push(this.simplifyStreamline(a))}pointsBetween(t,e,i){var s=t.dist(e),r=Math.floor(s/i);if(0===r)return[];var a=e.copy().sub(t),n=[];let o=1,h=t.copy().add(a.copy().mult(o/r));for(o=1;o<=r;o++){if(!(.001<integrate(h,!0).magSq()))return n;n.push(h),h=t.copy().add(a.copy().mult(o/r))}return n}getBestNextPoint(t,e){var i=this.majorGrid.getNearbyPoints(t,this.params.dlookahead),s=(i.push(...this.minorGrid.getNearbyPoints(t,this.params.dlookahead)),t.copy().sub(e));let r=null,a=1/0;for(const h of i)if(!h.equals(t)&&!h.equals(e)){var n=h.copy().sub(t);if(!(n.dot(s)<0)){var o=distanceToSquared(t,h);if(o<2*this.paramsSq.dstep){r=h;break}Math.abs(s.angleBetween(n))<this.params.joinangle&&o<a&&(a=o,r=h)}}return r=null!==r?r.copy().add(s.div(s.mag()).mult(4*this.params.simplifyTolerance)):r}async createAllStreamlines(){return new Promise(t=>{this.resolve=t;let e=!0;for(;this.createStreamline(e);)e=!e;t()}).then(()=>this.joinDanglingStreamlines())}simplifyStreamline(t){var e=[];for(const i of t)e.push(createVector(i.x,i.y));return e}createStreamline(t){var e=this.getSeed(t);return null!==e&&(5<(e=this.integrateStreamline(e,t)).length&&(this.grid(t).addPolyline(e),this.streamlines(t).push(e),this.allStreamlines.push(e),this.allStreamlinesSimple.push(this.simplifyStreamline(e)),e[0].equals(e[e.length-1])||(this.candidateSeeds(!t).push(e[0]),this.candidateSeeds(!t).push(e[e.length-1]))),!0)}setParamsSq(){this.paramsSq=Object.assign({},this.params);for(const t in this.paramsSq)"number"==typeof this.paramsSq[t]&&(this.paramsSq[t]*=this.paramsSq[t])}samplePoint(){return createVector(R.random_dec()*WIDTH,R.random_dec()*HEIGHT).add(this.origin)}getSeed(t){let e=this.samplePoint(),i=0;for(;!this.isValidSample(t,e,this.paramsSq.dsep);){if(i>=this.params.seedTries)return null;e=this.samplePoint(),i++}return e}isValidSample(t,e,i,s=!1){let r=this.grid(t).isValidSample(e,i);return r=s?r&&this.grid(!t).isValidSample(e,i):r}candidateSeeds(t){return t?this.candidateSeedsMajor:this.candidateSeedsMinor}streamlines(t){return t?this.streamlinesMajor:this.streamlinesMinor}grid(t){return t?this.majorGrid:this.minorGrid}pointInBounds(t){return t.x>=this.origin.x&&t.y>=this.origin.y&&t.x<this.worldDimensions.x+this.origin.x&&t.y<this.worldDimensions.y+this.origin.y}streamlineTurned(t,e,i,s){return e.dot(s)<0&&(e=createVector(e.y,-e.x),i.copy().sub(t).dot(e)<0==0<s.dot(e))}streamlineIntegrationStep(t,e,i){var s,r;t.valid&&(t.streamline.push(t.previousPoint),(s=integrate(t.previousPoint,e)).magSq()<.01?t.valid=!1:(s.dot(t.previousDirection)<0&&s.mult(-1),r=t.previousPoint.copy().add(s),this.pointInBounds(r)&&this.isValidSample(e,r,this.paramsSq.dtest,i)&&!this.streamlineTurned(t.seed,t.originalDir,r,s)?(t.previousPoint=r,t.previousDirection=s):(t.streamline.push(r),t.valid=!1)))}integrateStreamline(t,e){let i=0,s=!1;var r=R.random_dec()<this.params.collideEarly,a=integrate(t,e),n={seed:t,originalDir:a,streamline:[t],previousDirection:a,previousPoint:t.copy().add(a),valid:!0},a=(n.valid=this.pointInBounds(n.previousPoint),a.copy().mult(-1)),o={seed:t,originalDir:a,streamline:[],previousDirection:a,previousPoint:t.copy().add(a),valid:!0};for(o.valid=this.pointInBounds(o.previousPoint);i<this.params.pathIterations&&(n.valid||o.valid);){this.streamlineIntegrationStep(n,e,r),this.streamlineIntegrationStep(o,e,r);var h=distanceToSquared(n.previousPoint,o.previousPoint);if((s=!s&&h>this.paramsSq.dcirclejoin?!0:s)&&h<=this.paramsSq.dcirclejoin){n.streamline.push(n.previousPoint),n.streamline.push(o.previousPoint),o.streamline.push(o.previousPoint);break}i++}return o.streamline.reverse().push(...n.streamline),o.streamline}}class RoadGenerator{streamlines;params;constructor(t){this.params=t}get roads(){return this.streamlines.allStreamlinesSimple}async generateRoads(){return this.streamlines=new StreamlineGenerator(createVector(0,0),createVector(WIDTH,HEIGHT),Object.assign({},this.params)),this.streamlines.createAllStreamlines()}}class Tensor{oldTheta;_theta;matrix;r;constructor(t,e){this.r=t,this.matrix=e,this.oldTheta=!1,this._theta=this.calculateTheta()}static get zero(){return new Tensor(0,[0,0])}get theta(){return this.oldTheta&&(this._theta=this.calculateTheta(),this.oldTheta=!1),this._theta}add(i){return this.matrix=this.matrix.map((t,e)=>t*this.r+i.matrix[e]*i.r),this.r=2,this.oldTheta=!0,this}scale(t){return this.r*=t,this.oldTheta=!0,this}getMajor(){return 0===this.r?Vector.zeroVector():createVector(Math.cos(this.theta),Math.sin(this.theta))}getMinor(){var t;return 0===this.r?Vector.zeroVector():(t=this.theta+Math.PI/2,createVector(Math.cos(t),Math.sin(t)))}calculateTheta(){return 0===this.r?0:Math.atan2(this.matrix[1]/this.r,this.matrix[0]/this.r)/2}}class GridStorage{gridDimensions;grid;dsepSq;origin;dsep;worldDimensions;constructor(t,e,i){this.dsep=i,this.origin=e,this.worldDimensions=t,this.dsepSq=i*i,this.gridDimensions=this.worldDimensions.copy().div(this.dsep),this.grid=[];for(let e=0;e<this.gridDimensions.x;e++){this.grid.push([]);for(let t=0;t<this.gridDimensions.y;t++)this.grid[e].push([])}}addPolyline(t){for(const e of t)this.addSample(e)}addSample(t,e){e=e||this.getSampleCoords(t),this.grid[e.x][e.y].push(t)}isValidSample(i,s=this.dsepSq){var r=this.getSampleCoords(i);for(let e=-1;e<=1;e++)for(let t=-1;t<=1;t++){var a=r.copy().add(createVector(e,t));if(!this.vectorOutOfBounds(a,this.gridDimensions)&&!this.vectorFarFromVectors(i,this.grid[a.x][a.y],s))return!1}return!0}vectorFarFromVectors(t,e,i){for(const s of e)if(s!==t)if(distanceToSquared(s,t)<i)return!1;return!0}getNearbyPoints(t,e){var i=Math.ceil(e/this.dsep-.5),s=this.getSampleCoords(t),r=[];for(let e=-1*i;e<=+i;e++)for(let t=-1*i;t<=+i;t++){var a=s.copy().add(createVector(e,t));if(!this.vectorOutOfBounds(a,this.gridDimensions))for(const n of this.grid[a.x][a.y])r.push(n)}return r}worldToGrid(t){return t.copy().sub(this.origin)}vectorOutOfBounds(t,e){return t.x<0||t.y<0||t.x>=e.x||t.y>=e.y}getSampleCoords(t){t=this.worldToGrid(t);return this.vectorOutOfBounds(t,this.worldDimensions)?createVector(0,0):createVector(Math.floor(t.x/this.dsep),Math.floor(t.y/this.dsep))}}class BasisField{_centre;_decay;_type;constructor(t,e,i,s,r){this._centre=t.copy(),this._size=e,this._decay=i,this._theta=s,this._type=r}getWeightedTensor(t){return this.getTensor(t).scale(this.getTensorWeight(t))}getTensorWeight(t){t=t.copy().sub(this._centre).mag()/this._size;return 0===this._decay&&1<=t?0:Math.max(0,1-t)**this._decay}getTensor(t){return 0===this._type?this.getGridTensor():this.getRadialTensor(t)}getGridTensor(){var t=Math.cos(2*this._theta),e=Math.sin(2*this._theta);return new Tensor(1,[t,e])}getRadialTensor(t){var t=t.copy().sub(this._centre),e=t.y**2-t.x**2,t=-2*t.x*t.y;return new Tensor(1,[e,t])}}