@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 11.2 kB
JavaScript
import{isSome as e}from"../../../../core/maybe.js";import t from"../../../../core/ObjectPool.js";import n from"../../../../core/PooledArray.js";import{g as o,a as s,d as i,c as r,h}from"../../../../chunks/vec3.js";import{c as a,f as d}from"../../../../chunks/vec3f64.js";import{intersectsSphere as l}from"../../../../geometry/support/frustum.js";import{wrap as u}from"../../../../geometry/support/ray.js";import{h as c,a as f,g as _,j as m,c as p}from"../../../../chunks/sphere.js";import{rayBoxTest as b}from"./Util.js";class g{get bounds(){return this._root.bounds}get halfSize(){return this._root.halfSize}get root(){return this._root.node}get maximumObjectsPerNode(){return this._maximumObjectsPerNode}get maximumDepth(){return this._maximumDepth}get objectCount(){return this._objectCount}constructor(e,t){this._objectToBoundingSphere=e,this._maximumObjectsPerNode=10,this._maximumDepth=20,this._degenerateObjects=new Set,this._root=new S,this._objectCount=0,t&&(void 0!==t.maximumObjectsPerNode&&(this._maximumObjectsPerNode=t.maximumObjectsPerNode),void 0!==t.maximumDepth&&(this._maximumDepth=t.maximumDepth))}destroy(){this._degenerateObjects.clear(),S.clearPool(),R[0]=null,w.prune(),K.prune()}add(e,t=e.length){this._objectCount+=t,this._grow(e,t);const n=S.acquire();for(let o=0;o<t;o++){const t=e[o];this._isDegenerate(t)?this._degenerateObjects.add(t):(n.init(this._root),this._add(t,n))}S.release(n)}remove(t,n=null){this._objectCount-=t.length;const o=S.acquire();for(const s of t){const t=e(n)?n:c(this._objectToBoundingSphere(s),C);M(t[3])?(o.init(this._root),this._remove(s,t,o)):this._degenerateObjects.delete(s)}S.release(o),this._shrink()}update(e,t){if(!M(t[3])&&this._isDegenerate(e))return;const n=v(e);this.remove(n,t),this.add(n)}forEachAlongRay(e,t,n){const o=u(e,t);this._forEachNode(this._root,(e=>{if(!this._intersectsNode(o,e))return!1;const t=e.node;return t.terminals.forAll((e=>{this._intersectsObject(o,e)&&n(e)})),null!==t.residents&&t.residents.forAll((e=>{this._intersectsObject(o,e)&&n(e)})),!0}))}forEachAlongRayWithVerticalOffset(e,t,n,o){const s=u(e,t);this._forEachNode(this._root,(e=>{if(!this._intersectsNodeWithOffset(s,e,o))return!1;const t=e.node;return t.terminals.forAll((e=>{this._intersectsObjectWithOffset(s,e,o)&&n(e)})),null!==t.residents&&t.residents.forAll((e=>{this._intersectsObjectWithOffset(s,e,o)&&n(e)})),!0}))}forEach(e){this._forEachNode(this._root,(t=>{const n=t.node;return n.terminals.forAll(e),null!==n.residents&&n.residents.forAll(e),!0})),this._degenerateObjects.forEach(e)}forEachDegenerateObject(e){this._degenerateObjects.forEach(e)}findClosest(e,t,n,i=(()=>!0),r=1/0){let h=1/0,a=1/0,d=null;const u=z(e,t),c=o=>{if(--r,!i(o))return;const s=this._objectToBoundingSphere(o);if(!l(n,s))return;const u=E(e,t,_(s)),c=u-s[3],f=u+s[3];c<h&&(h=c,a=f,d=o)};return this._forEachNodeDepthOrdered(this._root,(i=>{if(r<=0||!l(n,i.bounds))return!1;o(y,u,i.halfSize),s(y,y,i.bounds);if(E(e,t,y)>a)return!1;const h=i.node;return h.terminals.forAll((e=>c(e))),null!==h.residents&&h.residents.forAll((e=>c(e))),!0}),e,t),d}forEachInDepthRange(e,t,n,i,r,h,a){let d=-1/0,u=1/0;const c={setRange:e=>{n===g.DepthOrder.FRONT_TO_BACK?(d=Math.max(d,e.near),u=Math.min(u,e.far)):(d=Math.max(d,-e.far),u=Math.min(u,-e.near))}};c.setRange(i);const f=E(t,n,e),m=z(t,n),p=z(t,-n),b=e=>{if(!a(e))return;const o=this._objectToBoundingSphere(e),s=_(o),i=E(t,n,s)-f,m=i-o[3],p=i+o[3];m>u||p<d||!l(h,o)||r(e,c)};this._forEachNodeDepthOrdered(this._root,(e=>{if(!l(h,e.bounds))return!1;o(y,m,e.halfSize),s(y,y,e.bounds);if(E(t,n,y)-f>u)return!1;o(y,p,e.halfSize),s(y,y,e.bounds);if(E(t,n,y)-f<d)return!1;const i=e.node;return i.terminals.forAll((e=>b(e))),null!==i.residents&&i.residents.forAll((e=>b(e))),!0}),t,n)}forEachNode(e){this._forEachNode(this._root,(t=>e(t.node,t.bounds,t.halfSize)))}forEachNeighbor(e,t){const n=f(t),o=_(t),s=t=>{const s=this._objectToBoundingSphere(t),r=f(s),h=n+r;return!(i(_(s),o)-h*h<=0)||e(t)};let r=!0;const h=e=>{r&&(r=s(e))};this._forEachNode(this._root,(e=>{const t=f(e.bounds),s=n+t;if(i(_(e.bounds),o)-s*s>0)return!1;const a=e.node;return a.terminals.forAll(h),r&&null!==a.residents&&a.residents.forAll(h),r})),r&&this.forEachDegenerateObject(h)}_intersectsNode(e,t){return x(t.bounds,2*-t.halfSize,k),x(t.bounds,2*t.halfSize,q),b(e.origin,e.direction,k,q)}_intersectsNodeWithOffset(e,t,n){return x(t.bounds,2*-t.halfSize,k),x(t.bounds,2*t.halfSize,q),n.applyToMinMax(k,q),b(e.origin,e.direction,k,q)}_intersectsObject(e,t){const n=this._objectToBoundingSphere(t);return!(n[3]>0)||m(n,e)}_intersectsObjectWithOffset(e,t,n){const o=this._objectToBoundingSphere(t);return!(o[3]>0)||m(n.applyToBoundingSphere(o),e)}_forEachNode(e,t){let n=S.acquire().init(e);const o=[n];for(;0!==o.length;){if(n=o.pop(),t(n)&&!n.isLeaf())for(let e=0;e<n.node.children.length;e++){n.node.children[e]&&o.push(S.acquire().init(n).advance(e))}S.release(n)}}_forEachNodeDepthOrdered(e,t,n,o=g.DepthOrder.FRONT_TO_BACK){let s=S.acquire().init(e);const i=[s];for(T(n,o,W);0!==i.length;){if(s=i.pop(),t(s)&&!s.isLeaf())for(let e=7;e>=0;--e){const t=W[e];s.node.children[t]&&i.push(S.acquire().init(s).advance(t))}S.release(s)}}_remove(e,t,n){w.clear();const o=n.advanceTo(t,((e,t)=>{w.push(e.node),w.push(t)}))?n.node.terminals:n.node.residents;if(o.removeUnordered(e),0===o.length)for(let s=w.length-2;s>=0;s-=2){const e=w.data[s],t=w.data[s+1];if(!this._purge(e,t))break}}_nodeIsEmpty(e){if(0!==e.terminals.length)return!1;if(null!==e.residents)return 0===e.residents.length;for(let t=0;t<e.children.length;t++)if(e.children[t])return!1;return!0}_purge(e,t){return t>=0&&(e.children[t]=null),!!this._nodeIsEmpty(e)&&(null===e.residents&&(e.residents=new n({shrink:!0})),!0)}_add(e,t){t.advanceTo(this._objectToBoundingSphere(e))?t.node.terminals.push(e):(t.node.residents.push(e),t.node.residents.length>this._maximumObjectsPerNode&&t.depth<this._maximumDepth&&this._split(t))}_split(e){const t=e.node.residents;e.node.residents=null;for(let n=0;n<t.length;n++){const o=S.acquire().init(e);this._add(t.getItemAt(n),o),S.release(o)}}_grow(e,t){if(0!==t&&(N(e,t,(e=>this._objectToBoundingSphere(e)),I),M(I[3])&&!this._fitsInsideTree(I)))if(this._nodeIsEmpty(this._root.node))c(I,this._root.bounds),this._root.halfSize=1.25*this._root.bounds[3],this._root.updateBoundsRadiusFromHalfSize();else{const e=this._rootBoundsForRootAsSubNode(I);this._placingRootViolatesMaxDepth(e)?this._rebuildTree(I,e):this._growRootAsSubNode(e),S.release(e)}}_rebuildTree(e,t){r(P,t.bounds),P[3]=t.halfSize,N([e,P],2,(e=>e),L);const n=S.acquire().init(this._root);this._root.initFrom(null,L,L[3]),this._root.increaseHalfSize(1.25),this._forEachNode(n,(e=>(this.add(e.node.terminals.data,e.node.terminals.length),null!==e.node.residents&&this.add(e.node.residents.data,e.node.residents.length),!0))),S.release(n)}_placingRootViolatesMaxDepth(e){const t=Math.log(e.halfSize/this._root.halfSize)*Math.LOG2E;let n=0;return this._forEachNode(this._root,(e=>(n=Math.max(n,e.depth),n+t<=this._maximumDepth))),n+t>this._maximumDepth}_rootBoundsForRootAsSubNode(e){const t=e[3],n=e;let o=-1/0;const s=this._root.bounds,i=this._root.halfSize;for(let h=0;h<3;h++){const e=s[h]-i-(n[h]-t),r=n[h]+t-(s[h]+i),a=Math.max(0,Math.ceil(e/(2*i))),d=Math.max(0,Math.ceil(r/(2*i)))+1,l=2**Math.ceil(Math.log(a+d)*Math.LOG2E);o=Math.max(o,l),H[h].min=a,H[h].max=d}for(let h=0;h<3;h++){let e=H[h].min,t=H[h].max;const n=(o-(e+t))/2;e+=Math.ceil(n),t+=Math.floor(n);const r=s[h]-i-e*i*2;F[h]=r+(t+e)*i}const r=o*i;return F[3]=r*B,S.acquire().initFrom(null,F,r,0)}_growRootAsSubNode(e){const t=this._root.node;r(I,this._root.bounds),I[3]=this._root.halfSize,this._root.init(e),e.advanceTo(I,null,!0),e.node.children=t.children,e.node.residents=t.residents,e.node.terminals=t.terminals}_shrink(){for(;;){const e=this._findShrinkIndex();if(-1===e)break;this._root.advance(e),this._root.depth=0}}_findShrinkIndex(){if(0!==this._root.node.terminals.length||this._root.isLeaf())return-1;let e=null;const t=this._root.node.children;let n=0,o=0;for(;o<t.length&&null==e;)n=o++,e=t[n];for(;o<t.length;)if(t[o++])return-1;return n}_isDegenerate(e){return!M(this._objectToBoundingSphere(e)[3])}_fitsInsideTree(e){const t=this._root.bounds,n=this._root.halfSize;return e[3]<=n&&e[0]>=t[0]-n&&e[0]<=t[0]+n&&e[1]>=t[1]-n&&e[1]<=t[1]+n&&e[2]>=t[2]-n&&e[2]<=t[2]+n}}class S{constructor(){this.bounds=p(),this.halfSize=0,this.initFrom(null,null,0,0)}init(e){return this.initFrom(e.node,e.bounds,e.halfSize,e.depth)}initFrom(t,n,o,s=this.depth){return this.node=e(t)?t:S.createEmptyNode(),e(n)&&c(n,this.bounds),this.halfSize=o,this.depth=s,this}increaseHalfSize(e){this.halfSize*=e,this.updateBoundsRadiusFromHalfSize()}updateBoundsRadiusFromHalfSize(){this.bounds[3]=this.halfSize*B}advance(e){let t=this.node.children[e];t||(t=S.createEmptyNode(),this.node.children[e]=t),this.node=t,this.halfSize/=2,this.depth++;const n=A[e];return this.bounds[0]+=n[0]*this.halfSize,this.bounds[1]+=n[1]*this.halfSize,this.bounds[2]+=n[2]*this.halfSize,this.updateBoundsRadiusFromHalfSize(),this}advanceTo(e,t,n=!1){for(;;){if(this.isTerminalFor(e))return t&&t(this,-1),!0;if(this.isLeaf()){if(!n)return t&&t(this,-1),!1;this.node.residents=null}const o=this._childIndex(e);t&&t(this,o),this.advance(o)}}isLeaf(){return null!=this.node.residents}isTerminalFor(e){return e[3]>this.halfSize/2}_childIndex(e){const t=this.bounds;return(t[0]<e[0]?1:0)+(t[1]<e[1]?2:0)+(t[2]<e[2]?4:0)}static createEmptyNode(){return{children:[null,null,null,null,null,null,null,null],terminals:new n({shrink:!0}),residents:new n({shrink:!0})}}static acquire(){return S._pool.acquire()}static release(e){S._pool.release(e)}static clearPool(){S._pool.prune()}}function O(e,t){e[0]=Math.min(e[0],t[0]-t[3]),e[1]=Math.min(e[1],t[1]-t[3]),e[2]=Math.min(e[2],t[2]-t[3])}function j(e,t){e[0]=Math.max(e[0],t[0]+t[3]),e[1]=Math.max(e[1],t[1]+t[3]),e[2]=Math.max(e[2],t[2]+t[3])}function x(e,t,n){n[0]=e[0]+t,n[1]=e[1]+t,n[2]=e[2]+t}function N(e,t,n,o){if(1===t){const t=n(e[0]);c(t,o)}else{k[0]=1/0,k[1]=1/0,k[2]=1/0,q[0]=-1/0,q[1]=-1/0,q[2]=-1/0;for(let o=0;o<t;o++){const t=n(e[o]);M(t[3])&&(O(k,t),j(q,t))}h(o,k,q,.5),o[3]=Math.max(q[0]-k[0],q[1]-k[1],q[2]-k[2])/2}}function T(e,t,n){if(!K.length)for(let o=0;o<8;++o)K.push({index:0,distance:0});for(let o=0;o<8;++o){const n=A[o];K.data[o].index=o,K.data[o].distance=E(e,t,n)}K.sort(((e,t)=>e.distance-t.distance));for(let o=0;o<8;++o)n[o]=K.data[o].index}function z(e,t){let n,o=1/0;for(let s=0;s<8;++s){const i=E(e,t,D[s]);i<o&&(o=i,n=D[s])}return n}function E(e,t,n){return t*(e[0]*n[0]+e[1]*n[1]+e[2]*n[2])}function M(e){return!isNaN(e)&&e!==-1/0&&e!==1/0&&e>0}S._pool=new t(S),function(e){var t;(t=e.DepthOrder||(e.DepthOrder={}))[t.FRONT_TO_BACK=1]="FRONT_TO_BACK",t[t.BACK_TO_FRONT=-1]="BACK_TO_FRONT"}(g||(g={}));const A=[d(-1,-1,-1),d(1,-1,-1),d(-1,1,-1),d(1,1,-1),d(-1,-1,1),d(1,-1,1),d(-1,1,1),d(1,1,1)],D=[d(-1,-1,-1),d(-1,-1,1),d(-1,1,-1),d(-1,1,1),d(1,-1,-1),d(1,-1,1),d(1,1,-1),d(1,1,1)],B=Math.sqrt(3),R=[null];function v(e){return R[0]=e,R}const F=p(),y=a(),k=a(),q=a(),w=new n,C=p(),I=p(),P=p(),L=p(),H=[{min:0,max:0},{min:0,max:0},{min:0,max:0}],K=new n,W=[0,0,0,0,0,0,0,0],V=g;export{V as default};