@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 5.61 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */
import{Point as e}from"../../../../geometry/support/TileClipper.js";import{tilePixelRatio as t}from"./constants.js";import{cDegToRad as i,cPi as n,cInfinity as s,positiveMod as a,radToByte as o,c2pi as h}from"./GeometryUtils.js";import{TextShaping as l,sdfGlyphSize as r,sdfGlyphBaseline as c}from"./TextShaping.js";const g=.5,x=2;class m{constructor(e,t,i=0,n=-1,s=g){this.x=e,this.y=t,this.angle=i,this.segment=n,this.minzoom=s}}class d{constructor(e,t,i,n,a,o=g,h=s){this.anchor=e,this.labelAngle=t,this.glyphAngle=i,this.page=n,this.alternateVerticalGlyph=a,this.minzoom=o,this.maxzoom=h}}class p{constructor(e,t,i,n,s,a,o,h,l,r,c,g){this.tl=e,this.tr=t,this.bl=i,this.br=n,this.mosaicRect=s,this.labelAngle=a,this.minAngle=o,this.maxAngle=h,this.anchor=l,this.minzoom=r,this.maxzoom=c,this.page=g}}class w{constructor(e){this.shapes=e}}class y{getIconPlacement(t,s,a){const o=new e(t.x,t.y),h=0===a.rotationAlignment,l=a.keepUpright;let r=a.rotate*i;h&&(r+=t.angle);const c=new w([]);return c.iconColliders=[],this._addIconPlacement(c,o,s,a,r),h&&l&&this._addIconPlacement(c,o,s,a,r+n),c}_addIconPlacement(t,i,n,a,o){const h=n.rasterizationScale,l=n.width/h,r=n.height/h,c=a.offset;let x=c[0],m=c[1];switch(a.anchor){case 0:x-=l/2,m-=r/2;break;case 1:m-=r/2;break;case 2:x-=l,m-=r/2;break;case 3:x-=l/2;break;case 4:x-=l/2,m-=r;break;case 5:break;case 7:m-=r;break;case 6:x-=l;break;case 8:x-=l,m-=r}const d=n.rect,w=2/h,y=x-w,f=m-w,b=y+d.width/h,u=f+d.height/h,I=new e(y,f),T=new e(b,u),k=new e(y,u),P=new e(b,f);if(0!==o){const e=Math.cos(o),t=Math.sin(o);I.rotate(e,t),T.rotate(e,t),k.rotate(e,t),P.rotate(e,t)}const N=new p(I,P,k,T,d,o,0,256,i,g,s,0);t.shapes.push(N);{const e=a.size,n=a.padding,h={xTile:i.x,yTile:i.y,dxPixels:x*e-n,dyPixels:m*e-n,hard:!a.optional,partIndex:0,width:l*e+2*n,height:r*e+2*n,angle:o,minLod:g,maxLod:s};t.iconColliders.push(h)}}getTextPlacement(a,o,h,m){const y=new e(a.x,a.y),{keepUpright:f,rotate:b,rotationAlignment:u,size:I}=m,T=b*i,k=0===u,P=f,N=m.padding;let z=g;const A=!k?0:a.angle,_=a.segment>=0&&k,G=[],M=[],E=4,L=!_;let V=Number.POSITIVE_INFINITY,v=Number.NEGATIVE_INFINITY,j=V,C=v;const F=(_||k)&&P,S=I/r;let Y=!1;for(const e of o)if(e.vertical){Y=!0;break}let q,U=0,O=0;if(!_&&Y){const e=l.getTextBox(o,m.lineHeight*r);switch(m.anchor){case 1:U=e.height/2,O=-e.width/2;break;case 2:U=-e.height/2,O=e.width/2;break;case 3:U=e.height/2,O=e.width/2;break;case 4:U=-e.height/2,O=-e.width/2;break;case 5:U=e.height;break;case 7:O=-e.width;break;case 6:O=e.width;break;case 8:U=-e.height}}U+=m.offset[0]*r,O+=m.offset[1]*r;for(const i of o){const o=i.glyphMosaicItem;if(!o||o.rect.isEmpty)continue;const l=o.rect,r=o.metrics,w=o.page;if(G&&L){if(void 0!==q&&q!==i.y){let e,t,i,n;Y?(e=-C+U,t=V+O,i=C-j,n=v-V):(e=V+U,t=j+O,i=v-V,n=C-j);const o={xTile:a.x,yTile:a.y,dxPixels:e*S-N,dyPixels:t*S-N,hard:!m.optional,partIndex:1,width:i*S+2*N,height:n*S+2*N,angle:T,minLod:g,maxLod:s};G.push(o),V=Number.POSITIVE_INFINITY,v=Number.NEGATIVE_INFINITY,j=V,C=v}q=i.y}const f=[];if(_){const e=.5*o.metrics.width,n=(i.x+r.left-E+e)*S*t;if(z=this._placeGlyph(a,z,n,h,a.segment,1,i.vertical,w,f),P&&(z=this._placeGlyph(a,z,n,h,a.segment,-1,i.vertical,w,f)),z>=x)break}else f.push(new d(y,A,A,w,!1)),k&&P&&f.push(new d(y,A+n,A+n,w,!1));const b=i.x+r.left,u=i.y-c-r.top,I=b+r.width,B=u+r.height;let H,R,D,J,K,Q,W,X;if(!_&&Y)if(i.vertical){const t=(b+I)/2-r.height/2,i=(u+B)/2+r.width/2;H=new e(-i-E+U,t-E+O),R=new e(H.x+l.width,H.y+l.height),D=new e(H.x,R.y),J=new e(R.x,H.y)}else H=new e(-u+E+U,b-E+O),R=new e(H.x-l.height,H.y+l.width),D=new e(R.x,H.y),J=new e(H.x,R.y);else H=new e(b-E+U,u-E+O),R=new e(H.x+l.width,H.y+l.height),D=new e(H.x,R.y),J=new e(R.x,H.y);for(const t of f){let n,s,o,h;if(t.alternateVerticalGlyph){if(!K){const t=(u+B)/2+O;K=new e((b+I)/2+U-r.height/2-E,t+r.width/2+E),Q=new e(K.x+l.height,K.y-l.width),W=new e(Q.x,K.y),X=new e(K.x,Q.y)}n=K,s=W,o=X,h=Q}else n=H,s=D,o=J,h=R;const c=u,g=B,d=t.glyphAngle+T;if(0!==d){const e=Math.cos(d),t=Math.sin(d);n=n.clone(),s=s?.clone(),o=o?.clone(),h=h?.clone(),n.rotate(e,t),h?.rotate(e,t),s?.rotate(e,t),o?.rotate(e,t)}let w=0,y=256;if(_&&Y?i.vertical?t.alternateVerticalGlyph?(w=32,y=96):(w=224,y=32):(w=224,y=96):(w=192,y=64),M.push(new p(n,o,s,h,l,t.labelAngle,w,y,t.anchor,t.minzoom,t.maxzoom,t.page)),G&&(!F||this._legible(t.labelAngle)))if(L)b<V&&(V=b),c<j&&(j=c),I>v&&(v=I),g>C&&(C=g);else if(t.minzoom<x){const e={xTile:a.x,yTile:a.y,dxPixels:(b+U)*S-N,dyPixels:(c+U)*S-N,hard:!m.optional,partIndex:1,width:(I-b)*S+2*N,height:(g-c)*S+2*N,angle:d,minLod:t.minzoom,maxLod:t.maxzoom};G.push(e)}}}if(z>=x)return null;if(G&&L){let e,t,i,n;Y?(e=-C+U,t=V+O,i=C-j,n=v-V):(e=V+U,t=j+O,i=v-V,n=C-j);const o={xTile:a.x,yTile:a.y,dxPixels:e*S-N,dyPixels:t*S-N,hard:!m.optional,partIndex:1,width:i*S+2*N,height:n*S+2*N,angle:T,minLod:g,maxLod:s};G.push(o)}const B=new w(M);return G&&G.length>0&&(B.textColliders=G),B}_legible(e){const t=o(e);return t<65||t>=193}_placeGlyph(t,i,o,l,r,c,g,x,m){let p=c;const w=p<0?a(t.angle+n,h):t.angle;let y=0;o<0&&(p*=-1,o*=-1,y=n),p>0&&++r;let f=new e(t.x,t.y),b=l[r],u=s;if(l.length<=r)return u;for(;;){const e=b.x-f.x,t=b.y-f.y,n=Math.sqrt(e*e+t*t),s=Math.max(o/n,i),c=e/n,I=t/n,T=a(Math.atan2(I,c)+y,h);if(m.push(new d(f,w,T,x,!1,s,u)),g&&m.push(new d(f,w,T,x,!0,s,u)),s<=i)return s;f=b.clone();do{if(r+=p,l.length<=r||r<0)return s;b=l[r]}while(f.isEqual(b));let k=b.x-f.x,P=b.y-f.y;const N=Math.sqrt(k*k+P*P);k*=n/N,P*=n/N,f.x-=k,f.y-=P,u=s}}}export{m as Anchor,p as PlacedSymbol,w as Placement,y as PlacementEngine};