UNPKG

venn-helper

Version:

Area Proportional Venn and Euler Diagrams

8 lines (7 loc) 14.9 kB
"use strict";var G=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var fe=Object.prototype.hasOwnProperty;var le=(e,n)=>{for(var r in n)G(e,r,{get:n[r],enumerable:!0})},ce=(e,n,r,t)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of ue(n))!fe.call(e,a)&&a!==r&&G(e,a,{get:()=>n[a],enumerable:!(t=oe(n,a))||t.enumerable});return e};var de=e=>ce(G({},"__esModule",{value:!0}),e);var Ce={};le(Ce,{bestInitialLayout:()=>j,chartVega:()=>be,circleArea:()=>w,circleCircleIntersection:()=>q,circleOverlap:()=>L,circlePath:()=>ie,computeTextCentre:()=>Y,computeTextCentres:()=>ae,constrainedMDSLayout:()=>E,containedInCircles:()=>Q,disjointCluster:()=>ee,distance:()=>z,distanceFromIntersectArea:()=>B,getCenter:()=>_,getDistanceMatrices:()=>Z,greedyLayout:()=>N,intersectionArea:()=>S,intersectionAreaPath:()=>re,lossFunction:()=>D,normalizeSolution:()=>V,scaleSolution:()=>W,venn:()=>T,vennSolution:()=>te});module.exports=de(Ce);var P=require("fmin");function S(e){var n=he(e),r=n.filter(function(b){return Q(b,e)}),t=0,a=0,i=[],s;if(r.length>1){var f=_(r);r=r.map(b=>({...b,angle:Math.atan2(b.x-f.x,b.y-f.y)})).sort((b,I)=>I.angle-b.angle);var u=r[r.length-1];for(s=0;s<r.length;++s){var o=r[s];a+=(u.x+o.x)*(o.y-u.y);for(var l={x:(o.x+u.x)/2,y:(o.y+u.y)/2},c=null,h=0;h<o.parentIndex.length;++h)if(u.parentIndex.indexOf(o.parentIndex[h])>-1){var g=e[o.parentIndex[h]],x=Math.atan2(o.x-g.x,o.y-g.y),d=Math.atan2(u.x-g.x,u.y-g.y),v=d-x;v<0&&(v+=2*Math.PI);var p=d-v/2,y=z(l,{x:g.x+g.radius*Math.sin(p),y:g.y+g.radius*Math.cos(p)});y>g.radius*2&&(y=g.radius*2),(c===null||c.width>y)&&(c={circle:g,width:y,p1:o,p2:u})}c!==null&&(i.push(c),t+=w(c.circle.radius,c.width),u=o)}}else{var m=e[0];for(s=1;s<e.length;++s){let b=e[s];(m==null||b.radius<m.radius)&&(m=b)}var C=!1;for(s=0;s<e.length;++s){let b=e[s];if(b!==void 0&&z(b,m)>Math.abs(m.radius-b.radius)){C=!0;break}}C?t=a=0:(t=m.radius*m.radius*Math.PI,i.push({circle:m,p1:{x:m.x,y:m.y+m.radius},p2:{x:m.x-1e-10,y:m.y+m.radius},width:m.radius*2}))}return a/=2,{overlap:t+a,stats:{area:t+a,arcArea:t,polygonArea:a,arcs:i,innerPoints:r,intersectionPoints:n}}}function Q(e,n){for(var r=0;r<n.length;++r){let t=n[r];if(t!==void 0&&z(e,t)>t.radius+1e-10)return!1}return!0}function he(e){for(var n=[],r=0;r<e.length;++r)for(var t=r+1;t<e.length;++t){let s=e[r],f=e[t];if(!(!s||!f))for(var a=q(s,f),i=0;i<a.length;++i){let u=a[i];u&&n.push({...u,parentIndex:[r,t]})}}return n}function w(e,n){return e*e*Math.acos(1-n/e)-(e-n)*Math.sqrt(n*(2*e-n))}function z(e,n){return Math.sqrt((e.x-n.x)*(e.x-n.x)+(e.y-n.y)*(e.y-n.y))}function L(e,n,r){if(r>=e+n)return 0;if(r<=Math.abs(e-n))return Math.PI*Math.min(e,n)*Math.min(e,n);var t=e-(r*r-n*n+e*e)/(2*r),a=n-(r*r-e*e+n*n)/(2*r);return w(e,t)+w(n,a)}function q(e,n){var r=z(e,n),t=e.radius,a=n.radius;if(r>=t+a||r<=Math.abs(t-a))return[];var i=(t*t-a*a+r*r)/(2*r),s=Math.sqrt(t*t-i*i),f=e.x+i*(n.x-e.x)/r,u=e.y+i*(n.y-e.y)/r,o=-(n.y-e.y)*(s/r),l=-(n.x-e.x)*(s/r);return[{x:f+o,y:u-l},{x:f-o,y:u+l}]}function _(e){let n=e.reduce((r,t)=>({x:r.x+t.x,y:r.y+t.y}),{x:0,y:0});return n.x/=e.length,n.y/=e.length,n}var ge=new Map([["greedy",N],["MDS",E],["best",j]]);function T(e,n){n=n??{},n.maxIterations=n.maxIterations||500,n.seed=n.seed??Math.random();let r=ge.get(n.layout??"best");var t=D;e=me(e);var a=r(e,n),i=[],s=[];for(let c of Object.keys(a)){let h=a[c];h&&(i.push(h.x),i.push(h.y),s.push(c))}for(var f=0,u=(0,P.nelderMead)(function(c){f+=1;for(var h={},g=0;g<s.length;++g){var x=s[g];let v=a[x];h[x]={x:c[2*g],y:c[2*g+1],radius:v.radius,setid:x,size:v.size,rowid:v.rowid}}return t(h,e)},i,n),o=u.x,l=0;l<s.length;++l){let c=s[l],h=a[c];h.x=o[2*l],h.y=o[2*l+1]}return a}var U=1e-10;function B(e,n,r){return Math.min(e,n)*Math.min(e,n)*Math.PI<=r+U?Math.abs(e-n):(0,P.bisect)(function(t){return L(e,n,t)-r},0,e+n)}function me(e){e=e.slice();var n=[],r={},t,a,i,s;for(let f of e)f.sets.length==1?n.push(f.sets[0]):f.sets.length==2&&(i=f.sets[0],s=f.sets[1],r[`${i},${s}`]=!0,r[`${s},${i}`]=!0);for(n.sort((f,u)=>f.toString().localeCompare(u.toString())),t=0;t<n.length;++t)for(i=n[t],a=t+1;a<n.length;++a)s=n[a],`${i},${s}`in r||e.push({sets:[i,s],size:0});return e}function Z(e,n,r){var t=(0,P.zerosM)(n.length,n.length),a=(0,P.zerosM)(n.length,n.length);return e.filter(function(i){return i.sets.length===2}).map(function(i){var s=r[i.sets[0]],f=r[i.sets[1]];if(s===void 0||f===void 0)return i;var u=Math.sqrt(n[s].size/Math.PI),o=Math.sqrt(n[f].size/Math.PI),l=B(u,o,i.size);t[s][f]=t[f][s]=l;var c=0;i.size+1e-10>=Math.min(n[s].size,n[f].size)?c=1:i.size<=1e-10&&(c=-1),a[s][f]=a[f][s]=c}),{distances:t,constraints:a}}function xe(e,n,r,t){var a=0,i;for(i=0;i<n.length;++i)n[i]=0;for(i=0;i<r.length;++i)for(var s=e[2*i],f=e[2*i+1],u=i+1;u<r.length;++u){var o=e[2*u],l=e[2*u+1],c=r[i][u],h=t[i][u],g=(o-s)*(o-s)+(l-f)*(l-f),x=Math.sqrt(g),d=g-c*c;h>0&&x<=c||h<0&&x>=c||(a+=2*d*d,n[2*i]+=4*d*(s-o),n[2*i+1]+=4*d*(f-l),n[2*u]+=4*d*(o-s),n[2*u+1]+=4*d*(l-f))}return a}function j(e,n){var r=N(e,n),t=D;if(e.length>=8){var a=E(e,n),i=t(a,e),s=t(r,e);i+1e-8<s&&(r=a)}return r}function ye(e=1){return()=>{e=e+1831565813|0;let n=Math.imul(e^e>>>15,1|e);return n=Math.imul(n^n>>>7,61|n)^n,((n^n>>>14)>>>0)/4294967296}}function E(e,n){var r=n.restarts||10,t=[],a={},i;for(i=0;i<e.length;++i){var s=e[i];s?.sets.length===1&&(s.sets[0]&&(a[s.sets[0]]=t.length),t.push(s))}var f=Z(e,t,a),u=f.distances,o=f.constraints,l=(0,P.norm2)(u.map(P.norm2))/u.length;u=u.map(function(m){return m.map(function(C){return C/l})});let c=(n.seed??Math.random())*2**32>>>0,h=ye(c);var g,x;for(i=0;i<r;++i){var d=(0,P.zeros)(u.length*2).map(()=>h());x=(0,P.conjugateGradient)((m,C)=>xe(m,C,u,o),d,n),(!g||x.fx<g.fx)&&(g=x)}var v=g?.x,p={};for(i=0;i<t.length;++i){var y=t[i];let m=y?.sets[0];y===void 0||m===void 0||(p[m]={x:v[2*i]*l,y:v[2*i+1]*l,radius:Math.sqrt(y.size/Math.PI),setid:m,size:y.size,rowid:Object.keys(p).length})}if(n.history)for(let m of n.history)(0,P.scale)(m.x,l);return p}function N(e,n){for(var r=D,t={},a={},i,s=0;s<e.length;++s){var f=e[s];f.sets.length==1&&(i=f.sets[0],t[i]={x:1e10,y:1e10,rowid:Object.keys(t).length,size:f.size,setid:i,radius:Math.sqrt(f.size/Math.PI)},a[i]=[])}for(e=e.filter(function(M){return M.sets.length==2}),s=0;s<e.length;++s){var u=e[s],o=u.weight?u.weight:1,l=u.sets[0],c=u.sets[1];if(l===void 0||c===void 0)continue;let M=t[l],R=t[c];!M.size||!R.size||(u.size+U>=Math.min(M.size,R.size)&&(o=0),a[l]?.push({set:c,size:u.size,weight:o}),a[c]?.push({set:l,size:u.size,weight:o}))}var h=[];for(i in a){let M=a[i];if(M){var g=0;for(s=0;s<M.length;++s){let R=M[s];R&&(g+=R.size*R.weight)}h.push({set:i,size:g})}}h.sort((M,R)=>R.size-M.size);var x={};function d(M){return M.set in x}function v(M,R){let A=t[R];A&&(A.x=M.x,A.y=M.y),x[R]=!0}for(v({x:0,y:0},h[0]?.set??""),s=1;s<h.length;++s){var p=h[s]?.set,y=p?a[p]?.filter(d):null;let M=p?t[p]:null;if(y?.sort((R,A)=>A.size-R.size),y?.length===0||!y)throw"ERROR: missing pairwise overlap information";for(var m=[],C=0;C<y.length;++C){let R=y[C];if(!R)continue;var b=t[y[C].set];if(!b)continue;let A=B(M.radius,b.radius,R.size);m.push({x:b.x+A,y:b.y}),m.push({x:b.x-A,y:b.y}),m.push({y:b.y+A,x:b.x}),m.push({y:b.y-A,x:b.x});for(var I=C+1;I<y.length;++I)for(var O=t[y[I].set],se=B(M.radius,O.radius,y[I].size),k=q({x:b.x,y:b.y,radius:A},{x:O.x,y:O.y,radius:se}),F=0;F<k.length;++F)m.push(k[F])}var H=1e50,J=m[0];for(C=0;C<m.length;++C){t[p].x=m[C].x,t[p].y=m[C].y;var K=r(t,e);K<H&&(H=K,J=m[C])}v(J,p)}return t}function D(e,n){var r=0;function t(l){return l.map(function(c){return e[c]})}for(var a=0;a<n.length;++a){var i=n[a],s;if(!(!i||i.sets.length===1)){if(i.sets.length===2){var f=e[i.sets[0]],u=e[i.sets[1]];if(f===void 0||u===void 0)continue;s=L(f.radius,u.radius,z(f,u))}else s=S(t(i.sets)).overlap;var o=i.weight?i.weight:1;r+=o*(s-i.size)*(s-i.size)}}return r}function ve(e,n,r){r===null?e.sort(function(d,v){return v.radius-d.radius}):e.sort(r);var t;if(e.length>0){var a=e[0].x,i=e[0].y;for(t=0;t<e.length;++t)e[t].x-=a,e[t].y-=i}if(e.length==2){let d=e[0],v=e[1];if(d&&v){var s=z(d,v);s<Math.abs(v.radius-d.radius)&&(v.x=d.x+d.radius-v.radius-1e-10,v.y=v.y)}}if(e.length>1){var f=Math.atan2(e[1].x,e[1].y)-(n??0),u=Math.cos(f),o=Math.sin(f),l,c;for(t=0;t<e.length;++t){let d=e[t];d&&(l=d.x,c=d.y,d.x=u*l-o*c,d.y=o*l+u*c)}}if(e.length>2){for(var h=Math.atan2(e[2].x,e[2].y)-(n??0);h<0;)h+=2*Math.PI;for(;h>2*Math.PI;)h-=2*Math.PI;if(h>Math.PI){var g=e[1].y/(1e-10+e[1].x);for(t=0;t<e.length;++t){let d=e[t];if(d){var x=(d.x+g*d.y)/(1+g*g);d.x=2*x-d.x,d.y=2*x*g-d.y}}}}}function ee(e){e.map(function(o){o.parent=o});function n(o){if(o)return o.parent!==o&&(o.parent=n(o.parent)),o.parent}function r(o,l){var c=n(o),h=n(l);c&&(c.parent=h)}for(var t=0;t<e.length;++t)for(var a=t+1;a<e.length;++a){let o=e[t],l=e[a];if(!(!o||!l)){var i=o.radius+l.radius;z(o,l)+1e-10<i&&r(l,o)}}var s={},f;for(t=0;t<e.length;++t){let o=e[t];if(!o)continue;let c=n(e[t])?.parent?.setid;c&&(c in s||(s[c]=[]),s[c]&&s[c].push(o))}e.map(function(o){delete o.parent});var u=[];for(f in s){let o=s[f];o&&u.push(o)}return u}function $(e){var n=function(r){var t=Math.max.apply(null,e.map(function(i){return i[r]+i.radius})),a=Math.min.apply(null,e.map(function(i){return i[r]-i.radius}));return{max:t,min:a}};return{xRange:n("x"),yRange:n("y")}}function V(e,n,r){n===null&&(n=Math.PI/2);var t=[],a,i;for(i in e){var s=e[i];s&&t.push({...s,setid:i})}var f=ee(t);for(a=0;a<f.length;++a){let d=f[a];if(d){ve(d,n,r);var u=$(d);d.size=(u.xRange.max-u.xRange.min)*(u.yRange.max-u.yRange.min),d.bounds=u}}f.sort(function(d,v){return!d.size||!v.size?0:v.size-d.size});var l=f[0].bounds,c=(l.xRange.max-l.xRange.min)/50;function h(d,v,p){if(d&&!(!d.size||!d.bounds)){var y=d.bounds,m,C,b;v?m=l.xRange.max-y.xRange.min+c:(m=l.xRange.max-y.xRange.max,b=(y.xRange.max-y.xRange.min)/2-(l.xRange.max-l.xRange.min)/2,b<0&&(m+=b)),p?C=l.yRange.max-y.yRange.min+c:(C=l.yRange.max-y.yRange.max,b=(y.yRange.max-y.yRange.min)/2-(l.yRange.max-l.yRange.min)/2,b<0&&(C+=b));for(var I=0;I<d.length;++I){let O=d[I];O&&(O.x+=m,O.y+=C,t.push(O))}}}for(var g=1;g<f.length;)h(f[g],!0,!1),h(f[g+1],!1,!0),h(f[g+2],!0,!0),g+=3,l=$(t);var x={};for(let d of t)x[d.setid]=d;return x}function W(e,n,r,t){var a=[],i=[];for(var s in e){let y=e[s];y&&(i.push(s),a.push(y))}n-=2*t,r-=2*t;var f=$(a),u=f.xRange,o=f.yRange;if(u.max==u.min||o.max==o.min)return e;for(var l=n/(u.max-u.min),c=r/(o.max-o.min),h=Math.min(c,l),g=(n-(u.max-u.min)*h)/2,x=(r-(o.max-o.min)*h)/2,d={},v=0;v<a.length;++v){var p=a[v];let y=i[v];!p||!y||(d[y]={...p,radius:h*p.radius,x:t+g+(p.x-u.min)*h,y:t+x+(p.y-o.min)*h})}return d}var ne=require("fmin");function be(e,n){let{circles:r,intersections:t}=te(e,n);return{$schema:"https://vega.github.io/schema/vega/v5.json",width:n.width,height:n.height,padding:n.padding,data:[{name:"circles",values:r},{name:"intersections",values:t}],scales:[{name:"color",type:"ordinal",domain:{data:"circles",field:"set_id"},range:"category"}],marks:[{type:"symbol",from:{data:"circles"},encode:{enter:{x:{field:"x"},y:{field:"y"},size:{field:"size"},shape:{value:"circle"},fillOpacity:{value:.3},fill:{scale:"color",field:"set_id"},tooltip:[{field:"text",type:"quantitative"}]},hover:{fillOpacity:{value:.5}},update:{fillOpacity:{value:.3}}}},{type:"path",from:{data:"intersections"},encode:{enter:{path:{field:"path"},fill:{value:"grey"},fillOpacity:{value:0},tooltip:[{field:"text",type:"quantitative"}]},hover:{stroke:{value:"black"},strokeWidth:{value:1},fill:{value:"grey"}},update:{strokeWidth:{value:0}}}},{type:"text",from:{data:"intersections"},encode:{enter:{x:{field:"textX"},y:{field:"textY"},text:{field:"size"},fontSize:{value:14},fill:{scale:"color",field:"set_id"},fontWeight:{value:"normal"}}}}]}}function te(e,{layout:n,height:r,width:t,padding:a,seed:i,orientation:s,set_id_delimiter:f,orientationOrder:u}){let o=e.filter(x=>x.size!==0&&x.sets.length>0);if(o.length===0)return{circles:[],intersections:[]};let l=T(o,{layout:n,seed:i});s!==Math.PI/2&&(l=V(l,s,u)),l=W(l,t,r,a);let c=ae(l,o),h=o.map(x=>{let d=x.sets.join(","),{x:v,y:p,disjoint:y}=c[d];return{set_id:x.sets.join(f),sets:x.sets,path:re(x.sets.map(m=>l[m])),textX:y?void 0:v,textY:y?void 0:p,size:x.size}}).filter(x=>x.sets.length>1);return{circles:Object.entries(l).map(([x,d])=>({set_id:x,x:d.x,y:d.y,size:Math.pow(d.radius*2,2),textX:c[x].x,textY:c[x].y})),intersections:h}}function re(e){let{stats:n}=S(e);var r=n.arcs;if(r.length===0)return"M 0 0";if(r.length===1){var t=r[0].circle;return ie(t.x,t.y,t.radius)}var a=[` M`,r[0].p2.x,r[0].p2.y];for(let i of r){let s=i.circle.radius,f=i.width>s;a.push(` A`,s,s,0,f?1:0,1,i.p1.x,i.p1.y)}return a.join(" ")}function ie(e,n,r){var t=[];return t.push(` M`,e.toString(),n.toString()),t.push(` m`,-r,0),t.push(` a`,r,r,0,1,0,r*2,0),t.push(` a`,r,r,0,1,0,-r*2,0),t.join(" ")}function ae(e,n,r=","){for(var t={},a=pe(e),i=0;i<n.length;++i){for(var s=n[i].sets,f={},u={},o=0;o<s.length;++o){f[s[o]]=!0;var l=a[s[o]];if(l)for(var c=0;c<l.length;++c)u[l[c]]=!0}var h=[],g=[];for(var x in e)x in f?h.push(e[x]):x in u||g.push(e[x]);var d=Y(h,g);t[s.join(r)]=d,d.disjoint&&n[i].size>0&&console.log("WARNING: area "+s+" not represented on screen")}return t}function pe(e){var n={},r=Object.keys(e);r.forEach(u=>n[u]=[]);for(var t=0;t<r.length;t++)for(var a=e[r[t]],i=t+1;i<r.length;++i){var s=e[r[i]],f=z(a,s);f+s.radius<=a.radius+1e-10?n[r[i]].push(r[t]):f+a.radius<=s.radius+1e-10&&n[r[t]].push(r[i])}return n}function Y(e,n){var r=[],t;for(t=0;t<e.length;++t){var a=e[t];a&&(r.push({x:a.x,y:a.y}),r.push({x:a.x+a.radius/2,y:a.y}),r.push({x:a.x-a.radius/2,y:a.y}),r.push({x:a.x,y:a.y+a.radius/2}),r.push({x:a.x,y:a.y-a.radius/2}))}var i=r[0],s=X(r[0],e,n);for(t=1;t<r.length;++t){var f=X(r[t],e,n);f>=s&&(i=r[t],s=f)}var u=(0,ne.nelderMead)(function(c){return-1*X({x:c[0],y:c[1]},e,n)},[i.x,i.y],{maxIterations:500,minErrorDelta:1e-10}).x,o={x:u[0],y:u[1]},l=!0;for(t=0;t<e.length;++t)if(z(o,e[t])>e[t].radius){l=!1;break}for(t=0;t<n.length;++t)if(z(o,n[t])<n[t].radius){l=!1;break}if(!l)if(e.length==1)o={x:e[0].x,y:e[0].y};else{let{stats:c}=S(e);c.arcs.length===0?o={x:0,y:-1e3,disjoint:!0}:c.arcs.length===1?o={x:c.arcs[0].circle.x,y:c.arcs[0].circle.y}:n.length?o=Y(e,[]):o=_(c.arcs.map(function(h){return h.p1}))}return o}function X(e,n,r){var t=n[0].radius-z(n[0],e),a,i;for(a=1;a<n.length;++a)i=n[a].radius-z(n[a],e),i<=t&&(t=i);for(a=0;a<r.length;++a)i=z(r[a],e)-r[a].radius,i<=t&&(t=i);return t}0&&(module.exports={bestInitialLayout,chartVega,circleArea,circleCircleIntersection,circleOverlap,circlePath,computeTextCentre,computeTextCentres,constrainedMDSLayout,containedInCircles,disjointCluster,distance,distanceFromIntersectArea,getCenter,getDistanceMatrices,greedyLayout,intersectionArea,intersectionAreaPath,lossFunction,normalizeSolution,scaleSolution,venn,vennSolution});