UNPKG

region2d

Version:

A JavaScript implementation of the Region abstract data type, which GUIs use to perform constructive solid geometry with 2-D rectangles.

1 lines 14.1 kB
"use strict";function RegionError(n){this.message=(this.name="RegionError")+": "+n;var r=String((new Error).stack).split("\n");r.shift(),r.shift(),this.stack=r.join("\n")}RegionError.prototype=Object.create?Object.create(Error.prototype):new Error;var Region1D=function(){function n(n,u,a){if(u===k)"number"!=typeof a&&(a=p(n));else{if("undefined"!=typeof u||"undefined"!=typeof a)throw new e("Illegal access");w(n),a=p(n)}this._opaque=i({array:n,min:n.length?n[0]:r,max:n.length?n[n.length-1]:t,hash:a},k)}var r=Number.POSITIVE_INFINITY,t=Number.NEGATIVE_INFINITY,e=RegionError,i=function(n,r){return function(t){if(t===r)return n;throw new e("Illegal access")}},u=function(n){return Array.isArray?Array.isArray(n):n instanceof Array},a=function(n,r){var t=0,e=0;return function(){return t>=n.length&&e>=r.length?null:t>=n.length?{x:r[e],kind:1&e++?-1:1,src:2}:e>=r.length||n[t]<r[e]?{x:n[t],kind:1&t++?-1:1,src:1}:{x:r[e],kind:1&e++?-1:1,src:2}}},o=function(n,r,t){if(!n.length&&!r.length)return[];var e=a(n,r),i=0,u=0,o=0,l=0,f=e(),s=[];do{1===f.src?i+=f.kind:u+=f.kind;for(var h=void 0;(h=e())&&h.x===f.x;)1===h.src?i+=h.kind:u+=h.kind;l=o,o=t(i,u),o!==l&&s.push(f.x),f=h}while(f);return s},l=function(n,r){return o(n,r,function(n,r){return n|r})},f=function(n,r){return o(n,r,function(n,r){return n&r})},s=function(n,r){return o(n,r,function(n,r){return n^r})},h=function(n,r){return o(n,r,function(n,r){return n&~r})},m=function(n,r,t){if(!n.length||!r.length)return"";if(n[n.length-1]<r[0]||r[r.length-1]<n[0])return"";var e=0,i=0,u=a(n,r),o=u(),l=3;do{1===o.src?e+=o.kind:i+=o.kind;for(var f=void 0;(f=u())&&f.x===o.x;)1===f.src?e+=f.kind:i+=f.kind;if(e&i){if(l|=4,t)return"intersect"}else i&~e?l&=-2:e&~i&&(l&=-3);o=f}while(o);switch(l){case 4:return"intersect";case 5:return"a-contain-b";case 6:return"b-contain-a";case 7:return"equal";default:return""}},c=function(n,r){if(!n.length)return!1;if(r<n[0]||r>n[n.length-1])return!1;if(n.length<=8){for(var t=0,e=n.length;e>t;t+=2)if(r>=n[t]&&r<n[t+1])return!0;return!1}for(var i=0,u=n.length,a=0;u>i;){var o=(i+u)/2&-1,l=n[o];if(r===l){a=o;break}l>r?u=o:(a=o,i=o+1)}return!(1&a)},g=function(n){var e=[],i=0;if(!n.length)return e.push(t),e.push(r),e;for(n[i]!=t?e.push(t):i++;i<n.length-1;)e.push(n[i++]);return n[i]!=r&&(e.push(n[i++]),e.push(r)),e},y=function(n,i,u){if(u=Number(u),!(u>t&&r>u))throw new e("Invalid translation delta");if(i=Number(i),!(i>t&&r>i)||0===i)throw new e("Invalid scale ratio");for(var a=[],o=0,l=n.length;l>o;o++)a[o]=n[o]*i+u;return a},x=function(n,r){if(n.length!==r.length)return!1;for(var t=0,e=n.length;e>t;t++)if(n[t]!==r[t])return!1;return!0},v=function(n,r,t,e){for(var i=t-r,u=0,a=n.length;a>u;u+=2){var o=n[u],l=n[u+1];e.push({x:o,y:r,width:l-o,height:i,left:o,top:r,right:l,bottom:t})}return e},d=function(n){for(var r=[],t=0,e=n.length;e>t;t+=2)r.push(n[t]),r.push(n[t+1]);return r},p=function(n){for(var r=0,t=0,e=n.length;e>t;t++)r*=23,r+=0|n[t],r&=-1;return r},Y=function(r){if(!(r instanceof n))throw new e("Object must be a Region1D instance.")},w=function(n){var r="Expected an ordered array of numeric start/end pairs.",t="Array start/end pairs are not in strictly ascending order.";if(!u(n)||1&n.length)throw new e(r);if(0!=n.length){var i=n[0];if("number"!=typeof i)throw new e(r);for(var a=1,o=n.length;o>a;a++){var l=n[a];if("number"!=typeof l)throw new e(r);if(i>=l)throw new e(t);i=l}}},k={},b=function(n){return n._opaque(k)};return n.prototype={union:function(r){Y(r);var t=b(this),e=b(r);return new n(l(t.array,e.array),k)},intersect:function(r){Y(r);var t=b(this),e=b(r);return new n(f(t.array,e.array),k)},subtract:function(r){Y(r);var t=b(this),e=b(r);return new n(h(t.array,e.array),k)},xor:function(r){Y(r);var t=b(this),e=b(r);return new n(s(t.array,e.array),k)},not:function(){var r=b(this);return new n(g(r.array),k)},transform:function(r,t){var e=b(this);return new n(y(e.array,r,t))},translate:function(r){var t=b(this);return new n(y(t.array,1,r))},scale:function(r){var t=b(this);return new n(y(t.array,r,0))},isEmpty:function(){return!b(this).array.length},getCount:function(){return b(this).array.length>>1},doesIntersect:function(n){return Y(n),!!m(b(this).array,b(n).array,!0)},relate:function(n){return Y(n),m(b(this).array,b(n).array,!1)},isPointIn:function(n){return c(b(this).array,Number(n))},equals:function(n){Y(n);var r=b(this),t=b(n);return r===t?!0:r.hash!==t.hash?!1:x(r.array,t.array)},getRawSpans:function(){var n=b(this);return d(n.array)},getAsRects:function(n,r,t){var e=b(this);return v(e.array,n,r,t||[])},getBounds:function(){var n=b(this);return{min:n.min,max:n.max}},getHashCode:function(){return b(this).hash}},n.empty=new n([],k,0),n}(),Region2D=function(){function n(n,r){var t=r===_?n:"undefined"!=typeof n?b(n):N();this._opaque=a(t,_)}var r=void 0,t=void 0,e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY,u=RegionError,a=function(n,r){return function(t){if(t===r)return n;throw new u("Illegal access")}},o=function(n){return Array.isArray?Array.isArray(n):n instanceof Array},l=function(n,r){var t=0,e=0,u=i,a=Region1D.empty;return function(){if(t>=n.length){if(e>=r.length)return null;var i={row1:a,row2:r[e].region,minY:Math.max(r[e].minY,u),maxY:u=r[e].maxY};return e++,i}if(e>=r.length){var o={row1:n[t].region,row2:a,minY:Math.max(n[t].minY,u),maxY:u=n[t].maxY};return t++,o}var l=n[t],f=r[e],s=Math.max(l.minY,u),h=Math.max(f.minY,u),m=void 0,c=void 0,g=void 0,y=void 0;s===h?(g=s,m=l.region,c=f.region,f.maxY<l.maxY?(u=y=f.maxY,e++):f.maxY===l.maxY?(u=y=l.maxY,t++,e++):(u=y=l.maxY,t++)):h>s?(g=s,m=l.region,c=a,h>=l.maxY?(u=y=l.maxY,t++):u=y=h):(g=h,m=a,c=f.region,s>=f.maxY?(u=y=f.maxY,e++):u=y=s);var x={row1:m,row2:c,minY:g,maxY:y};return x}},f=function(n,r,t){for(var u,a=l(n,r),o=null,f=[],s=e,h=i,m=0,c=0;u=a();){var g=t(u.row1,u.row2);if(!g.isEmpty())if(o&&g.equals(o.region)&&o.maxY==u.minY)o.maxY=u.maxY;else{f.push(o={region:g,minY:u.minY,maxY:u.maxY}),c+=g.getCount();var y=g.getBounds();y.min<s&&(s=y.min),y.max>h&&(h=y.max),m*=23,m+=0|g.getHashCode(),m&=-1}}var x={array:f,count:c,minX:s,minY:f.length?f[0].minY:e,maxX:h,maxY:f.length?f[f.length-1].maxY:i,hash:m};return x},s=function(n,r){return f(n,r,function(n,r){return n.union(r)})},h=function(n,r){return f(n,r,function(n,r){return n.intersect(r)})},m=function(n,r){return f(n,r,function(n,r){return n.xor(r)})},c=function(n,r){return f(n,r,function(n,r){return n.subtract(r)})},g=function(n){var r=[];if(1===n.length){for(var t=n[0].region.getRawSpans(),e=n[0].minY,i=n[0].maxY,u=0;u<t.length;u+=2)r.push({x1:t[u],y1:e,x2:t[u+1],y2:e,kind:"top",key1:null,key2:null,next:null,prev:null,used:!1}),r.push({x1:t[u+1],y1:e,x2:t[u+1],y2:i,kind:"right",key1:null,key2:null,next:null,prev:null,used:!1}),r.push({x1:t[u+1],y1:i,x2:t[u],y2:i,kind:"bottom",key1:null,key2:null,next:null,prev:null,used:!1}),r.push({x1:t[u],y1:i,x2:t[u],y2:e,kind:"left",key1:null,key2:null,next:null,prev:null,used:!1});return r}for(var a=n[0].region.getRawSpans(),o=n[0].minY,l=n[0].maxY,f=0;f<a.length;f+=2)r.push({x1:a[f],y1:o,x2:a[f+1],y2:o,kind:"top",key1:null,key2:null,next:null,prev:null,used:!1}),r.push({x1:a[f+1],y1:o,x2:a[f+1],y2:l,kind:"right",key1:null,key2:null,next:null,prev:null,used:!1}),r.push({x1:a[f],y1:l,x2:a[f],y2:o,kind:"left",key1:null,key2:null,next:null,prev:null,used:!1});for(var s=1,h=n.length;h>s;s++){if(o=n[s].minY,l=n[s].maxY,o>n[s-1].maxY){for(var m=0;m<a.length;m+=2)r.push({x1:a[m+1],y1:n[s-1].maxY,x2:a[m],y2:n[s-1].maxY,kind:"bottom",key1:null,key2:null,next:null,prev:null,used:!1});a=n[s].region.getRawSpans();for(var c=0;c<a.length;c+=2)r.push({x1:a[c],y1:o,x2:a[c+1],y2:o,kind:"top",key1:null,key2:null,next:null,prev:null,used:!1})}else{var g=n[s-1].region.subtract(n[s].region);a=g.getRawSpans();for(var y=0;y<a.length;y+=2)r.push({x1:a[y+1],y1:o,x2:a[y],y2:o,kind:"bottom",key1:null,key2:null,next:null,prev:null,used:!1});g=n[s].region.subtract(n[s-1].region),a=g.getRawSpans();for(var x=0;x<a.length;x+=2)r.push({x1:a[x],y1:o,x2:a[x+1],y2:o,kind:"top",key1:null,key2:null,next:null,prev:null,used:!1})}a=n[s].region.getRawSpans();for(var v=0;v<a.length;v+=2)r.push({x1:a[v+1],y1:o,x2:a[v+1],y2:l,kind:"right",key1:null,key2:null,next:null,prev:null,used:!1}),r.push({x1:a[v],y1:l,x2:a[v],y2:o,kind:"left",key1:null,key2:null,next:null,prev:null,used:!1})}for(var d=0;d<a.length;d+=2)r.push({x1:a[d+1],y1:l,x2:a[d],y2:l,kind:"bottom",key1:null,key2:null,next:null,prev:null,used:!1});return r},y=function(n){for(var r={},t=0,e=n.length;e>t;t++){var i=n[t];i.key1=i.x1+","+i.y1,i.key2=i.x2+","+i.y2,i.prev=t>0?n[t-1]:null,i.next=e-1>t?n[t+1]:null,i.key1 in r?r[i.key1].push(i):r[i.key1]=[i]}return r},x=function(n,r){for(var t=[],e=n[0],i=n[n.length-1],a=function(n){n.next?n.next.prev=n.prev:i=n.prev,n.prev?n.prev.next=n.next:e=n.next,n.used=!0},o=function(n,r){if(1===r.length&&!r.used)return r[0];for(var t=0,e=r.length;e>t;t++)if(!r[t].used)switch(n.kind){case"top":if("right"===r[t].kind)return r[t];break;case"right":if("bottom"===r[t].kind)return r[t];break;case"bottom":if("left"===r[t].kind)return r[t];break;case"left":if("top"===r[t].kind)return r[t]}for(var i=0,a=r.length;a>i;i++)if(!r[i].used)return r[i];throw new u("Edge generation failure.")};e;){for(var l=[],f=e;"top"!==f.kind;)f=f.next;a(f),l.push({x:f.x1,y:f.y1});for(var s=f,h=f.x1,m=null;s.key2!==f.key1;){var c=r[s.key2];s=o(s,c),a(s),s.x1===h&&h===m?l[l.length-1].y=s.y1:l.push({x:s.x1,y:s.y1}),m=h,h=s.x1}l[0].x===h&&h===m&&l.pop(),t.push(l)}return t},v=function(n){if(!n.length)return[];var r=g(n),t=y(r),e=x(r,t);return e},d=function(n,r,t,a,o){if(a=Number(a),o=Number(o),!(a>i&&e>a&&o>i&&e>o))throw new u("Invalid translation delta");if(r=Number(r),t=Number(t),!(r>i&&e>r&&0!==r&&t>i&&e>t&&0!==t))throw new u("Invalid scale ratio");for(var l=[],f=0,s=n.length;s>f;f++){var h=n[f];l[f]={region:h.region.transform(r,a),minY:h.minY*t+o,maxY:h.maxY*t+o}}return l},p=function(n,r){return!(n.minX>r.maxX||n.maxX<r.minX||n.minY>r.maxY||n.maxY<r.minY)},Y="Cannot construct a Region2D from ",w=Y+"invalid rectangle data.",k=Y+"a rectangle of zero or negative size.",b=function(n){var r=void 0,t=void 0,e=void 0,i=void 0;if("undefined"!=typeof HTMLElement&&n instanceof HTMLElement){var a=n.getBoundingClientRect();r=window.scrollX+a.left,e=window.scrollY+a.top,t=window.scrollX+a.right,i=window.scrollY+a.bottom}else if(o(n)){if(4!==n.length)throw new u(w);r=Number(n[0]),e=Number(n[1]),t=Number(n[2]),i=Number(n[3])}else if("left"in n)r=Number(n.left),e=Number(n.top),t=Number(n.right),i=Number(n.bottom);else{if(!("x"in n))throw new u(w);r=Number(n.x),e=Number(n.y),t=r+Number(n.width),i=e+Number(n.height)}if(r>=t||e>=i)throw new u(k);var l=new Region1D([r,t]),f={array:[{region:l,minY:e,maxY:i}],count:1,minX:r,minY:e,maxX:t,maxY:i,hash:l.getHashCode()};return f},N=function(){return{array:[],count:0,minX:e,minY:e,maxX:i,maxY:i,hash:0}},I="Invalid row data for row ",R=function(n){for(var r=i,t=0,u=e,a=i,o=0,l=[],f=0,s=n.length;s>f;f++){var h=n[f];if(h.minY<r||h.minY>=h.maxY||!(h.region instanceof Region1D))throw new RegionError(I+f);l.push({region:h.region,minY:h.minY,maxY:h.maxY});var m=h.region.getCount();if(!m)throw new RegionError(I+f);t+=m;var c=h.region.getBounds();c.min<u&&(u=c.min),c.max>a&&(a=c.max),o*=23,o+=0|h.region.getHashCode(),o&=-1,r=h.maxY}return{array:l,count:t,minX:u,minY:l.length?l[0].minY:e,maxX:a,maxY:l.length?l[l.length-1].maxY:i,hash:o}},E=function(n){return{x:n.minX,y:n.minY,width:n.maxX-n.minX,height:n.maxY-n.minY,left:n.minX,top:n.minY,right:n.maxX,bottom:n.maxY}},X=function(n){for(var r=[],t=0,e=n.length;e>t;t++){var i=n[t];r.push({minY:i.minY,maxY:i.maxY,region:i.region})}return r},A=function(n){for(var r=[],t=0,e=n.length;e>t;t++){var i=n[t];i.region.getAsRects(i.minY,i.maxY,r)}return r},C=function(n){return n.minX===i||n.minY===i||n.maxX===e||n.maxY===e},S=function(n,r){if(n.length!=r.length)return!1;for(var t=0,e=n.length;e>t;t++){if(n[t].minY!==r[t].minY||n[t].maxY!==r[t].maxY)return!1;if(!n[t].region.equals(r[t].region))return!1}return!0},T=function(n,r){return!!h(n.array,r.array).array.length},q=function(n,r,t){var e=n.array;if(!e.length)return!1;if(t<n.minY||t>n.maxY||r<n.minX||r>n.maxX)return!1;if(e.length<=5){for(var i=0,u=e.length;u>i;i++)if(t>=e[i].minY&&t<e[i].maxY)return e[i].region.isPointIn(r);return!1}for(var a=0,o=e.length;o>a;){var l=(a+o)/2&-1,f=e[l];if(t>=f.minY&&t<f.maxY)return f.region.isPointIn(r);t<f.minY?o=l:a=l+1}return!1},D=function(r){if(!(r instanceof n))throw new u("Object must be a Region2D instance.")},_={},H=function(n){return n._opaque(_)};return n.prototype={union:function(r){D(r);var t=H(this),e=H(r);return new n(s(t.array,e.array),_)},intersect:function(r){D(r);var e=H(this),i=H(r);return p(e,i)?new n(h(e.array,i.array),_):t},subtract:function(r){D(r);var t=H(this),e=H(r);return p(t,e)?new n(c(t.array,e.array),_):this},xor:function(r){D(r);var t=H(this),e=H(r);return new n(m(t.array,e.array),_)},not:function(){var t=H(this),e=H(r);return new n(m(t.array,e.array),_)},transform:function(r,t,e,i){var u=H(this);return new n(R(d(u.array,r,t,e,i)),_)},translate:function(r,t){var e=H(this);return new n(R(d(e.array,1,1,r,t)),_)},scale:function(r,t){var e=H(this);return new n(R(d(e.array,r,t,0,0)),_)},isEmpty:function(){return!H(this).array.length},isInfinite:function(){return C(H(this))},isFinite:function(){return!C(H(this))},isRectangular:function(){return 1===H(this).count},doesIntersect:function(n){return D(n),T(H(this),H(n))},isPointIn:function(n,r){return q(H(this),Number(n),Number(r))},equals:function(n){D(n);var r=H(this),t=H(n);return r===t?!0:r.hash!==t.hash||r.count!==t.count?!1:S(r.array,t.array)},getCount:function(){return H(this).count},getRects:function(){return A(H(this).array)},getRawRows:function(){return X(H(this).array)},getBounds:function(){return E(H(this))},getPath:function(){return v(H(this).array)},getHashCode:function(){return H(this).hash}},n.infinite=r=new n([i,i,e,e]),n.empty=t=new n,n.fromRects=function(r){if(!r.length)return t;for(var e=new n(r[0]),i=1,u=r.length;u>i;i++)e=e.union(new n(r[i]));return e},n.fromRawRows=function(r){return new n(R(r),_)},n}();