UNPKG

@anvaka/streamlines

Version:
2 lines (1 loc) 6.61 kB
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class A{constructor(e,t){this.x=e,this.y=t}equals(e){return this.x===e.x&&this.y===e.y}add(e){return new A(this.x+e.x,this.y+e.y)}mulScalar(e){return new A(this.x*e,this.y*e)}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}normalize(){const e=this.length();this.x/=e,this.y/=e}distanceTo(e){const t=e.x-this.x,u=e.y-this.y;return Math.sqrt(t*t+u*u)}}function W(r,e){if(!(r instanceof e))throw new TypeError("Cannot call a class as a function")}var K=(function(){function r(){W(this,r),this.children=null}return r.prototype.occupy=function(t){this.children||(this.children=[]),this.children.push(t)},r.prototype.isTaken=function(t,u,f){if(!this.children)return!1;for(var o=0;o<this.children.length;++o){var s=this.children[o],a=s.x-t,h=s.y-u,m=Math.sqrt(a*a+h*h);if(f(m,s))return!0}return!1},r.prototype.getMinDistance=function(t,u){let f=1/0;if(!this.children)return f;for(var o=0;o<this.children.length;++o){var s=this.children[o],a=s.x-t,h=s.y-u,m=Math.sqrt(a*a+h*h);m<f&&(f=m)}return f},r})();function U(r,e){var t=Math.max(r.width,r.height),u=Math.ceil(t/e),f=new Map,o={occupyCoordinates:h,isTaken:m,isOutside:a,findNearest:s};return o;function s(l,c){var T=P(l),y=x(c);let g=1/0;for(var v=-1;v<2;++v){var w=T+v;if(!(w<0||w>=u)){var n=f.get(w);if(n)for(var i=-1;i<2;++i){var d=y+i;if(d<0||d>=u)continue;var S=n.get(d);if(!S)continue;let E=S.getMinDistance(l,c);E<g&&(g=E)}}}return g}function a(l,c){return l<r.left||l>r.left+r.width||c<r.top||c>r.top+r.height}function h(l){var c=l.x,T=l.y;k(c,T).occupy(l)}function m(l,c,T){if(!f)return!1;for(var y=P(l),g=x(c),v=-1;v<2;++v){var w=y+v;if(!(w<0||w>=u)){var n=f.get(w);if(n)for(var i=-1;i<2;++i){var d=g+i;if(!(d<0||d>=u)){var S=n.get(d);if(S&&S.isTaken(l,c,T))return!0}}}}return!1}function k(l,c){M(l,c);var T=P(l),y=f.get(T);y||(y=new Map,f.set(T,y));var g=x(c),v=y.get(g);return v||(v=new K,y.set(g,v)),v}function P(l){return Math.floor(u*(l-r.left)/t)}function x(l){return Math.floor(u*(l-r.top)/t)}function M(l,c){if(r.left>l||r.left+t<l)throw new Error("x is out of bounds");if(r.top>c||r.top+t<c)throw new Error("y is out of bounds")}}function _(r,e,t){var u=t(r);if(u){var f=t(r.add(u.mulScalar(e*.5)));if(f){var o=t(r.add(f.mulScalar(e*.5)));if(o){var s=t(r.add(o.mulScalar(e)));if(s){var a=u.mulScalar(e/6).add(f.mulScalar(e/3)).add(o.mulScalar(e/3)).add(s.mulScalar(e/6));return a}}}}}var D=1,z=2,I=3;function L(r,e,t){var u=[r],f=r,o=D,s=null,a=-1,h=U(t.boundingBox,t.timeStep*.9);return{start:r,next:M,getStreamline:m,getNextValidSeed:k};function m(){return u}function k(){for(;a<u.length-1;){a+=1;var n=u[a],i=w(n);if(i){var d=n.x-i.y*t.dSep,S=n.y+i.x*t.dSep;if(Array.isArray(t.seedArray)&&t.seedArray.length>0){var E=t.seedArray.shift();d=E.x,S=E.y}if(!e.isOutside(d,S)&&!e.isTaken(d,S,x))return a-=1,new A(d,S);var B=n.x+i.y*t.dSep,p=n.y-i.x*t.dSep;if(!e.isOutside(B,p)&&!e.isTaken(B,p,x))return new A(B,p)}}}function P(n){return F(n,t.dTest)?!1:n<t.dTest}function x(n){return F(n,t.dSep)?!1:n<t.dSep}function M(){for(;;){if(s=null,o===D){var n=c();if(n){u.push(n),h.occupyCoordinates(n),f=n;var i=v(n);if(i)return}else t.forwardOnly?o=I:(f=r,o=z)}if(o===z){var n=T();if(n){u.unshift(n),f=n,h.occupyCoordinates(n);var i=v(n);if(i)return}else o=I}if(o===I)return u.forEach(l),!0}}function l(n){e.occupyCoordinates(n)}function c(){var n=_(f,t.timeStep,w);if(n)return y(f,n)}function T(){var n=_(f,t.timeStep,w);if(n)return n=n.mulScalar(-1),y(f,n)}function y(n,i){if(s=n.add(i),!e.isOutside(s.x,s.y)&&!e.isTaken(s.x,s.y,P)&&!h.isTaken(s.x,s.y,g))return s}function g(n){return n<t.timeStep*.9}function v(n){var i=!1;return t.onPointAdded&&(i=t.onPointAdded(n,u[o===D?u.length-2:1],t,u)),i}function w(i){var i=t.vectorField(i,u,o===I);if(i&&!(Number.isNaN(i.x)||Number.isNaN(i.y))){var d=i.x*i.x+i.y*i.y;if(d!==0)return d=Math.sqrt(d),new A(i.x/d,i.y/d)}}}function F(r,e){return Math.abs(r-e)<1e-4}function V(r){if(!r)throw new Error("Canvas is required");var e=r.getContext("2d"),t=r.width,u=r.height;return f;function f(s,a,h){e.beginPath(),e.strokeStyle="rgba(0, 0, 0, 0.6)",s=o(s,h.boundingBox),a=o(a,h.boundingBox),e.moveTo(s.x,s.y),e.lineTo(a.x,a.y),e.stroke(),e.closePath()}function o(s,a){var h=(s.x-a.left)/a.width,m=(s.y-a.top)/a.height;return{x:h*t,y:(1-m)*u}}}var G=0,R=1,C=2,j=3,q=4;const Q=typeof globalThis<"u"&&globalThis.performance&&typeof globalThis.performance.now=="function"?globalThis.performance:{now:()=>Date.now()};function H(r){var e=Object.create(null);if(!r)throw new Error("Configuration is required to compute streamlines");r.boundingBox?(e.boundingBox={},Object.assign(e.boundingBox,r.boundingBox)):(console.warn("No bounding box passed to streamline. Creating default one"),e.boundingBox={left:-5,top:-5,width:10,height:10}),J(e.boundingBox);var t=e.boundingBox;if(e.vectorField=r.vectorField,e.onStreamlineAdded=r.onStreamlineAdded,e.onPointAdded=r.onPointAdded,e.forwardOnly=r.forwardOnly,!r.seed)e.seed=new A(Math.random()*t.width+t.left,Math.random()*t.height+t.top);else if(Array.isArray(r.seed)){var u=r.seed.shift();e.seed=new A(u.x,u.y),e.seedArray=r.seed}else e.seed=new A(r.seed.x,r.seed.y);e.dSep=r.dSep>0?r.dSep:1/Math.max(t.width,t.height),e.dTest=r.dTest>0?r.dTest:e.dSep*.5;var f=U(t,e.dSep);e.timeStep=r.timeStep>0?r.timeStep:.01,e.stepsPerIteration=r.stepsPerIteration>0?r.stepsPerIteration:10,e.maxTimePerIteration=r.maxTimePerIteration>0?r.maxTimePerIteration:1e3;var o=e.stepsPerIteration,s,a=G,h=[],m=L(e.seed,f,e),k=!1,P=!1,x;return{run:l,getGrid:M,dispose:T};function M(){return f}function l(){if(!P)return P=!0,x=setTimeout(y,0),new Promise(c)}function c(d){s=d}function T(){k=!0,clearTimeout(x)}function y(){if(!k){for(var d=e.maxTimePerIteration,S=Q.now(),E=0;E<o&&(a===G&&g(),a===R&&n(),a===C&&w(),a===q&&v(),!(Q.now()-S>d));++E)if(a===j){s(e);return}x=setTimeout(y,0)}}function g(){var d=m.next();d&&(i(),a=C)}function v(){var d=h[0],S=d.getNextValidSeed();S?(m=L(S,f,e),a=R):(h.shift(),a=C)}function w(){h.length===0?a=j:a=q}function n(){var d=m.next();d&&(i(),a=q)}function i(){var d=m.getStreamline();d.length>1&&(h.push(m),e.onStreamlineAdded&&e.onStreamlineAdded(d,e))}}function J(r){var e="Bounding box {left, top, width, height} is required";if(!r)throw new Error(e);if(N(r.left,e),N(r.top,e),typeof r.size=="number"&&(r.width=r.size,r.height=r.size),N(r.width,e),N(r.height,e),r.width<=0||r.height<=0)throw new Error("Bounding box cannot be empty")}function N(r,e){if(typeof r!="number"||Number.isNaN(r))throw new Error(e)}exports.default=H;exports.renderTo=V;