@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 5.98 kB
JavaScript
import{Point as e}from"../../../../geometry/support/TileClipper.js";import{C_DEG_TO_RAD as t,C_PI as i,C_INFINITY as n,radToByte as s,positiveMod as o,C_2PI as a}from"./GeometryUtils.js";import{SDF_GLYPH_SIZE as l,TextShaping as h,SDF_GLYPH_BASELINE as r}from"./TextShaping.js";import{DECLUTTER_TILES as c}from"./decluttering/config.js";import{RotationAlignment as g,SymbolAnchor as m}from"./style/StyleDefinition.js";const x=4096,d=512,p=8,w=.5,T=2;class y{constructor(e,t,i=0,n=-1,s=w){this.x=e,this.y=t,this.angle=i,this.segment=n,this.minzoom=s}}class f{constructor(e,t,i,s,o,a=w,l=n){this.anchor=e,this.labelAngle=t,this.glyphAngle=i,this.page=s,this.alternateVerticalGlyph=o,this.minzoom=a,this.maxzoom=l}}class I{constructor(e,t,i,n,s,o,a,l,h,r,c,g){this.tl=e,this.tr=t,this.bl=i,this.br=n,this.mosaicRect=s,this.labelAngle=o,this.minAngle=a,this.maxAngle=l,this.anchor=h,this.minzoom=r,this.maxzoom=c,this.page=g}}class u{constructor(e){this.shapes=e}}class b{getIconPlacement(n,s,o){const a=new e(n.x,n.y),l=o.rotationAlignment===g.MAP,h=o.keepUpright;let r=o.rotate*t;l&&(r+=n.angle);const m=new u([]);return o.allowOverlap&&o.ignorePlacement||!c||(m.iconColliders=[]),this._addIconPlacement(m,a,s,o,r),l&&h&&this._addIconPlacement(m,a,s,o,r+i),m}_addIconPlacement(t,i,s,o,a){const l=s.pixelRatio,h=s.width/l,r=s.height/l,g=o.offset;let x=g[0],d=g[1];switch(o.anchor){case m.CENTER:x-=h/2,d-=r/2;break;case m.LEFT:d-=r/2;break;case m.RIGHT:x-=h,d-=r/2;break;case m.TOP:x-=h/2;break;case m.BOTTOM:x-=h/2,d-=r;break;case m.TOP_LEFT:break;case m.BOTTOM_LEFT:d-=r;break;case m.TOP_RIGHT:x-=h;break;case m.BOTTOM_RIGHT:x-=h,d-=r}const p=s.rect,T=2/l,y=x-T,f=d-T,u=y+p.width/l,b=f+p.height/l,P=new e(y,f),O=new e(u,b),_=new e(y,b),k=new e(u,f);if(0!==a){const e=Math.cos(a),t=Math.sin(a);P.rotate(e,t),O.rotate(e,t),_.rotate(e,t),k.rotate(e,t)}const M=new I(P,k,_,O,p,a,0,256,i,w,n,0);if(t.shapes.push(M),(!o.allowOverlap||!o.ignorePlacement)&&c){const e=o.size,s=o.padding,l={xTile:i.x,yTile:i.y,dxPixels:x*e-s,dyPixels:d*e-s,hard:!o.optional,partIndex:0,width:h*e+2*s,height:r*e+2*s,angle:a,minLod:w,maxLod:n};t.iconColliders.push(l)}}getTextPlacement(s,o,a,c){const x=new e(s.x,s.y),d=c.rotate*t,y=c.rotationAlignment===g.MAP,b=c.keepUpright,P=c.padding;let O=w;const _=!y?0:s.angle,k=s.segment>=0&&y,M=c.allowOverlap&&c.ignorePlacement?null:[],E=[],G=4,N=!k;let A=Number.POSITIVE_INFINITY,L=Number.NEGATIVE_INFINITY,z=A,F=L;const v=(k||y)&&b,R=c.size/l;let B=!1;for(const e of o)if(e.vertical){B=!0;break}let H,V=0,j=0;if(!k&&B){const e=h.getTextBox(o,c.lineHeight*l);switch(c.anchor){case m.LEFT:V=e.height/2,j=-e.width/2;break;case m.RIGHT:V=-e.height/2,j=e.width/2;break;case m.TOP:V=e.height/2,j=e.width/2;break;case m.BOTTOM:V=-e.height/2,j=-e.width/2;break;case m.TOP_LEFT:V=e.height;break;case m.BOTTOM_LEFT:j=-e.width;break;case m.TOP_RIGHT:j=e.width;break;case m.BOTTOM_RIGHT:V=-e.height}}V+=c.offset[0]*l,j+=c.offset[1]*l;for(const t of o){const o=t.glyphMosaicItem;if(!o||o.rect.isEmpty)continue;const l=o.rect,h=o.metrics,g=o.page;if(M&&N){if(void 0!==H&&H!==t.y){let e,t,i,o;B?(e=-F+V,t=A+j,i=F-z,o=L-A):(e=A+V,t=z+j,i=L-A,o=F-z);const a={xTile:s.x,yTile:s.y,dxPixels:e*R-P,dyPixels:t*R-P,hard:!c.optional,partIndex:1,width:i*R+2*P,height:o*R+2*P,angle:d,minLod:w,maxLod:n};M.push(a),A=Number.POSITIVE_INFINITY,L=Number.NEGATIVE_INFINITY,z=A,F=L}H=t.y}const m=[];if(k){const e=.5*o.metrics.width,i=(t.x+h.left-G+e)*R*p;if(O=this._placeGlyph(s,O,i,a,s.segment,1,t.vertical,g,m),b&&(O=this._placeGlyph(s,O,i,a,s.segment,-1,t.vertical,g,m)),O>=T)break}else m.push(new f(x,_,_,g,!1)),y&&b&&m.push(new f(x,_+i,_+i,g,!1));const u=t.x+h.left,C=t.y-r-h.top,S=u+h.width,Y=C+h.height;let q,U,D,J,K,Q,W,X;if(!k&&B)if(t.vertical){const t=(u+S)/2-h.height/2,i=(C+Y)/2+h.width/2;q=new e(-i-G+V,t-G+j),U=new e(q.x+l.width,q.y+l.height),D=new e(q.x,U.y),J=new e(U.x,q.y)}else q=new e(-C+G+V,u-G+j),U=new e(q.x-l.height,q.y+l.width),D=new e(U.x,q.y),J=new e(q.x,U.y);else q=new e(u-G+V,C-G+j),U=new e(q.x+l.width,q.y+l.height),D=new e(q.x,U.y),J=new e(U.x,q.y);for(const i of m){let n,o,a,r;if(i.alternateVerticalGlyph){if(!K){const t=(C+Y)/2+j;K=new e((u+S)/2+V-h.height/2-G,t+h.width/2+G),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,o=W,a=X,r=Q}else n=q,o=D,a=J,r=U;const g=C,m=Y,x=i.glyphAngle+d;if(0!==x){const e=Math.cos(x),t=Math.sin(x);n=n.clone(),o=o?.clone(),a=a?.clone(),r=r?.clone(),n.rotate(e,t),r?.rotate(e,t),o?.rotate(e,t),a?.rotate(e,t)}let p=0,w=256;if(k&&B?t.vertical?i.alternateVerticalGlyph?(p=32,w=96):(p=224,w=32):(p=224,w=96):(p=192,w=64),E.push(new I(n,a,o,r,l,i.labelAngle,p,w,i.anchor,i.minzoom,i.maxzoom,i.page)),M&&(!v||this._legible(i.labelAngle)))if(N)u<A&&(A=u),g<z&&(z=g),S>L&&(L=S),m>F&&(F=m);else if(i.minzoom<T){const e={xTile:s.x,yTile:s.y,dxPixels:(u+V)*R-P,dyPixels:(g+V)*R-P,hard:!c.optional,partIndex:1,width:(S-u)*R+2*P,height:(m-g)*R+2*P,angle:x,minLod:i.minzoom,maxLod:i.maxzoom};M.push(e)}}}if(O>=T)return null;if(M&&N){let e,t,i,o;B?(e=-F+V,t=A+j,i=F-z,o=L-A):(e=A+V,t=z+j,i=L-A,o=F-z);const a={xTile:s.x,yTile:s.y,dxPixels:e*R-P,dyPixels:t*R-P,hard:!c.optional,partIndex:1,width:i*R+2*P,height:o*R+2*P,angle:d,minLod:w,maxLod:n};M.push(a)}const C=new u(E);return M&&M.length>0&&(C.textColliders=M),C}_legible(e){const t=s(e);return t<65||t>=193}_placeGlyph(t,s,l,h,r,c,g,m,x){let d=c;const p=d<0?o(t.angle+i,a):t.angle;let w=0;l<0&&(d*=-1,l*=-1,w=i),d>0&&++r;let T=new e(t.x,t.y),y=h[r],I=n;if(h.length<=r)return I;for(;;){const e=y.x-T.x,t=y.y-T.y,i=Math.sqrt(e*e+t*t),n=Math.max(l/i,s),c=e/i,u=t/i,b=o(Math.atan2(u,c)+w,a);if(x.push(new f(T,p,b,m,!1,n,I)),g&&x.push(new f(T,p,b,m,!0,n,I)),n<=s)return n;T=y.clone();do{if(r+=d,h.length<=r||r<0)return n;y=h[r]}while(T.isEqual(y));let P=y.x-T.x,O=y.y-T.y;const _=Math.sqrt(P*P+O*O);P*=i/_,O*=i/_,T.x-=P,T.y-=O,I=n}}}export{y as Anchor,I as PlacedSymbol,u as Placement,b as PlacementEngine,x as TILE_COORD_SIZE,p as TILE_PIXEL_RATIO,d as TILE_PIXEL_SIZE};