UNPKG

@doegis/core

Version:

DOE GIS API

3 lines (1 loc) 11.3 kB
import{deg2rad as e}from"../../../../../core/mathUtils.js";import{isSome as t,unwrapOr as s}from"../../../../../core/maybe.js";import{createLength as i,createArea as o}from"../../../../../core/quantityUtils.js";import{s as r,d as n}from"../../../../../chunks/vec2.js";import{a as h}from"../../../../../chunks/vec2f64.js";import{n as a,i as d,c as g,f as l,o as c,b as p,e as m,g as u,a as _}from"../../../../../chunks/vec3.js";import{c as f}from"../../../../../chunks/vec3f64.js";import{c as C}from"../../../../../chunks/vec4f64.js";import{getReferenceEllipsoid as S}from"../../../../../geometry/ellipsoidUtils.js";import{canProjectWithoutEngine as L,canProjectToWGS84ComparableLonLat as P,projectPointToVector as R,projectPointToWGS84ComparableLonLat as j,projectDirection as M,projectVectorToVector as A}from"../../../../../geometry/projection.js";import v from"../../../../../geometry/SpatialReference.js";import{getSphericalPCPF as W}from"../../../../../geometry/spatialReferenceEllipsoidUtils.js";import{Axis as w}from"../../../../../geometry/support/Axis.js";import{segmentIntersects as I}from"../../../../../geometry/support/intersectsBase.js";import{areaPoints2d as z}from"../../../../../geometry/support/triangle.js";import{MeasurementMode as U}from"../../interfaces.js";import{segmentLengthGeodesicVector as G,bestFitPlane as V,fitHemisphere as y,triangleAreaGeodesic as T,planePointDistance as F,boundingSphere as b,segmentLengthGeodesic as E,segmentLengthEuclidean as N}from"../../support/measurementUtils.js";import{midpoint as x}from"../../support/viewUtils.js";import{getElevationAtPoint as k}from"../../../support/ElevationProvider.js";import{makeOrthonormal as q,tangentFrame as D}from"../../../support/mathUtils.js";import{compactIndices as B}from"../../../webgl-engine/lib/Indices.js";import{triangulate as H}from"../../../../support/euclideanAreaMeasurementUtils.js";class X{constructor(e,t){this.positionsWorldCoords=[],this.positionsRenderCoords=[],this.positionsProjectedWorldCoords=[],this.positionsFittedRenderCoords=[],this.positionsGeographic=[],this.positionsSpherical=[],this.positionsStereographic=[],this.pathSegmentLengths=[],this.geodesicPathSegmentLengths=[],this.perimeterSegmentLengths=[],this.intersectingSegments=new Set,this.geodesicIntersectingSegments=new Set,this.triangleIndices=null,this.geodesicTriangleIndices=null,this.areaCentroidWorldCoords=f(),this.areaCentroidRenderCoords=f(),this.geodesicAreaCentroidRenderCoords=f(),this.area=null,this.geodesicArea=null,this.pathLength=null,this.geodesicPathLength=null,this.perimeterLength=null,this._length=0,this._centroidRenderCoords=f(),this._planeWorldCoords=C(),this._worldUp=f(),this._worldTangent=f(),this._frame=[f(),f(),f()],this._pathVersion=-1,this._validMeasurement=!1,this._hasCursorPoint=!1,this._mode=null,this._tempU=f(),this._tempV=f(),this._tempVec3=f(),this._tempSphere={center:f(),radius:0},this._sceneView=e,this.unitNormalizer=t}update(e,s,o,r,n,h,d){const g=this.unitNormalizer,l=this._sceneView.renderSpatialReference,c=this.unitNormalizer.spatialReference,p=t(s);if(this._pathVersion===e.version&&this._validMeasurement===r&&!d&&this._hasCursorPoint===p&&this._mode===h){return!e.isValidPolygon&&(this._updateCursorSegmentLength(e,s),!0)}this._pathVersion=e.version,this._validMeasurement=r,this._hasCursorPoint=p;const m=e.numVertices;this._resize(m);const u=W(o.spatialReference),_=L(o.spatialReference,u)&&P(o.spatialReference),{positionsGeographic:f,positionsWorldCoords:C,positionsRenderCoords:S,positionsSpherical:M}=this;e.forEachVertexPosition(((e,t)=>{Z(o.elevationProvider,e),R(e,C[t],c),R(e,S[t],l),_&&(j(e,f[t]),R(e,M[t],u),a(M[t],M[t]))}));const A=this._updatePathLengths(r);if(this.pathLength=this._length>1?i(g.normalizeDistance(A),"meters"):null,_){const e=this._updateGeodesicPathLengths(r,c);this.geodesicPathLength=this._length>1?i(e,"meters"):null}else this.geodesicPathLength=null;return this._updateCursorSegmentLength(e,s),this._updateMode(e,h),r?(this._updateArea(o,g,l,c,n),_&&this._updateGeodesicArea(o),!0):(this.area=null,this.geodesicArea=null,this.perimeterLength=null,this.triangleIndices=null,this.geodesicTriangleIndices=null,this.intersectingSegments.clear(),this.geodesicIntersectingSegments.clear(),!0)}getData(){return{positionsWorldCoords:this.positionsWorldCoords,positionsRenderCoords:this.positionsRenderCoords,positionsProjectedWorldCoords:this.positionsProjectedWorldCoords,positionsFittedRenderCoords:this.positionsFittedRenderCoords,positionsGeographic:this.positionsGeographic,positionsSpherical:this.positionsSpherical,positionsStereographic:this.positionsStereographic,pathSegmentLengths:this.pathSegmentLengths,geodesicPathSegmentLengths:this.geodesicPathSegmentLengths,perimeterSegmentLengths:this.perimeterSegmentLengths,intersectingSegments:this.intersectingSegments,geodesicIntersectingSegments:this.geodesicIntersectingSegments,triangleIndices:this.triangleIndices,geodesicTriangleIndices:this.geodesicTriangleIndices,areaCentroidWorldCoords:this.areaCentroidWorldCoords,areaCentroidRenderCoords:this.areaCentroidRenderCoords,geodesicAreaCentroidRenderCoords:this.geodesicAreaCentroidRenderCoords,fittingMode:this.fittingMode,area:this.area,geodesicArea:this.geodesicArea,pathLength:this.pathLength,geodesicPathLength:this.geodesicPathLength,perimeterLength:this.perimeterLength,cursorSegmentLength:this.cursorSegmentLength,geodesicCursorSegmentLength:this.geodesicCursorSegmentLength,unitNormalizer:this.unitNormalizer,actualMeasurementMode:this.actualMeasurementMode}}_resize(e){for(e<this._length&&(this.positionsWorldCoords.length=e,this.positionsRenderCoords.length=e,this.positionsProjectedWorldCoords.length=e,this.positionsFittedRenderCoords.length=e,this.positionsGeographic.length=e,this.positionsSpherical.length=e,this.positionsStereographic.length=e,this.pathSegmentLengths.length=e,this.geodesicPathSegmentLengths.length=e,this.perimeterSegmentLengths.length=e,this._length=e);this._length<e;)this.positionsWorldCoords.push(f()),this.positionsRenderCoords.push(f()),this.positionsProjectedWorldCoords.push(h()),this.positionsFittedRenderCoords.push(f()),this.positionsGeographic.push(f()),this.positionsSpherical.push(f()),this.positionsStereographic.push(h()),this.pathSegmentLengths.push(0),this.geodesicPathSegmentLengths.push(0),this.perimeterSegmentLengths.push(0),++this._length}_updatePathLengths(e){const t=this.positionsWorldCoords,s=this.pathSegmentLengths;let i=0;for(let o=0;o<this._length;++o){const r=s[o]=d(t[o],t[(o+1)%this._length]);(o<this._length-1||e)&&(i+=r)}return i}_updateGeodesicPathLengths(e,t){const s=this.positionsGeographic,i=this.geodesicPathSegmentLengths;let o=0;for(let r=0;r<this._length;++r){const n=i[r]=G(s[r],s[(r+1)%this._length],t??void 0);(r<this._length-1||e)&&(o+=n)}return o}_updateArea(e,t,s,n,h){const a=e.renderCoordsHelper,d=this.positionsWorldCoords,f=this.positionsRenderCoords,C=this.positionsProjectedWorldCoords,S=this.positionsFittedRenderCoords,L=this._planeWorldCoords,P=this._centroidRenderCoords;x(f,P),a.worldUpAtPosition(P,this._worldUp),a.worldBasisAtPosition(P,w.X,this._worldTangent),M(P,this._worldUp,s,this._worldUp,n),M(P,this._worldTangent,s,this._worldTangent,n),d.length>2&&V(d,L),this.fittingMode=this._selectFittingMode(L,d,this._worldUp,h);let R=0;if("horizontal"===this.fittingMode){let e=-1/0;f.forEach(((t,s)=>{const i=a.getAltitude(f[s]);i>e&&(e=i,R=s)}))}const j=d[R];let v=L,W=this._worldTangent;"horizontal"===this.fittingMode?v=this._worldUp:"vertical"===this.fittingMode&&(v=this._tempVec3,W=this._worldUp,q(L,this._worldUp,v)),g(this._frame[2],v),q(W,v,this._frame[0]),l(this._frame[1],this._frame[0],this._frame[2]),c(this._frame[1],this._frame[1]);const I=this._tempVec3,z=this._tempU,U=this._tempV;for(let i=0;i<this._length;++i){const e=C[i],t=S[i];p(I,d[i],j),r(e,m(this._frame[0],I),m(this._frame[1],I)),u(z,this._frame[0],e[0]),u(U,this._frame[1],e[1]),_(I,z,U),_(I,I,j),A(I,n,t,s)}this.perimeterLength=this._length>0?i(t.normalizeDistance(this._updatePerimeterLengths()),"meters"):null,x(S,this.areaCentroidRenderCoords),A(this.areaCentroidRenderCoords,s,this.areaCentroidWorldCoords,n),this._updateIntersectingSegments(),this.area=0===this.intersectingSegments.size?o(t.normalizeArea(this._computeArea()),"square-meters"):null}_updateGeodesicArea(e){const{renderCoordsHelper:t,spatialReference:s}=e,{positionsSpherical:i,positionsStereographic:n}=this,h=this._tempVec3,a=y(i,h);if(!a)return void(this.geodesicArea=null);const d=this._tempU,g=this._tempV;D(h,d,g);for(let o=0;o<this._length;++o){const e=m(i[o],d),t=m(i[o],g),s=m(i[o],h);r(n[o],e/s,t/s)}u(h,h,S(s).radius),t.toRenderCoords(h,W(s),this.geodesicAreaCentroidRenderCoords),this._updateGeodesicIntersectingSegments(),this.geodesicArea=a&&0===this.geodesicIntersectingSegments.size?o(this._computeGeodesicArea(),"square-meters"):null}_updatePerimeterLengths(){const e=this.positionsProjectedWorldCoords,t=this.perimeterSegmentLengths;let s=0;for(let i=0;i<this._length;++i){s+=t[i]=n(e[i],e[(i+1)%this._length])}return s}_updateIntersectingSegments(){const e=this.positionsProjectedWorldCoords,t=this.intersectingSegments;t.clear();for(let s=0;s<this._length;++s)for(let i=s+2;i<this._length;++i){if((i+1)%this._length===s)continue;const o=e[s],r=e[(s+1)%this._length],n=e[i],h=e[(i+1)%this._length];I(o,r,n,h)&&(t.add(s),t.add(i))}}_computeArea(){const e=this.positionsProjectedWorldCoords,t=this.triangleIndices=B(H(e));let s=0;for(let i=0;i<t.length;i+=3)s+=z(e[t[i]],e[t[i+1]],e[t[i+2]]);return s}_updateGeodesicIntersectingSegments(){const e=this.positionsStereographic,t=this.geodesicIntersectingSegments;t.clear();for(let s=0;s<this._length;++s)for(let i=s+2;i<this._length;++i){if((i+1)%this._length===s)continue;const o=e[s],r=e[(s+1)%this._length],n=e[i],h=e[(i+1)%this._length];I(o,r,n,h)&&(t.add(s),t.add(i))}}_computeGeodesicArea(){const e=this.positionsGeographic,t=this.positionsStereographic,s=this.geodesicTriangleIndices=B(H(t));let i=0;for(let o=0;o<s.length;o+=3)i+=T(e[s[o]],e[s[o+1]],e[s[o+2]],v.WGS84);return i}_selectFittingMode(t,s,i,o){const r=s.map((e=>Math.abs(F(t,e)))).reduce(((e,t)=>Math.max(e,t)),0);b(s,this._tempSphere);const n=r/(2*this._tempSphere.radius),h=n<o.maxRelativeErrorCoplanar,a=n<o.maxRelativeErrorAlmostCoplanar;let d="horizontal";if(h)d="oblique";else if(a){d=Math.abs(m(i,t))>Math.cos(e(o.verticalAngleThreshold))?"horizontal":"vertical"}return d}_updateCursorSegmentLength(e,s){const o=e.lastPoint;!e.isValidPolygon&&t(o)&&t(s)?(this.geodesicCursorSegmentLength=i(E(o,s),"meters"),this.cursorSegmentLength=i(this.unitNormalizer.normalizeDistance(N(o,s,this.unitNormalizer.spatialReference)),"meters")):(this.geodesicCursorSegmentLength=null,this.cursorSegmentLength=null)}_updateMode(e,s){if(s===U.Auto){this.actualMeasurementMode="euclidean";let s=0;null!=this.geodesicPathLength&&(s+=this.geodesicPathLength.value),!e.isValidPolygon&&t(this.geodesicCursorSegmentLength)&&(s+=this.geodesicCursorSegmentLength.value),s>J&&(this.actualMeasurementMode="geodesic")}else this.actualMeasurementMode=s===U.Euclidean?"euclidean":"geodesic";null==this.geodesicPathLength&&(this.actualMeasurementMode="euclidean"),this._mode=s}}function Z(e,t){t.hasZ||(t.z=s(k(e,t,"ground"),0))}const J=1e5;export{X as MeasurementDataManager};