@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 8.37 kB
JavaScript
import{_ as e}from"../../../chunks/tslib.es6.js";import t from"../../../core/Evented.js";import{HandleOwner as n}from"../../../core/HandleOwner.js";import{isNone as i,isSome as s}from"../../../core/maybe.js";import{isAborted as r}from"../../../core/promiseUtils.js";import{watch as a,sync as o,syncAndInitial as p}from"../../../core/reactiveUtils.js";import{property as c}from"../../../core/accessorSupport/decorators/property.js";import"../../../core/accessorSupport/ensureType.js";import"../../../core/arrayUtils.js";import{subclass as d}from"../../../core/accessorSupport/decorators/subclass.js";import{project as h,initializeProjection as l}from"../../../geometry/projection.js";import{absoluteHeightElevationInfo as u}from"../../../support/elevationInfoUtils.js";import{defaults as f}from"./Settings.js";import{SnappingDomain as _}from"./SnappingDomain.js";import{defaultSnappingEnginesFactory as g}from"./snappingFactory.js";import m from"./SnappingOptions.js";import{pointToSnappingPoint as S,snappingPointToSnappingOutput as v}from"./SnappingPoint.js";import{sortCandidatesInPlace as y,squaredScreenDistance as C}from"./snappingUtils.js";import{IntersectionSnappingCandidate as P}from"./candidates/IntersectionSnappingCandidate.js";import{vectorToScreenPoint as T}from"../support/viewUtils.js";let w=class extends(t.EventedMixin(n)){constructor(e){super(e),this.options=new m,this.snappingEnginesFactory=g,this._engines=[],this._currentMainCandidate=null,this._currentOtherActiveCandidates=[],this._currentSnappedType=E.MAIN}initialize(){this.handles.add([a((()=>{const{effectiveFeatureEnabled:e,effectiveSelfEnabled:t,touchSensitivityMultiplier:n,distance:i}=this.options;return{effectiveFeatureEnabled:e,effectiveSelfEnabled:t,touchSensitivityMultiplier:n,distance:i}}),(()=>{this.doneSnapping(),this.emit("changed")}),o),a((()=>this.options),(e=>{for(const t of this._engines)t.options=e}),o),a((()=>({viewReady:this.view.ready,viewSpatialReference:this.view.spatialReference,snappingEnginesFactory:this.snappingEnginesFactory})),(({viewReady:e,snappingEnginesFactory:t})=>this._recreateEngines(e,t)),p)])}destroy(){this._destroyEngines()}get updating(){return this._engines.some((e=>e.updating))}_recreateEngines(e,t){if(this._destroyEngines(),!e)return;const{view:n,options:i}=this;this._engines=t(n,i)}_destroyEngines(){for(const e of this._engines)e.destroy();this._engines=[]}get _squaredMouseProximityTreshold(){return this.options.distance*this.options.distance}get _squaredTouchProximityThreshold(){const{distance:e,touchSensitivityMultiplier:t}=this.options,n=e*t;return n*n}get _squaredSatisfiesConstraintThreshold(){return f.satisfiesConstraintScreenThreshold*f.satisfiesConstraintScreenThreshold}async snap(e){return M(e)?this._snapMultiPoint(e):this._snapSinglePoint(e)}update(e){const{point:t,context:n}=e;this._removeVisualization();const r=this._currentMainCandidate;if(i(r))return t;const a=this._selectUpdateInput(e);if(i(a))return t;const{spatialReference:o}=n,p=h(a,o);if(i(p))return t;const{view:c}=this,{elevationInfo:d,visualizer:l}=n,u=[],f=S(p,c,n),_=r.constraint.closestTo(f);if(!this._arePointsWithinScreenThreshold(f,_,n))return this._resetSnappingState(),t;r.targetPoint=_,u.push(...r.hints);for(const i of this._currentOtherActiveCandidates)i.targetPoint=_,u.push(...i.hints);return s(l)&&this.handles.add(l.draw(u,{spatialReference:o,elevationInfo:R(n),view:c,selfSnappingZ:n.selfSnappingZ}),I),v(_,c,{z:t.z,m:t.m,spatialReference:t.spatialReference,elevationInfo:d})}doneSnapping(){this._removeVisualization(),this._resetSnappingState()}_selectUpdateInput({point:e,scenePoint:t}){switch(this._currentSnappedType){case E.MAIN:return e;case E.SCENE:return t}}_resetSnappingState(){this._currentMainCandidate=null,this._currentOtherActiveCandidates=[],this._currentSnappedType=E.MAIN}_removeVisualization(){this.handles.remove(I)}async _snapSinglePoint({point:e,context:t,signal:n}){const{view:i}=this,s=S(e,i,t),r=await this._fetchCandidates(s,_.ALL,t,n);return this._createSnapResult(s,E.MAIN,r,i,t,{z:e.z,m:e.m,spatialReference:e.spatialReference,elevationInfo:t.elevationInfo},n)}async _snapMultiPoint({point:e,scenePoint:t,context:n,signal:i}){const{view:s}=this,{coordinateHelper:r,spatialReference:a}=n;await l(t.spatialReference,a);const o=h(t,a),p=S(o,s,n),c=await this._fetchCandidates(p,_.FEATURE,n,i);if(c.length>0){const e=await this._fetchCandidates(p,_.SELF,n,i);return this._createSnapResult(p,E.SCENE,[...c,...e],s,n,{z:o.z,m:o.m,spatialReference:o.spatialReference,elevationInfo:n.elevationInfo},i)}const d=S(e,s,n),u=await this._fetchCandidates(d,_.SELF,n,i);return this._createSnapResult(d,E.MAIN,u,s,n,{z:r.hasZ()&&e.hasZ?e.z??0:void 0,m:r.hasM()&&e.hasM?e.m??0:void 0,spatialReference:e.spatialReference,elevationInfo:n.elevationInfo},i)}async _fetchCandidates(e,t,n,i){return(await Promise.all(this._engines.map((s=>s.fetchCandidates(e,t,n,i))))).flat()}_createSnapResult(e,t,n,i,a,o,p){return{get valid(){return!r(p)},apply:()=>{const{spatialReference:r}=a,{snappedPoint:p,hints:c}=this._processCandidates(e,t,n,a);return this._removeVisualization(),s(a.visualizer)&&this.handles.add(a.visualizer.draw(c,{spatialReference:r,elevationInfo:u,view:i,selfSnappingZ:a.selfSnappingZ}),I),v(p,i,o)}}}_processCandidates(e,t,n,i){if(n.length<1)return this.doneSnapping(),{snappedPoint:e,hints:[]};this._currentSnappedType!==t&&this._resetSnappingState(),y(e,n);const r=this._currentMainCandidate;if(s(r)){const s=this._findOldConstraintInNewCandidates(r,n);if(s>=0){if(!(n[s]instanceof P))return this._intersectWithOtherCandidates(s,n,e,t,i);if(this._arePointsWithinScreenThreshold(e,r.targetPoint,i))return this._updateSnappingCandidate(r,t,n,i)}}return this._intersectWithOtherCandidates(0,n,e,t,i)}_findOldConstraintInNewCandidates(e,t){return e instanceof P?this._findOldCandidateIndex(t,e.first)>=0&&this._findOldCandidateIndex(t,e.second)>=0?0:-1:this._findOldCandidateIndex(t,e)}_intersectWithOtherCandidates(e,t,n,i,s){const{coordinateHelper:r}=s,a=t[e],o=[];for(let p=0;p<t.length;++p){if(p===e)continue;const i=t[p];for(const e of a.constraint.intersect(i.constraint)){const t=e.closestTo(a.targetPoint);o.push([new P(t,a,i,i.isDraped),this._squaredScreenDistance(n,t,r)])}}return o.length>0&&(o.sort(((e,t)=>e[1]-t[1])),o[0][1]<this._squaredPointProximityThreshold(s.pointer))?this._updateSnappingCandidate(o[0][0],i,t,s):this._updateSnappingCandidate(a,i,t,s)}_updateSnappingCandidate(e,t,n,i){this.doneSnapping(),this._currentMainCandidate=e,this._currentSnappedType=t;const s=this._currentMainCandidate.targetPoint,r=[];r.push(...e.hints);for(const a of n){if(e instanceof P){if(a.constraint.equals(e.first.constraint)||a.constraint.equals(e.second.constraint))continue}else if(a.constraint.equals(e.constraint))continue;const t=a.constraint.closestTo(s);this._squaredScreenDistance(t,s,i.coordinateHelper)<this._squaredSatisfiesConstraintThreshold&&(a.targetPoint=s,this._currentOtherActiveCandidates.push(a),r.push(...a.hints))}return{snappedPoint:s,hints:r}}_squaredPointProximityThreshold(e){return"touch"===e?this._squaredTouchProximityThreshold:this._squaredMouseProximityTreshold}_arePointsWithinScreenThreshold(e,t,n){return this._squaredScreenDistance(e,t,n.coordinateHelper)<this._squaredPointProximityThreshold(n.pointer)}_squaredScreenDistance(e,t,n){return C(this._toScreen(e,n),this._toScreen(t,n))}_toScreen(e,t){return T(e,t.spatialReference,u,this.view)}_findOldCandidateIndex(e,t){let n=-1;for(let i=0;i<e.length;++i)if(t.constraint.equals(e[i].constraint)){n=i;break}return n}get test(){return{visualizationsActive:this.handles.has(I),engines:this._engines}}};var E;e([c({constructOnly:!0})],w.prototype,"view",void 0),e([c()],w.prototype,"options",void 0),e([c({readOnly:!0})],w.prototype,"updating",null),e([c()],w.prototype,"snappingEnginesFactory",void 0),e([c()],w.prototype,"_engines",void 0),e([c()],w.prototype,"_squaredMouseProximityTreshold",null),e([c()],w.prototype,"_squaredTouchProximityThreshold",null),e([c()],w.prototype,"_squaredSatisfiesConstraintThreshold",null),w=e([d("esri.views.interactive.snapping.SnappingManager")],w),function(e){e[e.MAIN=0]="MAIN",e[e.SCENE=1]="SCENE"}(E||(E={}));const I="visualization-handle";function M(e){return s(e.scenePoint)}function R({coordinateHelper:e,elevationInfo:t}){return e.hasZ()?u:t}export{w as SnappingManager};