@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 6.32 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import t from"../../../core/RandomLCG.js";import{Placement as s}from"../CIMPlacements.js";import{PlacementGridType as i}from"../enums.js";const e=512,h=10,n=24,_=1e-6;class r{static{this.instance=null}static local(){return null===r.instance&&(r.instance=new r),r.instance}execute(t,s,i,e,h){return new a(t,s,i,e,h)}}class a{constructor(h,n,_,r,a){if(this._xMin=0,this._xMax=0,this._yMin=0,this._yMax=0,this._currentX=0,this._currentY=0,this._accelerationMap=null,this._testInsidePolygon=!1,this._verticalSubdivision=!0,this._stepX=Math.abs(n.stepX??16)*_,this._stepY=Math.abs(n.stepY??16)*_,this._stepX=Math.round(128*this._stepX)/128,this._stepY=Math.round(128*this._stepY)/128,0!==this._stepX&&0!==this._stepY){if(this._gridType=n.gridType??i.Fixed,this._gridType===i.Random){const s=n.seed??13,i=1;this._randomLCG=new t(s*i),this._randomness=(n.randomness??100)/100,this._gridAngle=0,this._shiftOddRows=!1,this._cosAngle=1,this._sinAngle=0,this._offsetX=0,this._offsetY=0,this._buildRandomValues()}else{if(this._randomness=0,this._gridAngle=n.gridAngle??0,this._shiftOddRows=n.shiftOddRows??!1,this._offsetX=(n.offsetX??0)*_,this._offsetY=(n.offsetY??0)*_,this._cosAngle=Math.cos(this._gridAngle/180*Math.PI),this._sinAngle=-Math.sin(this._gridAngle/180*Math.PI),this._stepX)if(this._offsetX<0)for(;this._offsetX<-.5*this._stepX;)this._offsetX+=this._stepX;else for(;this._offsetX>=.5*this._stepX;)this._offsetX-=this._stepX;if(this._stepY)if(this._offsetY<0)for(;this._offsetY<-.5*this._stepY;)this._offsetY+=this._stepY;else for(;this._offsetY>=.5*this._stepY;)this._offsetY-=this._stepY}if(this._graphicOriginX=0,this._graphicOriginY=0,null!=r){const[t,s,i,h]=r.split("/"),n=parseFloat(t),_=parseFloat(s),a=parseFloat(i),o=parseFloat(h);this._graphicOriginX=-(o*2**n+a)*e,this._graphicOriginY=_*e,this._testInsidePolygon=!0}this._internalPlacement=new s,this._calculateMinMax(h),this._geometryCursor=h}}next(){return this._geometryCursor?this._nextInside():null}_buildRandomValues(){if(!a._randValues){a._randValues=[];for(let t=0;t<n;t++)for(let s=0;s<n;s++)a._randValues.push(this._randomLCG.getFloat()),a._randValues.push(this._randomLCG.getFloat())}}_calculateMinMax(t){let s,i,h,n,_,r,a,o,l,f,c,u,p,M;this._xMin=0,this._xMax=0,this._yMin=0,this._yMax=0,a=o=p=c=Number.MAX_VALUE,l=f=M=u=-Number.MAX_VALUE;const g=1!==this._cosAngle;for(t.reset();t.nextPath();)for(;t.nextPoint();)r=t.x,_=t.y,s=r-this._graphicOriginX-this._offsetX,i=_-this._graphicOriginY-this._offsetY,g?(h=this._cosAngle*s-this._sinAngle*i,n=this._sinAngle*s+this._cosAngle*i):(h=s,n=i),a=Math.min(a,h),l=Math.max(l,h),o=Math.min(o,n),f=Math.max(f,n),c=Math.min(c,_),u=Math.max(u,_),p=Math.min(p,r),M=Math.max(M,r);c=c!==Number.MAX_VALUE?c:-512-this._stepY,u=u!==-Number.MAX_VALUE?u:this._stepY,p=p!==Number.MAX_VALUE?p:-this._stepX,M=M!==-Number.MAX_VALUE?M:e+this._stepX;const d=u-c,X=M-p;if(this._verticalSubdivision=d>=X,this._polygonMin=this._verticalSubdivision?c:p,this._testInsidePolygon){let t=0-this._graphicOriginX-this._offsetX-this._stepX,s=e-this._graphicOriginX-this._offsetX+this._stepX,i=-512-this._graphicOriginY-this._offsetY-this._stepY,h=0-this._graphicOriginY-this._offsetY+this._stepY;if(g){const e=[[t,i],[t,h],[s,i],[s,h]];t=i=Number.MAX_VALUE,s=h=-Number.MAX_VALUE;for(const n of e){const e=this._cosAngle*n[0]-this._sinAngle*n[1],_=this._sinAngle*n[0]+this._cosAngle*n[1];t=Math.min(t,e),s=Math.max(s,e),i=Math.min(i,_),h=Math.max(h,_)}}a=a!==Number.MAX_VALUE?Math.max(a,t):t,o=o!==Number.MAX_VALUE?Math.max(o,i):i,l=l!==-Number.MAX_VALUE?Math.min(l,s):s,f=f!==-Number.MAX_VALUE?Math.min(f,h):h}this._xMin=Math.round(a/this._stepX),this._xMax=Math.round(l/this._stepX),this._yMin=Math.round(o/this._stepY),this._yMax=Math.round(f/this._stepY),this._currentX=this._xMax+1,this._currentY=this._yMin-1,this._buildAccelerationMap(t,p,M,c,u)}_buildAccelerationMap(t,s,i,n,_){t.reset();const r=new Map,a=this._verticalSubdivision,o=a?_-n:i-s;let f=Math.ceil(o/h);if(f<=1)return;const c=Math.floor(o/f);let u,p,M,g,d,X,m,x,A,Y,y;for(f++,this._delta=c,a?(A=-512-2*this._stepY,Y=2*this._stepY,y=n):(A=-2*this._stepX,Y=e+2*this._stepX,y=s);t.nextPath();)if(!(t.pathSize<2)&&t.nextPoint())for(u=t.x,p=t.y;t.nextPoint();u=M,p=g){if(M=t.x,g=t.y,a){if(p===g||p<A&&g<A||p>Y&&g>Y)continue;d=Math.min(p,g),X=Math.max(p,g)}else{if(u===M||u<A&&M<A||u>Y&&M>Y)continue;d=Math.min(u,M),X=Math.max(u,M)}for(;d<X;)m=Math.floor((d-y)/c),l(m,u,p,M,g,r),d+=c;x=Math.floor((X-y)/c),x>m&&l(x,u,p,M,g,r)}this._accelerationMap=r}_nextInside(){for(;;){if(this._currentX>this._xMax){if(this._currentY++,this._currentY>this._yMax)return null;this._currentX=this._xMin,this._shiftOddRows&&this._currentY%2&&this._currentX--}let t=this._currentX*this._stepX+this._offsetX;this._shiftOddRows&&this._currentY%2&&(t+=.5*this._stepX);const s=this._currentY*this._stepY+this._offsetY;let e,h;if(this._currentX++,this._gridType===i.Random){const i=(this._currentX%n+n)%n,_=(this._currentY%n+n)%n;e=this._graphicOriginX+t+this._stepX*this._randomness*(.5-a._randValues[_*n+i])*2/3,h=this._graphicOriginY+s+this._stepY*this._randomness*(.5-a._randValues[_*n+i+1])*2/3}else e=this._graphicOriginX+this._cosAngle*t+this._sinAngle*s,h=this._graphicOriginY-this._sinAngle*t+this._cosAngle*s;if(!this._testInsidePolygon||this._isInsidePolygon(e,h,this._geometryCursor))return this._internalPlacement.setTranslate(e,h),this._internalPlacement}}_isInsidePolygon(t,s,i){if(null==this._accelerationMap)return o(t,s,i);t+=_,s+=_;const e=this._verticalSubdivision,h=e?s:t,n=Math.floor((h-this._polygonMin)/this._delta),r=this._accelerationMap.get(n);if(!r)return!1;let a,l,f,c=0;for(const _ of r){if(a=_[0],l=_[1],e){if(a[1]>s==l[1]>s)continue;f=(l[0]-a[0])*(s-a[1])-(l[1]-a[1])*(t-a[0])}else{if(a[0]>t==l[0]>t)continue;f=(l[1]-a[1])*(t-a[0])-(l[0]-a[0])*(s-a[1])}f>0?c++:c--}return 0!==c}}function o(t,s,i){let e,h,n,r,a=0;for(t+=_,s+=_,i.reset();i.nextPath();)if(i.nextPoint())for(e=i.x,h=i.y;i.nextPoint();e=n,h=r){if(n=i.x,r=i.y,h>s==r>s)continue;(n-e)*(s-h)-(r-h)*(t-e)>0?a++:a--}return 0!==a}function l(t,s,i,e,h,n){let _=n.get(t);_||(_=[],n.set(t,_)),_.push([[s,i],[e,h]])}export{r as PlacementInsidePolygon};