UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

6 lines (5 loc) 8.88 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.33/esri/copyright.txt for details. */ import{_ as e}from"../../../chunks/tslib.es6.js";import t from"../../../core/Accessor.js";import{isSome as r}from"../../../core/arrayUtils.js";import{destroyHandle as a}from"../../../core/handleUtils.js";import"../../../core/has.js";import{mapCollectionAsync as n}from"../../../core/mapCollectionUtils.js";import{allSettledValues as s,throwIfAborted as o}from"../../../core/promiseUtils.js";import{watch as i,sync as c}from"../../../core/reactiveUtils.js";import{getMetersPerUnitForSR as u,getMetersPerVerticalUnitForSR as l}from"../../../core/unitUtils.js";import{property as p}from"../../../core/accessorSupport/decorators/property.js";import"../../../core/Logger.js";import{subclass as d}from"../../../core/accessorSupport/decorators/subclass.js";import{squaredDistance as m}from"../../../core/libs/gl-matrix-2/math/vec2.js";import{c as g,s as h}from"../../../chunks/vec32.js";import{create as S}from"../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{getEpsilon as f}from"../../../core/libs/gl-matrix-2/math/common.js";import{UpdatingHandles as y}from"../../../core/support/UpdatingHandles.js";import{absoluteHeightElevationInfo as _}from"../../../support/elevationInfoUtils.js";import{VerticalHalfPlaneConstraint as v}from"../sketch/constraints.js";import{fromAnyMapPoint as w,asVec2 as j,markAsTarget as F}from"../sketch/normalizedPoint.js";import{FeatureSnappingSourceInfo as b}from"./FeatureSnappingSourceInfo.js";import{SnappingDomain as x}from"./SnappingDomain.js";import{sortCandidatesInPlace as C,screenDistance as R}from"./snappingUtils.js";import{DrapedEdgeSnappingCandidate as E}from"./candidates/DrapedEdgeSnappingCandidate.js";import{EdgeSnappingCandidate as M}from"./candidates/EdgeSnappingCandidate.js";import{FeatureSnappingCandidate as L}from"./candidates/FeatureSnappingCandidate.js";import{RightAngleSnappingCandidate as I,OtherVertexType as G}from"./candidates/RightAngleSnappingCandidate.js";import{vectorToScreenPoint as H}from"../support/viewUtils.js";let P=class extends t{get updating(){return this._snappingSources.some((e=>null==e?.valid||!0===e.valid&&!0===e.snappingSource?.updating))||this._updatingHandles.updating}constructor(e){super(e),this.options=null,this._domain=x.FEATURE,this._updatingHandles=new y,this._sourceModules={featureService:{module:null,loader:null},featureCollection:{module:null,loader:null},graphics:{module:null,loader:null},notes:{module:null,loader:null},scene:{module:null,loader:null}}}initialize(){const e=n((()=>this.options?._effectiveFeatureSources),((e,t)=>this._createSourceInfo(e,t)));this._snappingSources=e,this.addHandles([a(e),i((()=>({rulesEnabled:!!this.options?.attributeRulesEnabled,sources:this._snappingSources.filter(r)})),(({rulesEnabled:e,sources:t})=>{for(const r of t)r.attributeRulesEnabled=e}),c)])}destroy(){this._set("options",null),this._updatingHandles.destroy()}async fetchCandidates(e,t,r,a){if(!(t&this._domain&&null!=this.options&&this.options.effectiveFeatureEnabled))return[];const n=[],i=this._computeScreenSizeDistanceParameters(e,r);for(const s of this._snappingSources){if(!s?.valid||!s.snappingSource?.layerSource?.enabled||s.layerView?.suspended)continue;const t=s.getFetchCandidatesParameters(e,r,i);for(const e of t)n.push(s.snappingSource.fetchCandidates(e,a).then((e=>e.filter((e=>!this._candidateIsExcluded(s.snappingSource,e,r.excludeFeature))))))}const c=(await s(n)).flat();return this._addRightAngleCandidates(c,e,i,r),o(a),C(e,c),c}_addRightAngleCandidates(e,t,r,a){const n=null!=a.vertexHandle?a.vertexHandle.rightEdge?.rightVertex?.pos:null!=a.editGeometryOperations&&"polygon"===a.editGeometryOperations.data.type?a.editGeometryOperations.data.components[0]?.getFirstVertex()?.pos:null,s=null!=a.vertexHandle?a.vertexHandle.leftEdge?.leftVertex?.pos:null!=a.editGeometryOperations?a.editGeometryOperations.data.components[0]?.getLastVertex()?.pos:null,{view:o}=this,i=w(n,o,a),c=w(s,o,a),u=e.length;for(let l=0;l<u;l++)this._addRightAngleCandidate(e[l],c,t,r,e),this._addRightAngleCandidate(e[l],i,t,r,e)}_addRightAngleCandidate(e,t,r,a,n){if(null==t||!U(e))return;const s=e.constraint.closestTo(t),o=(s[0]-r[0])/a.x,i=(s[1]-r[1])/a.y,{start:c,end:u}=e.constraint;if(o*o+i*i<=1){const r=m(j(s),j(c))>m(j(s),j(u))?c:u,a=new I({targetPoint:F(s),otherVertex:t,otherVertexType:G.NEXT,previousVertex:r,constraint:new v(t,s),objectId:e.objectId,isDraped:e.isDraped,domain:x.FEATURE});n.push(a)}}_computeScreenSizeDistanceParameters(e,t){let r=null!=this.options?this.options.distance*("touch"===t.pointer?this.options.touchSensitivityMultiplier:1):0;return null==this.view?{x:r,y:r,z:r,distance:r}:"2d"===this.view.type?(r*=this.view.resolution,{x:r,y:r,z:r,distance:r}):this._computeScreenSizeDistanceParameters3D(e,r,this.view,t)}_computeScreenSizeDistanceParameters3D(e,t,r,a){const{spatialReference:n}=a;r.renderCoordsHelper.toRenderCoords(e,n,D);const s=r.state.camera.computeScreenPixelSizeAt(D),o=s*r.renderCoordsHelper.unitInMeters,i=o/u(n),c=o/l(n),p=t*i,d=t*c,m=H(e,n,_,r),g=m?z(m,e,i,0,0,r,a):0,h=m?z(m,e,0,i,0,r,a):0,S=m?z(m,e,0,0,c,r,a):0;return{x:0===g?0:p/g,y:0===h?0:p/h,z:0===S?0:d/S,distance:s*t}}_candidateIsExcluded(e,t,r){if(null==r)return!1;const a=this._getCandidateObjectId(t);if(null==a)return!1;const n=e.layerSource.layer;return"graphics"===n.type?r.uid===a:r.sourceLayer===n&&(!(!r.attributes||!("objectIdField"in n))&&r.attributes[n.objectIdField]===a)}_getCandidateObjectId(e){return e instanceof L?e.objectId:null}async _createSourceInfo(e,t){const r=e.layer;r.loaded||(await r.load(),o(t));const{view:a}=this,n=await this._createFeatureSnappingSourceType(e);return o(t),new b(null==n?{}:{snappingSource:n,view:a,layer:r})}async _createFeatureSnappingSourceType(e){switch(e.layer.type){case"feature":case"geojson":case"csv":case"oriented-imagery":case"subtype-group":case"wfs":return this._createFeatureSnappingSourceFeatureLayer(e);case"graphics":return this._createFeatureSnappingSourceGraphicsLayer(e);case"map-notes":return this._createFeatureSnappingSourceMapNotesLayer(e);case"scene":case"building-scene":return this._createFeatureSnappingSourceSceneLayer(e)}return null}async _createFeatureSnappingSourceSceneLayer(e){const{view:t}=this;if(null==t||"3d"!==t.type)return null;return new((await this._getSourceModule("scene")).SceneLayerSnappingSource)({layerSource:e,view:t})}async _createFeatureSnappingSourceFeatureLayer(e){switch(e.layer.source?.type){case"feature-layer":case"oriented-imagery":return new((await this._getSourceModule("featureService")).FeatureServiceSnappingSource)({spatialReference:this.spatialReference,view:this.view,layerSource:e});case"memory":case"csv":case"geojson":case"wfs":if("mesh"===e.layer.geometryType)return null;return new((await this._getSourceModule("featureCollection")).FeatureCollectionSnappingSource)({layerSource:e,view:this.view})}return null}async _createFeatureSnappingSourceGraphicsLayer(e){return new((await this._getSourceModule("graphics")).GraphicsSnappingSource)({getGraphicsLayers:()=>[e.layer],spatialReference:this.spatialReference,view:this.view,layerSource:e})}async _createFeatureSnappingSourceMapNotesLayer(e){return new((await this._getSourceModule("notes")).GraphicsSnappingSource)({getGraphicsLayers:()=>e.layer.sublayers?.toArray()??[],spatialReference:this.spatialReference,view:this.view,layerSource:e})}async _getSourceModule(e){const t=this._sourceModules[e];if(null==t.loader){const t=this._loadSourceModule(e),r={module:null,loader:t};this._sourceModules[e]=r;const a=await t,n={module:a,loader:t};return this._sourceModules[e]=n,a}return null==t.module?t.loader:t.module}_loadSourceModule(e){const t=this._updatingHandles;switch(e){case"featureService":return t.addPromise(import("./featureSources/FeatureServiceSnappingSource.js"));case"featureCollection":return t.addPromise(import("./featureSources/FeatureCollectionSnappingSource.js"));case"graphics":case"notes":return t.addPromise(import("./featureSources/GraphicsSnappingSource.js"));case"scene":return t.addPromise(import("./featureSources/SceneLayerSnappingSource.js"))}}get test(){}};function U(e){return(e instanceof M||e instanceof E)&&!A(e)}function A({constraint:{start:e,end:t}}){const r=h(e,t),a=m(j(e),j(t));return r<f()||a/r<T}function z(e,t,r,a,n,s,{spatialReference:o}){const i=g(O,t);i[0]+=r,i[1]+=a,i[2]+=n;const c=H(i,o,_,s);return c?R(c,e):1/0}e([p({constructOnly:!0})],P.prototype,"spatialReference",void 0),e([p({constructOnly:!0})],P.prototype,"view",void 0),e([p()],P.prototype,"options",void 0),e([p({readOnly:!0})],P.prototype,"updating",null),e([p()],P.prototype,"_snappingSources",void 0),P=e([d("esri.views.interactive.snapping.FeatureSnappingEngine")],P);const D=S(),O=S(),T=1e-4;export{P as FeatureSnappingEngine};