UNPKG

@arcgis/core

Version:

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

6 lines (5 loc) • 11.3 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.33/esri/copyright.txt for details. */ import e from"../../../../Color.js";import"../../../../core/has.js";import t from"../../../../core/Error.js";import{translate as r}from"../../../../core/libs/gl-matrix-2/math/mat4.js";import{IDENTITY as i,create as s}from"../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{set as a,scale as o}from"../../../../core/libs/gl-matrix-2/math/vec2.js";import{fromValues as n,fromArray as l,clone as c}from"../../../../core/libs/gl-matrix-2/factories/vec2f64.js";import{i as h}from"../../../../chunks/vec32.js";import{fromArray as p,create as m}from"../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{ZEROS as f}from"../../../../core/libs/gl-matrix-2/factories/vec4f64.js";import{projectBuffer as d}from"../../../../geometry/projection/projectBuffer.js";import{create as u,fromSubBuffer as g,intersectsClippingArea as b}from"../../../../geometry/support/aaBoundingBox.js";import{newDoubleArray as y,doubleArrayFrom as _}from"../../../../geometry/support/DoubleArray.js";import{newFloatArray as v}from"../../../../geometry/support/FloatArray.js";import{EmissiveSourceMode as w}from"../../../../symbols/support/materialUtils.js";import{needsElevationUpdates3D as x,evaluateElevationAlignmentAtPoint as j,SampleElevationInfo as P}from"./elevationAlignmentUtils.js";import{Graphics3DObject3DGraphicLayer as S}from"./Graphics3DObject3DGraphicLayer.js";import{pathNumRoundJoinSubdivisions as C,pathNumRoundCapExtrusionSubdivisions as D}from"./Graphics3DPathSymbolLayerConstants.js";import{Graphics3DSymbolLayer as V}from"./Graphics3DSymbolLayer.js";import{isValidSize as A}from"./graphicUtils.js";import{ApplyRendererDiffResult as U}from"./interfaces.js";import{ConvertOptions as R,initFastSymbolUpdatesState as k,updateFastSymbolUpdatesState as z,getAttributeValue as E}from"../support/FastSymbolUpdates.js";import{SamplePosition as L}from"../../support/ElevationProvider.js";import{NormalType as O}from"../../webgl-engine/core/shaderLibrary/attributes/NormalAttribute.glsl.js";import{CullFaceOptions as I}from"../../webgl-engine/lib/basicInterfaces.js";import{Object3D as G}from"../../webgl-engine/lib/Object3D.js";import{Path as B}from"../../webgl-engine/lib/Path.js";import{PathBuilder as F}from"../../webgl-engine/lib/PathBuilder.js";import{RoundCapBuilder as M,TriangulationCapBuilder as q,NoCapBuilder as H}from"../../webgl-engine/lib/PathCapBuilder.js";import{SimpleExtruder as N,MiterExtruder as W}from"../../webgl-engine/lib/PathExtruder.js";import{UpVectorAlignment as T,PathGeometry as Z,isPathGeometry as J}from"../../webgl-engine/lib/PathGeometry.js";import{FastUpdatePathGeometry as K,StaticPathGeometry as Q}from"../../webgl-engine/lib/PathGeometryData.js";import{computeMinimumRotationTangentFrame as X}from"../../webgl-engine/lib/pathGeometryUtils.js";import{quadProfiles as Y,circleProfiles as $}from"../../webgl-engine/lib/PathProfile.js";import{newPathVertex as ee}from"../../webgl-engine/lib/PathVertex.js";import{VertexAttribute as te}from"../../webgl-engine/lib/VertexAttribute.js";import{DefaultMaterial as re}from"../../webgl-engine/materials/DefaultMaterial.js";import{PathMaterial as ie}from"../../webgl-engine/materials/PathMaterial.js";const se=["polyline"];class ae extends V{constructor(e,t,r,i){super(e,t,r,i,he(t)),this._intrinsicSize=n(1,1),this._upVectorAlignment=T.Path,this._stencilWidth=.1,this.ensureDrapedStatus(!1)}async doLoad(){const e=this.symbolLayer,r=null!=e.width?e.width:e.height,i=null!=e.height?e.height:r;this._vvConvertOptions=new R({supports:{size:!0,color:!0,rotation:!1,opacity:!0},modelSize:[1,1,1],symbolSize:[r,1,i],unitInMeters:this._context.renderCoordsHelper.unitInMeters,fallbackColor:this._getFallbackOpacityAndColor(),fallbackSize:[r,1,i]});const s=this._context.renderer?.visualVariables;this._fastUpdates=s?.length?k(this._context.renderer,this._vvConvertOptions):null;const n=e.anchor||"center";this._upVectorAlignment="heading"===e.profileRotation?T.World:T.Path;const c=e.profile||"circle";switch(c){default:case"circle":this._profile=$[n];break;case"quad":this._profile=Y[n]}switch(e.join){case"round":this._extruder=new W(0,C);break;case"bevel":this._extruder=new W(0,1);break;case"miter":this._extruder=new W(.8*Math.PI,1);break;default:this._extruder=new N}const h=e.cap||"butt";switch(h){case"none":this._startCap=new H,this._endCap=new H;break;case"butt":default:this._startCap=new q(this._profile,0),this._endCap=new q(this._profile,0,!0);break;case"square":this._startCap=new q(this._profile,-.5),this._endCap=new q(this._profile,.5,!0);break;case"round":{const e="quad"===c;this._startCap=new M({profile:this._profile,flip:!1,breakNormals:e,subdivisions:D}),this._endCap=new M({profile:this._profile,flip:!0,breakNormals:e,subdivisions:D});break}}const m=this.symbolLayer?.material?.color,f=this._getCombinedOpacityAndColor(m),d=p(f),u=f[3],g=this.needsDrivenTransparentPass,b=e.material?.emissive,y={diffuse:d,ambient:d,emissiveStrength:b?.strength??0,emissiveSource:w.Color,opacity:u,drivenOpacity:g,hasVertexColors:!1,hasSlicePlane:this._context.slicePlaneEnabled,castShadows:this.symbolLayer.castShadows,offsetTransparentBackfaces:!0};if(!this._drivenProperties.size&&(a(this._intrinsicSize,r,i),!A(this._intrinsicSize[0])||!A(this._intrinsicSize[1])))throw new t("graphics3dpathsymbollayer:invalid-size","Symbol sizes may not be negative values");let _;this._fastUpdates?.visualVariables.size||o(this._intrinsicSize,this._intrinsicSize,1/this._context.renderCoordsHelper.unitInMeters),this._fastUpdates?_=new ie({...y,...this._fastUpdates.materialParameters,size:l(this._intrinsicSize)},this._context):(y.hasVertexColors=this._drivenProperties.color||this._drivenProperties.opacity,y.normalType=O.Compressed,_=new re(y,this._context)),_.setParameters({usePBR:this._context.physicalBasedRenderingEnabled,isSchematic:!0,cullFace:_.transparent||"none"===h?I.None:I.Back}),this._materials[0]=_}createGraphics3DGraphic(e){const t=e.graphic;if(!this._validateGeometry(t.geometry,se,this.symbolLayer.type))return null;const r=this.setGraphicElevationContext(t);return this._createAs3DShape(e,r)}layerOpacityChanged(){const e=this.symbolLayer?.material?.color,t=this._getCombinedOpacity(e);this._materials[0]?.setParameters({opacity:t})}layerElevationInfoChanged(e,t){return this.updateGraphics3DGraphicElevationInfo(e,t,x)}slicePlaneEnabledChanged(){return this._materials[0]?.setParameters({hasSlicePlane:this._context.slicePlaneEnabled}),!0}physicalBasedRenderingChanged(){return this._materials[0]?.setParameters({usePBR:this._context.physicalBasedRenderingEnabled,isSchematic:!0}),!0}applyRendererDiff(e,t){for(const r in e.diff){if("visualVariables"!==r)return U.RecreateSymbol;if(!z(this._fastUpdates,t,this._vvConvertOptions))return U.RecreateSymbol;this._materials[0]?.setParameters(this._fastUpdates.materialParameters)}return U.FastUpdate}_getVertexData(e){let t=0;const r=e.paths,i=[],s=e.spatialReference,a=this._context.elevationProvider.spatialReference,o=this._context.renderCoordsHelper.spatialReference;for(const h of r)t+=h.length;const n=y(3*t);let l,c=0;for(const h of r){i.push({offset:c,numVertices:h.length});for(const t of h)n[c++]=t[0],n[c++]=t[1],n[c++]=e.hasZ?t[2]:0}return null==a||s.equals(a)||d(n,s,0,n,a,0,t)?(null==a||a.equals(o)?l=_(n):(l=y(3*t),d(n,a,0,l,o,0,t)),{pathVertexDataInfos:i,vertexDataES:n,vertexDataRS:l}):null}_createAs3DShape(e,t){const{graphic:a,renderingInfo:o}=e,n=a.geometry,l=this._getVertexData(n);if(null==l)return this.logger.warn("PathSymbol3DLayer geometry failed to be created (failed to project geometry to view spatial reference)"),null;if(0===l.pathVertexDataInfos.length)return 0!==n.paths.length&&n.paths.some((e=>e.length>0))||this.logger.warn("PathSymbol3DLayer geometry failed to be created (no paths were defined)"),null;const p=new Array,m=n.spatialReference,f=u(),d=this._context.renderCoordsHelper,y=new L(l.vertexDataES),_=a.uid,w=v(l.vertexDataRS.length);for(const u of l.pathVertexDataInfos){const e=u.numVertices;if(e<2)continue;const n=u.offset;if(null!=this._context.clippingExtent&&(g(l.vertexDataES,n,e,f),!b(f,this._context.clippingExtent)))continue;const v=new Array,x=n+3*e;for(let r=n;r<x;r+=3){y.offset=r;const e=j(y,this._context.elevationProvider,t,d);h(pe,l.vertexDataRS[r],l.vertexDataRS[r+1],l.vertexDataRS[r+2]),d.setAltitude(pe,e),l.vertexDataRS[r]=pe[0],l.vertexDataRS[r+1]=pe[1],l.vertexDataRS[r+2]=pe[2],v.push(ee(this._upVectorAlignment))}const P=new B(v,l.vertexDataES,l.vertexDataRS,n,w);oe(P,this._upVectorAlignment,this._context.renderCoordsHelper);const S=new F(P,this._profile,this._extruder,this._startCap,this._endCap);let C=null;if(this._fastUpdates){const e=this._fastUpdates.visualVariables,t=E(e.size?.field,a)??0,r=E(e.color?.field,a)??0,i=E(e.opacity?.field,a)??0;C=new K(S,t,r,i)}else{const e=c(this._intrinsicSize);if(this._drivenProperties.size){const t=o.size??["symbol-value","symbol-value","symbol-value"];e[0]*=ne(t[0],"symbol-value"===t[2]?this.symbolLayer.height||0:t[2],this.symbolLayer.width||0),e[1]*=ne(t[2],"symbol-value"===t[0]?this.symbolLayer.width||0:t[0],this.symbolLayer.height||0)}let t;if(this._drivenProperties.color&&(t=o.color??this._getFallbackOpacityAndColor()),this._drivenProperties.opacity){const e=o.opacity??this._getFallbackOpacityAndColor()[3];t=t?[t[0],t[1],t[2],e]:[1,1,1,e]}const r=new Q(S);r.bake(e),t&&r.bakeVertexColors(t),C=r}const D=C.createGeometryData(),V=this._context.stage.renderView.getObjectAndLayerIdColor({graphicUid:_,layerViewUid:this._context.layerViewUid}),A=new Z(this._materials[0],D,C,m,this._stencilWidth,V);A.transformation=r(s(),i,S.path.origin),p.push(A)}if(0===p.length)return null;const P=new G({geometries:p,layerViewUid:this._context.layerViewUid,graphicUid:_}),C=new S(this,P,null,((e,t,r,i,s)=>ce(e,t,i,s,this._upVectorAlignment)),t,null);return C.alignedSampledElevation=0,C.needsElevationUpdates=x(t.mode),C}_getFallbackOpacityAndColor(){const t=this.symbolLayer?.material?.color;return e.toUnitRGBA(t)??f}}function oe(e,t,r){const{origin:i,positions:s}=e;let a=e.offset;switch(t){default:case T.World:for(const t of e.vertices)pe[0]=s[a++]+i[0],pe[1]=s[a++]+i[1],pe[2]=s[a++]+i[2],r.worldUpAtPosition(pe,pe),t.setFrameFromUpVector(pe);break;case T.Path:pe[0]=s[a]+i[0],pe[1]=s[a+1]+i[1],pe[2]=s[a+2]+i[2],r.worldUpAtPosition(pe,pe),X(e,pe)}}function ne(e,t,r){switch(e){case"symbol-value":return r;case"proportional":return t;default:return e}}function le(e,t,r,i){let s=0;const{origin:a,vertices:o,positions:n,positionsES:l}=e,c=e.offset+3*o.length;for(let p=e.offset;p<c;p+=3)h(pe,l[p],l[p+1],l[p+2]),r(pe,me),s+=me.sampledElevation,pe[0]=n[p]+a[0],pe[1]=n[p+1]+a[1],pe[2]=n[p+2]+a[2],i.setAltitude(pe,me.z),n[p]=pe[0]-a[0],n[p+1]=pe[1]-a[1],n[p+2]=pe[2]-a[2];return e.updatePathVertexInformation(),s/o.length}function ce(e,t,r,i,s){const a=e.stageObject,o=a.geometries;let n=0;for(const l of o){if(!J(l))continue;const e=l.path,o=e.builder.path;n+=le(o,t,r,i),s!==T.World&&oe(o,s,i),e.onPathChanged(l),l.invalidateBoundingInfo(),a.geometryVertexAttributeUpdated(l,te.POSITION)}return n/o.length}function he(e){return 1===(e.material?.color?.a??1)}const pe=m(),me=new P;export{ae as Graphics3DPathSymbolLayer};