@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 5.79 kB
JavaScript
import{unwrap as t}from"../../core/maybe.js";import n from"../../core/PriorityQueue.js";import{create as e}from"./aaBoundingRect.js";import{getBoundsXY as i,getPointsBounds as r}from"./boundsUtils.js";import{ringCentroid as o,ringsCentroid as s}from"./centroid.js";import{getRingArea as a,projectPointOnLine as c,distanceFromPointToPolygon as l}from"./coordsUtils.js";import{segmentIntersects as f}from"./intersectsBase.js";const N=100*222045e-21;function u(t){const{rings:n}=t;if(!n||0===n.length)return null;const s=i(e(),t);if(!s)return null;const c=4*(Math.abs(s[0])+Math.abs(s[2])+Math.abs(s[1])+Math.abs(s[3])+1)*N;let l=0,f=0;for(let e=0;e<n.length;e++){const t=a(n[e]);t>f&&(f=t,l=e)}if(Math.abs(f)<=2*c*c){const t=r(e(),n[l]);return[(t[0]+t[2])/2,(t[1]+t[3])/2]}const u=o(n[l],!1,e());if(null===u)return null;if(1===n.length&&n[0].length<4)return u;const d=[[NaN,NaN],[NaN,NaN],[NaN,NaN],[NaN,NaN]],x=[NaN,NaN,NaN,NaN],M=[NaN,NaN,NaN,NaN];let b=!1,w=m(u,t,!0);0===w.distance&&(b=!0,d[0][0]=u[0],d[0][1]=u[1],w=m(u,t,!1)),x[0]=w.distance,M[0]=0;const y=[NaN,NaN];let C=!1,k=.25,P=-1;const T=r(e(),n[l]);let z=NaN;do{if(z=NaN,d[1]=g(t,p(T[0],T[2],k),c,s),isNaN(d[1][0])||isNaN(d[1][1])||(w=m(d[1],t,!1),z=w.distance),!isNaN(z)&&z>c&&h(d[1],t))C=!0,x[1]=z,M[1]=j(d[1],u);else if(!isNaN(z)&&z>P&&(P=z,y[0]=d[1][0],y[1]=d[1][1]),k-=.01,k<.1){if(!(P>=0))break;C=!0,x[1]=P,d[1][0]=y[0],d[1][1]=y[1],M[1]=j(d[1],u)}}while(!C);C=!1,k=.5,P=-1;let D=.01,S=1;do{if(z=NaN,d[2]=g(t,p(T[0],T[2],k),c,s),isNaN(d[2][0])||isNaN(d[2][1])||(w=m(d[2],t,!1),z=w.distance),!isNaN(z)&&z>c&&h(d[2],t))C=!0,x[2]=z,M[2]=j(d[2],u);else if(!isNaN(z)&&z>P)P=z,y[0]=d[2][0],y[1]=d[2][1];else if(z>P&&(P=z,y[0]=d[2][0],y[1]=d[2][1]),k=.5+D*S,D+=.01,S*=-1,k<.3||k>.7){if(!(P>=0))break;C=!0,x[2]=P,d[2][0]=y[0],d[2][1]=y[1],M[2]=j(d[2],u)}}while(!C);C=!1,k=.75,P=-1;do{if(z=NaN,d[3]=g(t,p(T[0],T[2],k),c,s),isNaN(d[3][0])||isNaN(d[3][1])||(w=m(d[3],t,!1),z=w.distance),!isNaN(z)&&z>c&&h(d[3],t))C=!0,x[3]=z,M[3]=j(d[3],u);else if(z>P&&(P=z,y[0]=d[3][0],y[1]=d[3][1]),k+=.01,k>.9){if(!(P>=0))break;C=!0,x[3]=P,d[3][0]=y[0],d[3][1]=y[1],M[3]=j(d[3],u)}}while(!C);const B=[0,1,2,3],Q=b?0:1;let R;for(let e=Q;e<4;e++)for(let t=Q;t<3;t++){const n=M[t],e=M[t+1];q(n,e)>0&&(R=B[t],B[t]=B[t+1],B[t+1]=R,M[t]=e,M[t+1]=n)}let U=Q,v=0,A=0;for(let e=Q;e<4;e++){switch(e){case 0:A=2*x[B[e]];break;case 1:A=1.66666666*x[B[e]];break;case 2:A=1.33333333*x[B[e]];break;case 3:A=x[B[e]]}A>v&&(v=A,U=B[e])}return d[U]}function h(t,n){const{rings:e}=n;let i=0;for(const r of e){const n=r.length;for(let e=1;e<n;++e){const n=r[e-1],o=r[e];if(n[1]>t[1]==o[1]>t[1])continue;(o[0]-n[0])*(t[1]-n[1])-(o[1]-n[1])*(t[0]-n[0])>0?i++:i--}}return 0!==i}function m(t,n,e){if(e&&h(t,n))return{coord:t,distance:0};let i=1/0,r=0,o=0;const s=[0,0],{rings:a}=n;for(const l of a)if(!(l.length<2))for(let n=0;n<l.length-1;n++){c(s,t,l,n);const e=j(t,s);e<i&&(i=e,r=s[0],o=s[1])}return{coord:[r,o],distance:Math.sqrt(i)}}function g(t,n,i,r){const o=[n,0];let s=1/0,a=1/0,c=!1,l=!1;const N=[[n,r[1]-1],[n,r[3]+1]],u=[0,0],h=[0,0],m=[0,0],g=[[0,0],[0,0]],x=e(),{rings:M}=t;for(const e of M)if(!(e.length<2))for(let t=1;t<e.length;t++){if(g[0][0]=e[t-1][0],g[0][1]=e[t-1][1],g[1][0]=e[t][0],g[1][1]=e[t][1],null===d(x,g))continue;if(h[0]=N[0][0],h[1]=N[0][1],m[0]=N[1][0],m[1]=N[1][1],0===y(x,h,m))continue;if(!f(N[0],N[1],g[0],g[1],u))continue;const n=u[1];s>a?n<s&&(s=n,c=!0):n<a&&(a=n,l=!0)}return c&&l?o[1]=(s+a)/2:o[0]=o[1]=NaN,o}function d(t,n){if(n.length<2)return null;t||(t=e());const[i,r]=n[0],[o,s]=n[1];return t[0]=Math.min(i,o),t[1]=Math.min(r,s),t[2]=Math.max(i,o),t[3]=Math.max(r,s),t}const x=1,M=4,b=3,w=12;function y(t,n,e){let i=C(n,t),r=C(e,t);const o=t[0],s=t[1],a=t[2],c=t[3];if(i&r)return 0;if(!(i|r))return 4;const l=(i?1:0)|(r?2:0);do{const l=e[0]-n[0],f=e[1]-n[1];if(l>f)i&b?(i&x?(n[1]+=f*(o-n[0])/l,n[0]=o):(n[1]+=f*(a-n[0])/l,n[0]=a),i=C(n,t)):r&b?(r&x?(e[1]+=f*(o-e[0])/l,e[0]=o):(e[1]+=f*(a-e[0])/l,e[0]=a),r=C(e,t)):i?(i&M?(n[0]+=l*(s-n[1])/f,n[1]=s):(n[0]+=l*(c-n[1])/f,n[1]=c),i=C(n,t)):(r&M?(e[0]+=l*(s-e[1])/f,e[1]=s):(e[0]+=l*(c-e[1])/f,e[1]=c),r=C(e,t));else if(i&w?(i&M?(n[0]+=l*(s-n[1])/f,n[1]=s):(n[0]+=l*(c-n[1])/f,n[1]=c),i=C(n,t)):r&w?(r&M?(e[0]+=l*(s-e[1])/f,e[1]=s):(e[0]+=l*(c-e[1])/f,e[1]=c),r=C(e,t)):i?(i&x?(n[1]+=f*(o-n[0])/l,n[0]=o):(n[1]+=f*(a-n[0])/l,n[0]=a),i=C(n,t)):(r&x?(e[1]+=f*(o-e[0])/l,e[0]=o):(e[1]+=f*(a-e[0])/l,e[0]=a),r=C(e,t)),i&r)return 0}while(i|r);return l}function C(t,n){return(t[0]<n[0]?1:0)|(t[0]>n[2]?1:0)<<1|(t[1]<n[1]?1:0)<<2|(t[1]>n[3]?1:0)<<3}function p(t,n,e){return t+(n-t)*e}function j(t,n){return(t[0]-n[0])*(t[0]-n[0])+(t[1]-n[1])*(t[1]-n[1])}function q(t,n){if(t<n)return-1;if(t>n)return 1;if(t===n)return 0;const e=isNaN(t),i=isNaN(n);return e<i?-1:e>i?1:0}class k{constructor(t,n,e,i){this.x=t,this.y=n,this.cellSize=e,this.distancefromCellCenter=l(t,n,i),this.maxDistanceToPolygon=this.distancefromCellCenter+this.cellSize*Math.SQRT2}}const P=1,T=100;function z(i){if(!i||!i.rings||0===i.rings.length)return null;const o=r(e(),i.rings[0]);if(!o)return null;const a=o[2]-o[0],c=o[3]-o[1];if(0===a||0===c)return[o[0]+a/2,o[1]+c/2];const l=Math.max(Math.min(a,c)/T,P),f=new n(((t,n)=>n.maxDistanceToPolygon-t.maxDistanceToPolygon)),N=Math.min(a,c);let u=N/2,h=0,m=0;for(h=o[0];h<o[2];h+=N)for(m=o[1];m<o[3];m+=N)f.enqueue(new k(h+u,m+u,u,i));const g=s(i.rings,!1);if(null===g)return null;let d,x=new k(g[0],g[1],0,i);for(;f.size>0;)d=t(f.dequeue()),d.distancefromCellCenter>x.distancefromCellCenter&&(x=d),d.maxDistanceToPolygon-x.distancefromCellCenter<=l||(u=d.cellSize/2,f.enqueue(new k(d.x-u,d.y-u,u,i)),f.enqueue(new k(d.x+u,d.y-u,u,i)),f.enqueue(new k(d.x-u,d.y+u,u,i)),f.enqueue(new k(d.x+u,d.y+u,u,i)));return[x.x,x.y]}export{u as getLabelPoint,z as getPolylabelPoint};