@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 7.05 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import t from"../../../core/Error.js";import e from"../../../core/Logger.js";import{GeometryCursor as s}from"../../../geometry/GeometryCursor.js";import o from"../../../geometry/SpatialReference.js";import{closeRingsAndFixWinding as i}from"../../../geometry/support/coordsUtils.js";import{isPolygon as n,isPolyline as r}from"../../../geometry/support/jsonUtils.js";import l from"../../../geometry/support/PolylineBuilder.js";import{Point as a}from"../../../geometry/support/TileClipper.js";import{PathEffectCursor as h}from"../CIMCursor.js";import{SegmentCursor as c}from"../../../views/2d/engine/webgl/mesh/templates/segmentUtils.js";const y=()=>e.getLogger("esri.symbols.cim.effects.EffectTaperedPolygon");class x{static{this.instance=null}static local(){return null===x.instance&&(x.instance=new x),x.instance}execute(t,e,s,o,i){return new p(t,e,s,o,i)}}class p extends h{constructor(t,e,s,o,i){super(t,!1,!0),this._slopeS=0,this._slopeC=1,this._lastTangent1=new a(NaN,NaN),this._lastWidth=0,this._tileKey=null,this._halfFromWidth=Math.abs(void 0!==e.fromWidth?e.fromWidth:0)*s*.5,this._halfToWidth=Math.abs(void 0!==e.toWidth?e.toWidth:1)*s*.5,this._originalLength=(void 0!==e.length?e.length:0)*s,this._length=0,this._tileKey=o,this._geometryEngine=i}processPath(e){if(e.totalSize<=0)return null;if(this._halfFromWidth<=0&&this._halfToWidth<=0){const t=s.createEmptyOptimizedCIM("esriGeometryPolygon",!1,!1,e.yFactor);for(e.seekPathEnd();e.prevPoint();)t.pushXY(e.x,e.y);for(e.seekPathStart();e.nextPoint();)t.pushXY(e.x,e.y);return t}const a=[];e.seekPathStart();let h=0,x=0;for(;e.nextPoint();)a.push([e.x-h,e.y-x]),h=e.x,x=e.y;let p=this._geometryEngine?.simplify(o.WebMercator,{paths:[a]});p||null!=this._tileKey||(p={paths:[a]});const _=n(p)?p.rings:r(p)?p.paths:null;if(!_)return y().error(new t("mapview-bad-resource","Unable to process geometry")),null;const f=new l,d=new l;let m=0;for(const t of _){h=t[0][0],x=t[0][1];for(let e=1;e<t.length;e++){const s=h+t[e][0],o=x+t[e][1];m+=Math.sqrt((s-h)*(s-h)+(o-x)*(o-x)),h=s,x=o}}if(0===this._originalLength||this._originalLength>m){this._length=m;const t=(this._halfToWidth-this._halfFromWidth)/this._length;if(Math.abs(t)<1){const e=t*t;this._slopeC=Math.sqrt(1/(1+e)),this._slopeS=Math.sqrt(e/(1+e)),t<0&&(this._slopeS=-this._slopeS)}else this._slopeC=this._slopeS=.7071}else this._length=this._originalLength,this._slopeC=1,this._slopeS=0;let g=0;const u=[];for(const t of _){const e=c.create(t),s=c.create(t);this._setFromOffset(s,f,d);let o=s.next(),i=e;for(;o&&i;)g=this._setOffset(i,o,g,f,d),i=e.next(),o=s.next();i=e,i&&this._setToOffset(i,g,f,d);const n=f.getGeometry(),r=d.getGeometry(),l=[];for(const t of n)l.push(...t);for(let t=r.length-1;t>=0;t--){const e=r[t];for(let t=e.length-1;t>=0;t--)l.push(e[t])}u.push(l)}const S={rings:u};i(S);let T=this._geometryEngine?.simplify(o.WebMercator,S);if(!T){if(null!=this._tileKey)return null;T=S}return s.fromJSONCIM(T)}_setFromOffset(t,e,s){const o=this._halfFromWidth,i=new a(t.xEnd-t.xStart,t.yEnd-t.yStart);i.normalize(),i.scale(o),e.beginPath([t.xStart-i.y,t.yStart+i.x]),s.beginPath([t.xStart+i.y,t.yStart-i.x])}_setToOffset(t,e,s,o){let i;i=(e+=Math.sqrt((t.xEnd-t.xStart)*(t.xEnd-t.xStart)+(t.yEnd-t.yStart)*(t.yEnd-t.yStart)))>=this._length?this._halfToWidth:this._halfFromWidth+(this._halfToWidth-this._halfFromWidth)*e/this._length;const n=new a(t.xEnd-t.xStart,t.yEnd-t.yStart);n.normalize(),n.scale(i),s.lineTo([t.xEnd-n.y,t.yEnd+n.x]),o.lineTo([t.xEnd+n.y,t.yEnd-n.x])}_setOffset(e,s,o,i,n){const r=Math.sqrt((e.xEnd-e.xStart)*(e.xEnd-e.xStart)+(e.yEnd-e.yStart)*(e.yEnd-e.yStart));let l;l=o+r>=this._length?this._halfToWidth:this._halfFromWidth+(this._halfToWidth-this._halfFromWidth)*(o+r)/this._length,o+=r;const h=new a(e.xEnd,e.yEnd),c=new a(e.xEnd-e.xStart,e.yEnd-e.yStart);c.normalize();const x=new a(s.xEnd-s.xStart,s.yEnd-s.yStart);x.normalize();const p=c.x*x.y-c.y*x.x;let _;_=0===Math.abs(p)?new a(x.x,x.y):new a((x.x-c.x)/p,(x.y-c.y)/p);const f=i.getPointCount(),d=n.getPointCount();c.leftPerpendicular(),x.leftPerpendicular();const m=c.x*x.x+c.y*x.y;if(m>.99){const t=new a((c.x+x.x)*l/2,(c.y+x.y)*l/2),e=t.clone();e.rotate(this._slopeC,this._slopeS),i.lineTo([h.x+e.x,h.y+e.y]);const s=t.clone();s.rotateReverse(this._slopeC,this._slopeS),n.lineTo([h.x-s.x,h.y-s.y])}else{if(p<0){const e=_.clone().scale(-l);e.rotateReverse(this._slopeC,this._slopeS);const s=n.getXY(d-1);s||y().error(new t("mapview-bad-resource","Unable to process geometry, index out of scope"));const o=a.add(h,e),i=a.sub(o,a.fromArray(s));if(c.x*i.y-c.y*i.x>0){const t=new a(-c.x*l,-c.y*l);t.rotateReverse(this._slopeC,this._slopeS);const e=new a(-x.x*l,-x.y*l);e.rotateReverse(this._slopeC,this._slopeS),n.lineTo([h.x+t.x,h.y+t.y]),n.lineTo([h.x,h.y]),n.lineTo([h.x+e.x,h.y+e.y])}else n.lineTo([h.x+e.x,h.y+e.y])}else{const e=_.clone().scale(l);e.rotate(this._slopeC,this._slopeS);const s=i.getXY(f-1);s||y().error(new t("mapview-bad-resource","Unable to process geometry, index out of scope"));const o=a.add(h,e),n=a.sub(o,a.fromArray(s));if(c.x*n.y-c.y*n.x>0){const t=c.clone().scale(l);t.rotate(this._slopeC,this._slopeS);const e=x.clone().scale(l);e.rotate(this._slopeC,this._slopeS),i.lineTo([h.x+t.x,h.y+t.y]),i.lineTo([h.x,h.y]),i.lineTo([h.x+e.x,h.y+e.y])}else i.lineTo([h.x+e.x,h.y+e.y])}const s=Math.acos(m);let o=1;if(l>.25){const t=2*Math.acos(1-.25/l);t<s&&(o=Math.round(s/t))}const r=Math.cos(s/o),g=Math.sin(s/o),u=c.clone();if(p<0){u.rotate(this._slopeC,this._slopeS);const s=i.getXY(f-1);s||y().error(new t("mapview-bad-resource","Unable to process geometry, index out of scope"));const o=a.add(h,u.clone().scale(this._lastWidth)),n=a.sub(o,a.fromArray(s)),r=c.x*n.y-c.y*n.x;if(!isNaN(this._lastTangent1.x)&&!isNaN(this._lastTangent1.y)&&r>0){const t=new a(e.xStart,e.yStart),s=this._lastTangent1.clone().scale(this._lastWidth);s.rotate(this._slopeC,this._slopeS);const o=c.clone().scale(this._lastWidth);o.rotate(this._slopeC,this._slopeS),i.lineTo([t.x+s.x,t.y+s.y]),i.lineTo([t.x,t.y]),i.lineTo([t.x+o.x,t.y+o.y])}}else{u.scale(-1).rotateReverse(this._slopeC,this._slopeS);const s=n.getXY(d-1);s||y().error(new t("mapview-bad-resource","Unable to process geometry, index out of scope"));const o=a.add(h,u.clone().scale(this._lastWidth)),i=a.sub(o,a.fromArray(s)),r=c.x*i.y-c.y*i.x;if(!isNaN(this._lastTangent1.x)&&!isNaN(this._lastTangent1.y)&&r>0){const t=new a(e.xStart,e.yStart),s=this._lastTangent1.clone().scale(-this._lastWidth);s.rotateReverse(this._slopeC,this._slopeS);const o=c.clone().scale(-this._lastWidth);o.rotateReverse(this._slopeC,this._slopeS),n.lineTo([t.x+s.x,t.y+s.y]),n.lineTo([t.x,t.y]),n.lineTo([t.x+o.x,t.y+o.y])}}u.scale(l);for(let t=0;t<=o;t++)p<0?(i.lineTo([h.x+u.x,h.y+u.y]),u.rotateReverse(r,g)):(n.lineTo([h.x+u.x,h.y+u.y]),u.rotate(r,g))}return this._lastTangent1.setCoords(c.x,c.y),this._lastWidth=l,o}}export{x as EffectTaperedPolygon};