sweepline-intersections
Version:
A module to check if a polygon self-intersects using a sweepline algorithm
2 lines (1 loc) • 6.3 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).sweeplineIntersections=t()}(this,(function(){"use strict";var e=function(e,n){if(void 0===e&&(e=[]),void 0===n&&(n=t),this.data=e,this.length=this.data.length,this.compare=n,this.length>0)for(var r=(this.length>>1)-1;r>=0;r--)this._down(r)};function t(e,t){return e<t?-1:e>t?1:0}function n(e,t){return e.p.x>t.p.x?1:e.p.x<t.p.x?-1:e.p.x!==t.p.x||e.featureId===t.featureId&&e.ringId===t.ringId||!e.isLeftEndpoint||t.isLeftEndpoint?e.p.y!==t.p.y?e.p.y>t.p.y?1:-1:1:-1}function r(e,t){return e.rightSweepEvent.p.x>t.rightSweepEvent.p.x?1:e.rightSweepEvent.p.x<t.rightSweepEvent.p.x?-1:e.rightSweepEvent.p.y!==t.rightSweepEvent.p.y?e.rightSweepEvent.p.y<t.rightSweepEvent.p.y?1:-1:1}e.prototype.push=function(e){this.data.push(e),this.length++,this._up(this.length-1)},e.prototype.pop=function(){if(0!==this.length){var e=this.data[0],t=this.data.pop();return this.length--,this.length>0&&(this.data[0]=t,this._down(0)),e}},e.prototype.peek=function(){return this.data[0]},e.prototype._up=function(e){for(var t=this.data,n=this.compare,r=t[e];e>0;){var i=e-1>>1,p=t[i];if(n(r,p)>=0)break;t[e]=p,e=i}t[e]=r},e.prototype._down=function(e){for(var t=this.data,n=this.compare,r=this.length>>1,i=t[e];e<r;){var p=1+(e<<1),o=t[p],f=p+1;if(f<this.length&&n(t[f],o)<0&&(p=f,o=t[f]),n(o,i)>=0)break;t[e]=o,e=p}t[e]=i};var i=function(e,t,n,r){this.p={x:e[0],y:e[1]},this.featureId=t,this.ringId=n,this.eventId=r,this.otherEvent=null,this.isLeftEndpoint=null};i.prototype.isSamePoint=function(e){return this.p.x===e.p.x&&this.p.y===e.p.y},i.prototype.asNewXY=function(){return[this.p.x,this.p.y]};var p=0,o=0,f=0;function a(e,t){var r="Feature"===e.type?e.geometry:e,a=r.coordinates;"Polygon"!==r.type&&"MultiLineString"!==r.type||(a=[a]),"LineString"===r.type&&(a=[[a]]);for(var h=0;h<a.length;h++)for(var s=0;s<a[h].length;s++){var v=a[h][s][0],u=null;o+=1;for(var l=0;l<a[h][s].length-1;l++){u=a[h][s][l+1];var w=new i(v,p,o,f),E=new i(u,p,o,f+1);w.otherEvent=E,E.otherEvent=w,n(w,E)>0?(E.isLeftEndpoint=!0,w.isLeftEndpoint=!1):(w.isLeftEndpoint=!0,E.isLeftEndpoint=!1),t.push(w),t.push(E),v=u,f+=1}}p+=1}var h=function(e){this.leftSweepEvent=e,this.rightSweepEvent=e.otherEvent},s=11102230246251565e-32,v=134217729,u=(3+8*s)*s;function l(e,t,n,r,i){var p,o,f,a,h=t[0],s=r[0],v=0,u=0;s>h==s>-h?(p=h,h=t[++v]):(p=s,s=r[++u]);var l=0;if(v<e&&u<n)for(s>h==s>-h?(f=p-((o=h+p)-h),h=t[++v]):(f=p-((o=s+p)-s),s=r[++u]),p=o,0!==f&&(i[l++]=f);v<e&&u<n;)s>h==s>-h?(f=p-((o=p+h)-(a=o-p))+(h-a),h=t[++v]):(f=p-((o=p+s)-(a=o-p))+(s-a),s=r[++u]),p=o,0!==f&&(i[l++]=f);for(;v<e;)f=p-((o=p+h)-(a=o-p))+(h-a),h=t[++v],p=o,0!==f&&(i[l++]=f);for(;u<n;)f=p-((o=p+s)-(a=o-p))+(s-a),s=r[++u],p=o,0!==f&&(i[l++]=f);return 0===p&&0!==l||(i[l++]=p),l}function w(e){return new Float64Array(e)}var E=w(4),S=w(8),g=w(12),d=w(16),y=w(4);function c(e,t,n,r,i,p){var o=(t-p)*(n-i),f=(e-i)*(r-p),a=o-f;if(0===o||0===f||o>0!=f>0)return a;var h=Math.abs(o+f);return Math.abs(a)>=33306690738754716e-32*h?a:-function(e,t,n,r,i,p,o){var f,a,h,s,w,c,x,m,I,L,P,b,N,X,Y,_,M,k,F=e-i,T=n-i,j=t-p,A=r-p;w=(Y=(m=F-(x=(c=v*F)-(c-F)))*(L=A-(I=(c=v*A)-(c-A)))-((X=F*A)-x*I-m*I-x*L))-(P=Y-(M=(m=j-(x=(c=v*j)-(c-j)))*(L=T-(I=(c=v*T)-(c-T)))-((_=j*T)-x*I-m*I-x*L))),E[0]=Y-(P+w)+(w-M),w=(N=X-((b=X+P)-(w=b-X))+(P-w))-(P=N-_),E[1]=N-(P+w)+(w-_),w=(k=b+P)-b,E[2]=b-(k-w)+(P-w),E[3]=k;var C=function(e,t){for(var n=t[0],r=1;r<e;r++)n+=t[r];return n}(4,E),q=22204460492503146e-32*o;if(C>=q||-C>=q)return C;if(f=e-(F+(w=e-F))+(w-i),h=n-(T+(w=n-T))+(w-i),a=t-(j+(w=t-j))+(w-p),s=r-(A+(w=r-A))+(w-p),0===f&&0===a&&0===h&&0===s)return C;if(q=11093356479670487e-47*o+u*Math.abs(C),(C+=F*s+A*f-(j*h+T*a))>=q||-C>=q)return C;w=(Y=(m=f-(x=(c=v*f)-(c-f)))*(L=A-(I=(c=v*A)-(c-A)))-((X=f*A)-x*I-m*I-x*L))-(P=Y-(M=(m=a-(x=(c=v*a)-(c-a)))*(L=T-(I=(c=v*T)-(c-T)))-((_=a*T)-x*I-m*I-x*L))),y[0]=Y-(P+w)+(w-M),w=(N=X-((b=X+P)-(w=b-X))+(P-w))-(P=N-_),y[1]=N-(P+w)+(w-_),w=(k=b+P)-b,y[2]=b-(k-w)+(P-w),y[3]=k;var z=l(4,E,4,y,S);w=(Y=(m=F-(x=(c=v*F)-(c-F)))*(L=s-(I=(c=v*s)-(c-s)))-((X=F*s)-x*I-m*I-x*L))-(P=Y-(M=(m=j-(x=(c=v*j)-(c-j)))*(L=h-(I=(c=v*h)-(c-h)))-((_=j*h)-x*I-m*I-x*L))),y[0]=Y-(P+w)+(w-M),w=(N=X-((b=X+P)-(w=b-X))+(P-w))-(P=N-_),y[1]=N-(P+w)+(w-_),w=(k=b+P)-b,y[2]=b-(k-w)+(P-w),y[3]=k;var B=l(z,S,4,y,g);w=(Y=(m=f-(x=(c=v*f)-(c-f)))*(L=s-(I=(c=v*s)-(c-s)))-((X=f*s)-x*I-m*I-x*L))-(P=Y-(M=(m=a-(x=(c=v*a)-(c-a)))*(L=h-(I=(c=v*h)-(c-h)))-((_=a*h)-x*I-m*I-x*L))),y[0]=Y-(P+w)+(w-M),w=(N=X-((b=X+P)-(w=b-X))+(P-w))-(P=N-_),y[1]=N-(P+w)+(w-_),w=(k=b+P)-b,y[2]=b-(k-w)+(P-w),y[3]=k;var D=l(B,g,4,y,d);return d[D-1]}(e,t,n,r,i,p,h)}function x(e,t){if(null===e||null===t)return!1;var n=e.leftSweepEvent.p.x,r=e.leftSweepEvent.p.y,i=e.rightSweepEvent.p.x,p=e.rightSweepEvent.p.y,o=t.leftSweepEvent.p.x,f=t.leftSweepEvent.p.y,a=t.rightSweepEvent.p.x,h=t.rightSweepEvent.p.y,s=c(n,r,i,p,o,f),v=c(n,r,i,p,a,h);if(s>0&&v>0)return!1;if(s<0&&v<0)return!1;if(e.leftSweepEvent.ringId===t.leftSweepEvent.ringId){if(e.rightSweepEvent.isSamePoint(t.leftSweepEvent)||e.rightSweepEvent.isSamePoint(t.rightSweepEvent)||e.leftSweepEvent.isSamePoint(t.leftSweepEvent)||e.leftSweepEvent.isSamePoint(t.rightSweepEvent))return!1}else{if(e.rightSweepEvent.isSamePoint(t.leftSweepEvent))return t.leftSweepEvent.asNewXY();if(e.rightSweepEvent.isSamePoint(t.rightSweepEvent))return t.rightSweepEvent.asNewXY();if(e.leftSweepEvent.isSamePoint(t.leftSweepEvent))return t.leftSweepEvent.asNewXY();if(e.leftSweepEvent.isSamePoint(t.rightSweepEvent))return t.rightSweepEvent.asNewXY()}var u=(h-f)*(i-n)-(a-o)*(p-r),l=(a-o)*(r-f)-(h-f)*(n-o),w=(i-n)*(r-f)-(p-r)*(n-o);if(0===u)return!1;var E=l/u,S=w/u;return E>=0&&E<=1&&S>=0&&S<=1&&[n+E*(i-n),r+E*(p-r)]}return function(t,i){var p=new e([],n);return function(e,t){if("FeatureCollection"===e.type)for(var n=e.features,r=0;r<n.length;r++)a(n[r],t);else a(e,t)}(t,p),function(t,n){n=n||!1;for(var i=[],p=new e([],r);t.length;){var o=t.pop();if(o.isLeftEndpoint){for(var f=new h(o),a=0;a<p.data.length;a++){var s=p.data[a];if(!n||s.leftSweepEvent.featureId!==o.featureId){var v=x(f,s);!1!==v&&i.push(v)}}p.push(f)}else!1===o.isLeftEndpoint&&p.pop()}return i}(p,i)}}));